Open source USB echo demo

From DP

Revision as of 14:51, 8 May 2012 by Arakis (Talk | contribs)
Jump to: navigation , search

Contents

Overview

Here is a simple open source USB stack we use on our PIC24F and PIC18F projects. We've compiled a simple echo demo to help you get started. Download the package below.

Downloads

Basic hardware config

CONFIG words

As with each PIC there are CONFIG words that need to be setup to let the uC know in which stat it should operate. Examples for some of our project config words are contained in the confingwords.h file. Below is the example for PIC24F256GB106 located on the Bus Pirate v4.

_CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
_CONFIG2( IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_HS & FNOSC_PRIPLL & PLLDIV_DIV3 & IOL1WAY_ON & PLL_96MHZ_ON & DISUVREG_OFF)

In code Hardware setup

While the CONFIG words are programed in, further hardware setup need to be done, form inside the main function. This is done by calling the SetupBoard() function. Bellow is the function as it relates to the Bus Pirate hardware.

    INTCON1bits.NSTDIS = 1;
    volatile unsigned long delay = 0xffff;
    CLKDIV = 0x0000;    // Set PLL prescaler (1:1)
    CORCONbits.PSV = 1; // PSV initialisation
    PSVPAG = 0;         //
    OSCCONbits.SOSCEN = 0;
    AD1PCFGL = 0x7FD8; //BUSPIRATEV4 has five analog pins b0, b1, b2, b5, b15
    AD1PCFGH = 0x2;
    TRISBbits.TRISB10 = 0; // Let there be LEDS
    TRISBbits.TRISB8 = 0;
    TRISBbits.TRISB9 = 0;
    while (delay--);

This function sets up some interrupt options, the processor clock, and the analog and digital pinouts. At the end it delays for approximately 1s.

prj_usb_config.h Hardware deffinitions

    #define CDC_BUFFER_SIZE 64u
    #define CLOCK_FREQ 32000000
    #define BAUDCLOCK_FREQ 16000000 //  required for baud rate calculations
    #define UART_BAUD_setup(x)  U1BRG = x
    #define CDC_FLUSH_MS 4 // how many ms timeout before cdc in to host is sent

Within the prj_usb_config.h file are hardware definitions for some of our boards. The bare minumim required for the SB stack to function are the definitions listed above. The vaules are set for the Bus Pirate v4 hardware, so for other PIC they need to be changed.

Basic USB config

#define USB_VID (0x4d8)
#define USB_PID (0x000a)  // Microchip CDC 
#define USB_DEV 0x0002
 
#define USB_NUM_CONFIGURATIONS          1u
#define USB_NUM_INTERFACES              2u
#define USB_NUM_ENDPOINTS               3u
 
 
#define MAX_EPNUM_USED                  2u
 
#define USB_BUS_POWERED 1
#define USB_INTERNAL_TRANSCIEVER 1
#define USB_INTERNAL_PULLUPS 1
#define USB_INTERNAL_VREG 1
#define USB_FULL_SPEED_DEVICE 1
 
/* PingPong Buffer Mode
 * Valid values
 * 0 - No PingPong Buffers
 * 1 - PingPong on EP0
 * 2 - PingPong on all EP
 * 3 - PingPong on all except EP0
 */
#define USB_PP_BUF_MODE 0
#define USB_EP0_BUFFER_SIZE 8u
#define CDC_NOTICE_BUFFER_SIZE 10u

At the top of prj_usb_config.h file are basic USB configurations. This is where you can change the USB PID, VID, DEV etc.. In this file you can also define the hardware properties of the USB communication, such as pullups, self or bus powered etc.

USB setup

Polling

The stack supports both polling an interrupt driven USB communication. Located in the prj_usb_config.h are renaming definitions which are used by various functions through out the code.

 #define USB_INTERRUPTS //use interrupts instead of polling

By either commenting out or leaving the USB_INTERRUPTS statement above, you can chose weather you want to use USB by polling or through interrupts.

With polling the stack handles almost everything by itself, all you need to do is call the usb_handler function.

Interrupt

With interrupt driven communication some code needs to be added to the main.c

PIC24F

#pragma interrupt _USB1Interrupt
void __attribute__((interrupt, auto_psv)) _USB1Interrupt() {
    //USB interrupt
    //IRQ enable IEC5bits.USB1IE
    //IRQ flag    IFS5bits.USB1IF
    //IRQ priority IPC21<10:8>
    usb_handler();
    ClearGlobalUsbInterruptFlag();
}

This is the interrupt service routine. It calls the same usb_handler function the polling method does, and it clears the USB interrupt flags. While the two seam identical, interrupt driven communication is much more efficient, since the usb_handler function is called only when there is an USB event to handle, instead of being called all the time.

PIC18F

  • Insert explanation here

Bus Pirate v4

If you have Bus Pirate v4 there is a working example in our SVN.

  • project link
  • standalone hex
  • usb bootloader hex

Code for sending and receiving data

Here are 3 example of sending and receiving data from the USB.

Method 1

if (poll_getc_cdc(&RecvdByte))
  putc_cdc(RecvdByte+1);

Method 2

if (peek_getc_cdc(&RecvdByte)) {
  RecvdByte = getc_cdc();
  putc_cdc(RecvdByte+1);
}

Method 3

        if (poll_getc_cdc(&RecvdByte)) {
            putc_cdc(RecvdByte+1); //
            CDC_Flush_In_Now();
        }

Resources