Vous êtes sur la page 1sur 83

1.

LIBRERAS DEL USB

Las libreras que aqu aparecen son un ejemplo. Dependiendo de la clase (HID, MSD, GEN, BOOT o CDC) hay algunas variaciones. En rojo aparecen los datos que hay que cambiar en cada firmware. En azul las lneas que dependen de la clase. Y en verde la parte de la librera que es cdigo, aunque el texto en rojo y en azul tambin es cdigo. Para realizar una conexin sin caractersticas especficas, lo recomendable es utilizar la clase genrica (GEN) ya que permite una velocidad ms alta que la clase CDC, aunque esta ltima se utiliza por resultar ms fcil la programacin del host. Para ello se copian todas las libreras de esta clase que suministra Microchip y se modifican las lneas que aqu aparecen en rojo. Lo ms importante es definir bien las interfaces y los Endpoints. Para realizar una aplicacin en una clase determinada, lo ms sencillo es copiar todas las libreras de esa clase, corregirlas y modificar las libreras user.h y las aqu comentadas. Haciendo esto, nos evitamos tener que modificar el cdigo al cambiar la clase del dispositivo. Para ms informacin visitar la pgina web de microchip, en la que hay ejemplos de cada clase.

1.1.1.

USB.H

Esta librera proporciona la forma de incluir todos los archivos necesarios del firmware del USB de Microchip. En realidad, es la nica librera que hay que incluir en el programa de inicio, ya que se encarga de aadir las dems. El orden de inclusin es importante, ya que se resuelven los conflictos de dependencia con el orden correcto:
#include "autofiles\usbcfg.h" #include "system\usb\usbdefs\usbdefs_std_dsc.h" #include "autofiles\usbdsc.h" #include "system\usb\usbdefs\usbdefs_ep0_buff.h" #include "system\usb\usbmmap.h" #include "system\usb\usbdrv\usbdrv.h" #include "system\usb\usbctrltrf\usbctrltrf.h" #include "system\usb\usb9\usb9.h"

Si USB_USE_HID est definida se incluye la librera hid.h


#if defined(USB_USE_HID) #include "system\usb\class\hid\hid.h" #endif Ver autofiles\usbcfg.h

Documento creado por Slalen para Electronics Strange World

Si USB_USE_MSD est definida se incluye la librera msd.h


#if defined(USB_USE_MSD) #include "system\usb\class\msd\msd.h" #endif Ver autofiles\usbcfg.h

Si USB_USE_CDC est definida se incluye la librera cdc.h


#if defined(USB_USE_CDC) #include "system\usb\class\cdc\cdc.h" #endif Ver autofiles\usbcfg.h

Libreras C18 del USB

1.1.2.

USBCFG.H: CONFIGURACIN

Esta librera es la encargada de la configuracin del buffer por defecto, del Endpoint 0, de los Endpoints utilizados en la comunicacin Hay que modificarla en cada aplicacin.

1.1.2.1.

Definiciones

Tamao del buffer del Endpoint 0 (8, 16 32 64):


#define EP0_BUFF_SIZE 8

Nmero mximo de interrupciones:


#define MAX_NUM_INT 1

Definicin de parmetros descritos en usbdrv.h: Modo Ping-Pong:


#define MODE_PP _PPBM0

Valor de configuracin:
#define UCFG_VAL _PUEN|_TRINT|_FS|MODE_PP

E/S auto-alimentadas:
#define USE_SELF_POWER_SENSE_IO

E/S dependientes del bus USB:


#define USE_USB_BUS_SENSE_IO

Las dos definiciones anteriores se realizarn cuando sea necesario, siendo totalmente independiente una de la otra.

1.1.2.2.

Uso de la clase del dispositivo


Uso de la interfaz humana del dispositivo USB: #define USB_USE_HID Uso del CDC del dispositivo: #define USB_USE_CDC Uso de la clase Almacenamiento masivo: #define USB_USE_MSD

Dependiendo de la aplicacin hay que definir la clase que vamos a utilizar.

MUID = Microchip USB Clase ID Se utiliza para identificar la clase del USB de la sesin actual de control de la transferencia del EP0:
#define MUID_NULL #define MUID_USB9 #define MUID_HID #define MUID_CDC 0 1 2 3 Ninguna USB9 Interfaz humana Clase de comunicacin del dispositivo

1.1.2.3.

Distribucin de los Endpoint


0x00 UEP1 Identificacin de la interfaz Endpoints que se utlizan

#define HID_INTF_ID #define HID_UEP

Documento creado por Slalen para Electronics Strange World


#define #define #define #define HID_BD_OUT HID_INT_OUT_EP_SIZE HID_BD_IN HID_INT_IN_EP_SIZE ep1Bo 3 ep1Bi 3 1 50 Buffer descriptor de salida Tamao de la interrupcin del Endpoint de salida Buffer descriptor de entrada Tamao de la interrupcin del Endpoint de entrada Nmero de descriptores Tamao del informe

#define HID_NUM_OF_DSC #define HID_RPT01_SIZE

Macros HID
Ver la direccin del descriptor HID:
#define mUSBGetHIDDscAdr(ptr) { if(usb_active_cfg == 1) ptr = (rom byte*)&cfg01.hid_i00a00; }

Ver la direccin del informe del descriptor HID:


#define mUSBGetHIDRptDscAdr(ptr) { if(usb_active_cfg == 1) ptr = (rom byte*)&hid_rpt01; }

Ver el tamao del informe del descriptor HID:


#define mUSBGetHIDRptDscSize(count) { if(usb_active_cfg == 1) count = sizeof(hid_rpt01); }

Nmero mximo de Endpoints:


#define MAX_EP_NUMBER 1 //UEP1

Libreras C18 del USB

USBDEFS_STD_DSC.H: DESCRIPTORES:

1.1.3.

DEFINICIONES

ESTNDAR

DE

LOS

Mediante esta librara se crean las estructuras de los descriptores estndar, se definen constantes para realizar el cdigo ms rpidamente, etc. En general, no hay que modificar nada de la librera. En nuestra aplicacin copiaremos la que cede Microchip que corresponda con nuestra clase.

1.1.3.1. 1.1.3.2.

Incluye:
Librera en la que se definen tipos de datos

#include "system\typedefs.h"

Definiciones
0x01 0x02 0x03 0x04 0x05 Descriptor del dispositivo Descriptor de configuracin Descriptor de la secuencia Descriptor de la interfaz Descriptor del Endpoint

Tipos de descriptores:
#define DSC_DEV #define DSC_CFG #define DSC_STR #define DSC_INTF #define DSC_EP

Definicin de los Endpoint (slo usarse con los descriptores, para cualquier otro uso utilizar los definidos en usbdrv.h):
#define _EP01_OUT #define _EP01_IN #define _EP02_OUT #define _EP02_IN #define _EP03_OUT #define _EP03_IN #define _EP04_OUT #define _EP04_IN #define _EP05_OUT #define _EP05_IN #define _EP06_OUT #define _EP06_IN #define _EP07_OUT #define _EP07_IN #define _EP08_OUT #define _EP08_IN #define _EP09_OUT #define _EP09_IN #define _EP10_OUT #define _EP10_IN #define _EP11_OUT #define _EP11_IN #define _EP12_OUT #define _EP12_IN #define _EP13_OUT #define _EP13_IN 0x01 0x81 0x02 0x82 0x03 0x83 0x04 0x84 0x05 0x85 0x06 0x86 0x07 0x87 0x08 0x88 0x09 0x89 0x0A 0x8A 0x0B 0x8B 0x0C 0x8C 0x0D 0x8D

Documento creado por Slalen para Electronics Strange World


#define _EP14_OUT #define _EP14_IN #define _EP15_OUT #define _EP15_IN 0x0E 0x8E 0x0F 0x8F

Atributos de configuracin:
#define _DEFAULT #define _SELF #define _RWU 0x01<<7 0x01<<6 0x01<<5 Valor por defecto (El Bit 7 se activa) Auto-alimentado (Mantener si est activo) Reinicio remoto (Mantener si est activo)

Tipo de transferencia del Endpoint:


#define _CTRL #define _ISO #define _BULK #define _INT 0x00 0x01 0x02 0x03 Transferencia de control Transferencia sncrona Transferencia Bulk Transferencia interrupcin

Tipo de sincronizacin del Endpoint de transferencia sncrona:


#define _NS #define _AS #define _AD #define _SY 0x00<<2 0x01<<2 0x02<<2 0x03<<2 Sin sincronizacin Asncrona Adaptivo Sncrona

Utilizacin del Endpoint tipo sncrono:


#define _DE #define _FE #define _IE 0x00<<4 0x01<<4 0x02<<4 Endpoint de datos Endpoint retroalimentado Endpoint de datos y retroalimentado

1.1.3.3.

Estructuras

Estructura de los descriptores del dispositivo USB (ver usbdsc.c):


typedef struct _USB_DEV_DSC { Longitud; Tipo de descriptor; byte bLength; byte bDscType; Clase del dispositivo; Subclase del dispositivo; byte bDevCls; byte bDevSubCls; Tamao mximo del paquete; Identificador del fabricante; producto; byte bMaxPktSize0; word idVendor; Bcd del dsipositivo; Informacin de la manufactura; word bcdDevice; byte iMFR; Nmero de serie; Nmero de configuracin; byte iSerialNum; byte bNumCfg; } USB_DEV_DSC;

Bcd del USB; word bcdUSB; Protocolo del dispositivo; byte bDevProtocol; Identificacin del word idProduct; Informacin del producto; byte iProduct;

Estructura del descriptor de configuracin del USB:


typedef struct _USB_CFG_DSC { Longitud; Tipo de descriptor; byte bLength; byte bDscType; Nmero de interfaz; Valor de configuracin; configuracin;

Longitud total; word wTotalLength; Informacin de

Libreras C18 del USB


byte bNumIntf; Atributos; byte bmAttributes; } USB_CFG_DSC; byte bCfgValue; Mxima energa; byte bMaxPower; byte iCfg;

Estructura de la interfaz del dispositivo USB:


typedef struct _USB_INTF_DSC { Longitud; Tipo de descriptor; byte bLength; byte bDscType; Configuracin alterna; Nmero de Endpoints; byte bAltSetting; byte bNumEPs; Subclase de interfaz; Protocolo de la interfaz; byte bIntfSubCls; byte bIntfProtocol; } USB_INTF_DSC;

Nmero de interfaz; byte bIntfNum; Clase de interfaz; byte bIntfCls; Informacin de la interfaz; byte iIntf;

Estructura del Descriptor del Endpoint del USB:


typedef struct _USB_EP_DSC { Longitud; byte bLength; Atributos; byte bmAttributes; } USB_EP_DSC;

Tipo de descriptor; byte bDscType; Tamao mximo del paquete; word wMaxPktSize;

Direccin del Endpoint; byte bEPAdr; Intervalo; byte bInterval;

Documento creado por Slalen para Electronics Strange World

1.1.4.

USBDSC.H: DESCRIPTORES

Esta es una de las libreras ms importantes, ya que en ella se definen los descriptores. Como hemos visto anteriormente, los descriptores definen la interfaz, la clase, el fabricante, etc. Esta librera suele ser totalmente distinta en cada aplicacin.

1.1.4.1.

Libreras que incluye

#include "system\typedefs.h" #include "autofiles\usbcfg.h" #include "system\usb\usb.h"

1.1.4.2.

Definiciones
Configuracin 01 Descriptor de configuracin Descriptor de la interfaz Endpoint descriptor de salida Endpoint descriptor de entrada

#define CFG01 rom struct { USB_CFG_DSC cd01; USB_INTF_DSC i00a00; USB_EP_DSC ep01o_i00a00; USB_EP_DSC ep01i_i00a00; } cfg01

1.1.4.3.

Externas

extern rom USB_DEV_DSC device_dsc; extern CFG01; extern rom struct{byte bLength;byte bDscType;word string[1];}sd000;

Libreras C18 del USB

1.1.5. USBDEFS_EP0_BUFF.H: ENDPOINT 0

DESCRIPCIONES

DEL

BUFFER

DEL

La librera actual recopila las caractersticas del Endpoint 0 y de su buffer, no hay que modificarla ya que las variables se han declarado en otras libreras.

1.1.5.1.

Incluye

#include "system\typedefs.h" #include "autofiles\usbcfg.h"

Control de transferencias setup


Cada paquete setup tiene 8bytes. Sin embargo, el tamao del buffer del Endpoint 0 es el especificado en la librera usbcfg.h. El tamao del buffer puede ser de 8, 16, 32 64. Los primeros 8bytes se definen para direccionarse directamente para mejorar la velocidad y reducir el tamao del cdigo. El resto de bytes se direccionan indirectamente.
typedef union _CTRL_TRF_SETUP { Matriz para el direccionamiento indirecto struct { byte _byte[EP0_BUFF_SIZE]; }; Respuestas estndar del dispositivo struct { byte bmRequestType; byte bRequest; word wValue; word wIndex; word wLength; }; struct { unsigned :8; unsigned :8; WORD W_Value; WORD W_Index; WORD W_Length; }; struct { unsigned Recipient:5; unsigned RequestType:2; unsigned DataDir:1; unsigned :8;

Tipo de respuesta Respuesta Valor ndice Longitud

Valor ndice Longitud

Dispositivo, Interfaz, Endpoint, Otro Estndar, Clase, Fabricante, Reservado Host-al-dispositivo, Dispositivo-al-host

Documento creado por Slalen para Electronics Strange World


byte bFeature; unsigned :8; unsigned :8; unsigned :8; unsigned :8; unsigned :8; }; struct { unsigned :8; unsigned :8; byte bDscIndex; byte bDscType; word wLangID; unsigned :8; unsigned :8; }; struct { unsigned :8; unsigned :8; BYTE bDevADR; byte bDevADRH; unsigned :8; unsigned :8; unsigned :8; unsigned :8; }; struct { unsigned :8; unsigned :8; byte bCfgValue; byte bCfgRSD; unsigned :8; unsigned :8; unsigned :8; unsigned :8; }; struct { unsigned :8; unsigned :8; byte bAltID; byte bAltID_H; byte bIntfID; byte bIntfID_H; unsigned :8; unsigned :8; }; Reinicio remoto, Paro del Endpoint

Slo para configuracin y String del descriptor Dispositivo, Configuracin, String Identificacin de idioma

Direccin del dispositivo 0-127 Tiene que ser cero

Valor de configuracin 0-255 Tiene que ser cero (Reservado)

Valor alterno de configuracin 0-255 Tiene que ser cero Valor del nmero de interfaz 0-255 Tiene que ser cero

10

Libreras C18 del USB


struct { unsigned :8; unsigned :8; unsigned :8; unsigned :8; byte bEPID; byte bEPID_H; unsigned :8; unsigned :8; }; struct { unsigned :8; unsigned :8; unsigned :8; unsigned :8; unsigned EPNum:4; unsigned :3; unsigned EPDir:1; unsigned :8; unsigned :8; unsigned :8; }; } CTRL_TRF_SETUP;

Identificacin del Endpoint ID (Nmero y Direccin) Tiene que ser cero

Nmero del Endpoint 0-15 Direccin del Endpoint: 0-OUT, 1-IN

Control de transferencia de datos


typedef union _CTRL_TRF_DATA { Matriz para el direccionamiento indirecto: struct { byte _byte[EP0_BUFF_SIZE]; }; Los primeros 8bytes direccionables directamente: struct { byte _byte0; byte _byte1; byte _byte2; byte _byte3;

11

Documento creado por Slalen para Electronics Strange World


byte _byte4; byte _byte5; byte _byte6; byte _byte7; }; struct { word _word0; word _word1; word _word2; word _word3; }; } CTRL_TRF_DATA;

12

Libreras C18 del USB

1.1.6.

USBMMAP.H
Esta librera define constantes y estructuras utilizadas por otras.

El programador, salvo excepcin, no tiene que modificarla utilizndola tal y como aparece.

1.1.6.1. 1.1.6.2.

Incluye Definiciones
0x04 0x08 0x10 0x20 0x00 0x40 0x40 0x80 0x00 Parada del buffer activa Dato de sincronizacin activo Incremento de direccin desactivado Guardado del buffer descriptor por el SIE activo Paquete DATA0 esperando el siguiente Paquete DATA1 esperando el siguiente Mscara DTS El SIE controla el buffer La CPU controla el buffer

#include "system\typedefs.h"

Parmetros de inicializacin del descriptor del registro estado:


#define _BSTALL #define _DTSEN #define _INCDIS #define _KEN #define _DAT0 #define _DAT1 #define _DTSMASK #define _USIE #define _UCPU

Estados del dispositivo USB. Para utilizarlos con [byte usb_device_state]:


#define DETACHED_STATE #define ATTACHED_STATE #define POWERED_STATE #define DEFAULT_STATE #define ADR_PENDING_STATE #define ADDRESS_STATE #define CONFIGURED_STATE 0 1 2 3 4 5 6 Sin conexin Conectado Alimentado Por defecto Pendiente de direccin Direccionado Configurado

Tipos de memoria USB_DEVICE_STATUS:


#define _RAM 0 #define _ROM 1

para

el

control

de

transferencias,

utilizado

en

1.1.6.3.

Tipos
Estado del dispositivo

typedef union _USB_DEVICE_STATUS { byte _byte; struct

13

Documento creado por Slalen para Electronics Strange World


{ unsigned RemoteWakeup:1; unsigned ctrl_trf_mem:1; }; } USB_DEVICE_STATUS;

[0]Desactivado [1]Activado: Ver usbdrv.h, usb9.h [0]RAM [1]ROM

typedef union _BD_STAT { byte _byte; struct{ unsigned BC8:1; unsigned BC9:1; unsigned BSTALL:1; unsigned DTSEN:1; unsigned INCDIS:1; unsigned KEN:1; unsigned DTS:1; unsigned UOWN:1; }; struct{ unsigned BC8:1; unsigned BC9:1; unsigned PID0:1; unsigned PID1:1; unsigned PID2:1; unsigned PID3:1; unsigned :1; unsigned UOWN:1; }; struct{ unsigned :2; unsigned PID:4; unsigned :2; }; } BD_STAT; typedef union _BDT { struct { BD_STAT Stat; byte Cnt; byte ADRL; byte ADRH; }; struct { unsigned :8; unsigned :8;

Estado del buffer descriptor

Parada del buffer activa Dato de sincronizacin activo Incremento de direccin desactivado Guardado del buffer descriptor por el SIE activo Valor del dato de sincronizacin Propiedad del USB

Paquete de identificacin

Tabla del buffer descriptor

Direccin del buffer baja Direccin del buffer alta

14

Libreras C18 del USB


byte* ADR; }; } BDT; Direccin del Buffer

1.1.6.4.

Externas

extern byte usb_device_state; extern USB_DEVICE_STATUS usb_stat; extern byte usb_active_cfg; extern byte usb_alt_intf[MAX_NUM_INT]; extern volatile far BDT ep0Bo; extern volatile far BDT ep0Bi; extern volatile far BDT ep1Bo; extern volatile far BDT ep1Bi; extern volatile far BDT ep2Bo; extern volatile far BDT ep2Bi; extern volatile far BDT ep3Bo; extern volatile far BDT ep3Bi; extern volatile far BDT ep4Bo; extern volatile far BDT ep4Bi; extern volatile far BDT ep5Bo; extern volatile far BDT ep5Bi; extern volatile far BDT ep6Bo; extern volatile far BDT ep6Bi; extern volatile far BDT ep7Bo; extern volatile far BDT ep7Bi; extern volatile far BDT ep8Bo; extern volatile far BDT ep8Bi; extern volatile far BDT ep9Bo; extern volatile far BDT ep9Bi; extern volatile far BDT ep10Bo; extern volatile far BDT ep10Bi; extern volatile far BDT ep11Bo; extern volatile far BDT ep11Bi; extern volatile far BDT ep12Bo; extern volatile far BDT ep12Bi; extern volatile far BDT ep13Bo; extern volatile far BDT ep13Bi; extern volatile far BDT ep14Bo; extern volatile far BDT ep14Bi; extern volatile far BDT ep15Bo; extern volatile far BDT ep15Bi; Buffer descriptor del Endpoint #0 Out Buffer descriptor del Endpoint #0 In Buffer descriptor del Endpoint #1 Out Buffer descriptor del Endpoint #1 In Buffer descriptor del Endpoint #2 Out Buffer descriptor del Endpoint #2 In Buffer descriptor del Endpoint #3 Out Buffer descriptor del Endpoint #3 In Buffer descriptor del Endpoint #4 Out Buffer descriptor del Endpoint #4 In Buffer descriptor del Endpoint #5 Out Buffer descriptor del Endpoint #5 In Buffer descriptor del Endpoint #6 Out Buffer descriptor del Endpoint #6 In Buffer descriptor del Endpoint #7 Out Buffer descriptor del Endpoint #7 In Buffer descriptor del Endpoint #8 Out Buffer descriptor del Endpoint #8 In Buffer descriptor del Endpoint #9 Out Buffer descriptor del Endpoint #9 In Buffer descriptor del Endpoint #10 Out Buffer descriptor del Endpoint #10 In Buffer descriptor del Endpoint #11 Out Buffer descriptor del Endpoint #11 In Buffer descriptor del Endpoint #12 Out Buffer descriptor del Endpoint #12 In Buffer descriptor del Endpoint #13 Out Buffer descriptor del Endpoint #13 In Buffer descriptor del Endpoint #14 Out Buffer descriptor del Endpoint #14 In Buffer descriptor del Endpoint #15 Out Buffer descriptor del Endpoint #15 In

extern volatile far CTRL_TRF_SETUP SetupPkt; extern volatile far CTRL_TRF_DATA CtrlTrfData; #if defined(USB_USE_HID) Si est definido USB_USE_HID extern volatile far unsigned char hid_report_out[HID_INT_OUT_EP_SIZE]; extern volatile far unsigned char hid_report_in[HID_INT_IN_EP_SIZE]; #endif

15

Documento creado por Slalen para Electronics Strange World

1.1.7.

USBDRV.H: DRIVER DEL USB


Esta librera es la encargada de definir la configuracin inicial.

Lo nico que hay que modificar es la correccin de la errata en la original de Microchip, como se comenta ms adelante.

1.1.7.1.

Incluye

#include "system\typedefs.h" #include "system\usb\usb.h"

1.1.7.2.

Definiciones
0x00 0x01 0x02 0x00 0x04 0x00 0x08 0x10 0x40 0x80 Buffer Ping-pong Modo 0 Buffer Ping-pong Modo 1 Buffer Ping-pong Modo 2 Modo USB Low-Speed Modo USB Full-Speed Transmisor-receptor interno Transmisor-receptor externo Usar resistencias pull-up internas Usar el indicador de salida SIE Usar el test Patrn de ojo

Parmetros de configuracin iniciales:


#define _PPBM0 #define _PPBM1 #define _PPBM2 #define _LS #define _FS #define _TRINT #define _TREXT #define _PUEN #define _OEMON #define _UTEYE

Parmetros de los Endpoint iniciales:


#define EP_CTRL #define EP_OUT #define EP_IN #define EP_OUT_IN #define HSHK_EN sncronas 0x06 Pipe de control 0x0C Pipe de salida 0x0A Pipe de entrada 0x0E Pipe de entrada y salida 0x10 Activar paquetes de protocolo Los paquetes de protocolo se tienen que desactivar en la

Definiciones de los Endpoints PICmicro


El formato de la X:EP3:EP2:EP1:EP0:DIR:PPBI:X direccin de los EP PICmicro:

Esto se utiliza cuando se comprueba el valor ledo de la USTAT. NOTA: estas definiciones no se usan en los descriptores porque tienen distinto formato. Se definen en : "system\usb\usbdefs\usbdefs_std_dsc.h"

#define OUT #define IN

0 1 Nmero de mscara del Endpoint Direccin de la mscara del Endpoint

#define PIC_EP_NUM_MASK 0b01111000 #define PIC_EP_DIR_MASK 0b00000100

16

Libreras C18 del USB

NOTA: la librera tiene una errata en la definicin de los Endpoints, lo correcto es:
#define EP00_OUT #define EP00_IN #define EP01_OUT #define EP01_IN #define EP02_OUT #define EP02_IN #define EP03_OUT #define EP03_IN #define EP04_OUT #define EP04_IN #define EP05_OUT #define EP05_IN #define EP06_OUT #define EP06_IN #define EP07_OUT #define EP07_IN #define EP08_OUT #define EP08_IN #define EP09_OUT #define EP09_IN #define EP10_OUT #define EP10_IN #define EP11_OUT #define EP11_IN #define EP12_OUT #define EP12_IN #define EP13_OUT #define EP13_IN #define EP14_OUT #define EP14_IN #define EP15_OUT #define EP15_IN ((0x00<<3)|(OUT<<2)) ((0x00<<3)|(IN<<2)) ((0x01<<3)|(OUT<<2)) ((0x01<<3)|(IN<<2)) ((0x02<<3)|(OUT<<2)) ((0x02<<3)|(IN<<2)) ((0x03<<3)|(OUT<<2)) ((0x03<<3)|(IN<<2)) ((0x04<<3)|(OUT<<2)) ((0x04<<3)|(IN<<2)) ((0x05<<3)|(OUT<<2)) ((0x05<<3)|(IN<<2)) ((0x06<<3)|(OUT<<2)) ((0x06<<3)|(IN<<2)) ((0x07<<3)|(OUT<<2)) ((0x07<<3)|(IN<<2)) ((0x08<<3)|(OUT<<2)) ((0x08<<3)|(IN<<2)) ((0x09<<3)|(OUT<<2)) ((0x09<<3)|(IN<<2)) ((0x0A<<3)|(OUT<<2)) ((0x0A<<3)|(IN<<2)) ((0x0B<<3)|(OUT<<2)) ((0x0B<<3)|(IN<<2)) ((0x0C<<3)|(OUT<<2)) ((0x0C<<3)|(IN<<2)) ((0x0D<<3)|(OUT<<2)) ((0x0D<<3)|(IN<<2)) ((0x0E<<3)|(OUT<<2)) ((0x0E<<3)|(IN<<2)) ((0x0F<<3)|(OUT<<2)) ((0x0F<<3)|(IN<<2))

mInitializeUSBDriver()
Configura el modulo USB. La definicin de UCFG_VAL est en autofiles\usbcfg.h Este registro determina: velocidad del USB Speed, seleccin de las resistencias pull-up del chip, seleccin del transmisor-receptor del chip, modo de chequeo patrn de ojo, buffer modo Ping-pong

17

Documento creado por Slalen para Electronics Strange World


#define mInitializeUSBDriver() {UCFG = UCFG_VAL; usb_device_state = DETACHED_STATE; usb_stat._byte = 0x00; usb_active_cfg = 0x00; }

void mDisableEP1to15()
Esta macro desactiva todos los Endpoints menos el 0. Hay que invocar esta macro cada vez que el host enve una seal de RESET o una respuesta a SET_CONFIGURATION
#define mDisableEP1to15() ClearArray((byte*)&UEP1,15);

O lo que es lo mismo:
#define mDisableEP1to15() UEP1=0x00;UEP2=0x00;UEP3=0x00; UEP4=0x00;UEP5=0x00;UEP6=0x00;UEP7=0x00; UEP8=0x00;UEP9=0x00;UEP10=0x00;UEP11=0x00; UEP12=0x00;UEP13=0x00;UEP14=0x00;UEP15=0x00;

mUSBBufferReady(buffer_dsc)
Precondicin: Endpoint IN: El buffer est cargado y listo para enviar. Endpoint OUT: El buffer puede escribir al SIE. Entrada: byte buffer_dsc: Nombre del grupo del buffer descriptor (e.j. ep0Bo, ep1Bi) declarado en usbmmap.h. Los nombres se pueden cambiar por legibilidad; ver los ejemplos en usbcfg.h (#define HID_BD_OUT ep1Bo) Esta macro se tiene que llamar cada vez que ocurra: 1. Que se llene un buffer de un Endpoint, que no sea el EP0, con datos. 2. Que se lea un buffer de un Endpoint, que no sea el EP0. Esta macro convierte la propiedad del buffer al SIE para dar servicio; adems, cambia el bit DTS para sincronizacin.
#define mUSBBufferReady(buffer_dsc) { buffer_dsc.Stat._byte &= _DTSMASK; buffer_dsc.Stat.DTS = !buffer_dsc.Stat.DTS; buffer_dsc.Stat._byte |= _USIE|_DTSEN; }

Guarda slo el bit DTS Cambia el bit DTS Cambia la propiedad al SIE

1.1.7.3.

Prototipos pblicos

void USBCheckBusStatus(void); void USBDriverService(void); void USBRemoteWakeup(void); void USBSoftDetach(void); void ClearArray(byte* startAdr,byte count);

18

Libreras C18 del USB

1.1.8.

USBCTRLTRF.H: CONTROL DE TRANSFERENCIAS DEL USB

Esta librera es la encargada de definir los tipos de transferencia. Se utiliza desde otras libreras al declarar la interfaz, la transferecia, etc. No hay que modificarla

1.1.8.1. 1.1.8.2.

Incluye Definiciones
0 1 2 Espera Setup Transf. de control de transmisin Transf. de control de recepcin

#include "system\typedefs.h"

Estado de las transferencias de control


#define WAIT_SETUP #define CTRL_TRF_TX #define CTRL_TRF_RX

Tipos de Tokens:
#define SETUP_TOKEN #define OUT_TOKEN #define IN_TOKEN 0b00001101 0b00000001 0b00001001 Token setup Token de salida Token de entrada

Definicin de los tipos de respuesta:


#define HOST_TO_DEV #define DEV_TO_HOST #define STANDARD #define CLASS #define VENDOR #define RCPT_DEV #define RCPT_INTF #define RCPT_EP #define RCPT_OTH 0 1 0x00 0x01 0x02 0 1 2 3 Host-al-Dispositivo Dispositivo-al-Host Clase Fabricante Dispositivo destinatario Destinatario de la interfaz Destinatario del Endpoint

1.1.8.3.

Externas

extern byte ctrl_trf_session_owner; extern POINTER pSrc; extern POINTER pDst; extern WORD wCount;

1.1.8.4.

Prototipos pblicos

void USBCtrlEPService(void); void USBCtrlTrfTxService(void); void USBCtrlTrfRxService(void); void USBCtrlEPServiceComplete(void); void USBPrepareForNextSetupTrf(void);

19

Documento creado por Slalen para Electronics Strange World

1.1.9.

USB9.H

Gracias a esta librera obtenemos la direccin del dispositivo, entre otras caractersticas. No se tiene que modificar.

1.1.9.1. 1.1.9.2.

Incluye Definiciones
0 1 3 5 6 7 8 9 10 11 12 Obtiene estado Borra caracterstica Fija caracterstica Fija direccin Obtiene descriptor Fija descriptor Obtiene configuracin Fija configuracin Obtiene interfaz Fija interfaz Marco de sincronismo

#include "system\typedefs.h"

Cdigos de respuesta estndar:


#define GET_STATUS #define CLR_FEATURE #define SET_FEATURE #define SET_ADR #define GET_DSC #define SET_DSC #define GET_CFG #define SET_CFG #define GET_INTF #define SET_INTF #define SYNCH_FRAME

Caractersticas de los selectores estndar:


#define DEVICE_REMOTE_WAKEUP #define ENDPOINT_HALT 0x01 0x00 Reinicio remoto del dispositivo Paro del Endpoint

mUSBCheckAdrPendingState()
Rutina de chequeo especializado, comprueba si el dispositivo est en el estado Pendiente de direccin y le da servicio si est.
#define mUSBCheckAdrPendingState() if(usb_device_state==ADR_PENDING_STATE) { UADDR = SetupPkt.bDevADR._byte; if(UADDR > 0) usb_device_state=ADDRESS_STATE; else usb_device_state=DEFAULT_STATE; }

1.1.9.3.

Prototipos pblicos

void USBCheckStdRequest(void);

20

Libreras C18 del USB

1.1.10.

USBGEN.H: USB GENRICO

Esta es la librera de la clase genrica. Se definen las transferencias creando funciones para realizarlas. No hay que modificarla.

1.1.10.1. 1.1.10.2.

Incluye Definiciones

#include "system\typedefs.h"

(bit) mUSBGenRxIsBusy(void)
Esta macro se utiliza para comprobar que el Endpoint de salida est ocupado (lo controla el SIE) o no. Uso tpico: if(mUSBGenRxIsBusy())
#define mUSBGenRxIsBusy() USBGEN_BD_OUT.Stat.UOWN

(bit) mUSBGenTxIsBusy(void)
Esta macro se utiliza para comprobar que el Endpoint de entrada est ocupado (lo controla el SIE) o no. Uso tpico: if(mUSBGenTxIsBusy())
#define mUSBGenTxIsBusy() USBGEN_BD_IN.Stat.UOWN

byte mUSBGenGetRxLength(void)
Salida: mUSBGenGetRxLength devuelve usbgen_rx_len (longitude de Rx). mUSBGenGetRxLength se utiliza para recuperar el nmero de bytes copiados al buffer del usuario en la ltima llamada a la funcin USBGenRead.
#define mUSBGenGetRxLength() usbgen_rx_len

1.1.10.3. 1.1.10.4.

Externas Prototipos Pblicos

extern byte usbgen_rx_len;

void USBGenInitEP(void); void USBGenWrite(byte *buffer, byte len); byte USBGenRead(byte *buffer, byte len);

21

Documento creado por Slalen para Electronics Strange World

1.1.11.

MSD.H: ALMACENAMIENTO MASIVO

Esta es la librera de la clase MSD. Se definen las transferencias creando funciones para realizarlas. No hay que modificarla.

1.1.11.1.

Incluye
Mapa de pines E/S

#include "system\typedefs.h" #include "io_cfg.h"

1.1.11.2.

Definiciones
0x08

Cdigo de la clase de interfaz MSD:


#define MSD_INTF

Cdigo de la subclase de la interfas de clase MSD:


#define MSD_INTF_SUBCLASS 0x06

Cdigo de protocolo de la clase de la interfaz MSD:


#define MSD_PROTOCOL 0x50

Comandos de la clase:
#define MSD_RESET #define GET_MAX_LUN #define BLOCKLEN_512 #define STMSDTRIS #define STRUNTRIS #define STMSDLED #define STRUNLED #define ToggleRUNLED() 0xff 0xfe 0x0200 TRISD0 TRISD1 LATDbits.LATD0 LATDbits.LATD1 STRUNLED = !STRUNLED;

Set de commandos de cdigo de la subclase transparente SCSI:


#define INQUIRY #define READ_FORMAT_CAPACITY #define READ_CAPACITY #define READ_10 #define WRITE_10 #define REQUEST_SENSE #define MODE_SENSE #define PREVENT_ALLOW_MEDIUM_REMOVAL #define TEST_UNIT_READY #define VERIFY #define STOP_START 0x12 0x23 0x25 0x28 0x2A 0x03 0x1A 0x1E 0x00 0x2F 0x1B

Varios estados del Firmware de almacenamiento masivo:


#define MSD_WAIT 0 #define MSD_DATA_IN 2 #define MSD_DATA_OUT 3 Esperando para un CBW vlido Estado de datos IN (Dispositivo-> Host) Estado de datos OUT (Host -> Device)

22

Libreras C18 del USB


#define MSD_CSW_SIZE 0x0d #define MSD_CBW_SIZE 0x1f #define INVALID_CBW #define VALID_CBW #define MAX_LUN

Datos CSW de 10 bytes CSW Datos CSW de 31 bytes CBW

1 !INVALID_CBW 0

Clave de los cdigos de error Sense


#define S_NO_SENSE #define S_RECOVERED_ERROR #define S_NOT_READY #define S_MEDIUM_ERROR #define S_HARDWARE_ERROR #define S_ILLEGAL_REQUEST #define S_UNIT_ATTENTION #define S_DATA_PROTECT #define S_BLANK_CHECK #define S_VENDOR_SPECIFIC #define S_COPY_ABORTED #define S_ABORTED_COMMAND #define S_OBSOLETE #define S_VOLUME_OVERFLOW #define S_MISCOMPARE #define S_CURRENT #define S_DEFERRED 0x0 0x1 0x2 0x3 0X4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0x70 0x71

Cdigos ASC ASCQ para datos (slo el que vamos a utilizar) Con una respuesta de clave sense ilegal de un comando no soportado:
#define ASC_INVALID_COMMAND_OPCODE 0x20 #define ASCQ_INVALID_COMMAND_OPCODE 0x00

Con una respuesta de clave sense ilegal para probar si la unidad est disponible:
#define ASC_LOGICAL_UNIT_NOT_SUPPORTED 0x25 #define ASCQ_LOGICAL_UNIT_NOT_SUPPORTED 0x00

Con una clave sense Not ready


#define ASC_LOGICAL_UNIT_DOES_NOT_RESPOND 0x05 #define ASCQ_LOGICAL_UNIT_DOES_NOT_RESPOND 0x00 #define ASC_MEDIUM_NOT_PRESENT 0x3a #define ASCQ_MEDIUM_NOT_PRESENT 0x00 #define ASC_LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE 0x04 #define ASCQ_LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE 0x00

23

Documento creado por Slalen para Electronics Strange World


#define ASC_LOGICAL_UNIT_IN_PROCESS 0x04 #define ASCQ_LOGICAL_UNIT_IN_PROCESS 0x01 #define ASC_LOGICAL_UNIT_NOT_READY_INIT_REQD 0x04 #define ASCQ_LOGICAL_UNIT_NOT_READY_INIT_REQD 0x02 #define ASC_LOGICAL_UNIT_NOT_READY_INTERVENTION_REQD 0x04 #define ASCQ_LOGICAL_UNIT_NOT_READY_INTERVENTION_REQD 0x03 #define ASC_LOGICAL_UNIT_NOT_READY_FORMATTING 0x04 #define ASCQ_LOGICAL_UNIT_NOT_READY_FORMATTING 0x04 #define ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21 #define ASCQ_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x00 #define ASC_WRITE_PROTECTED 0x27 #define ASCQ_WRITE_PROTECTED 0x00

(bit) mMSDRxIsBusy(void)
Esta macro se utiliza para comprobar si el Endpoint MSD OUT est ocupado (controlado por el SIE) o no. Uso tpico: if(mMSDRxIsBusy())
#define mMSDRxIsBusy() MSD_BD_OUT.Stat.UOWN

(bit) mMSDTxIsBusy(void)
Esta macro se utiliza para comprobar si el Endpoint MSD IN est ocupado (controlado por el SIE) o no. Uso tpico: if(mMSDTxIsBusy())
#define mMSDTxIsBusy() MSD_BD_IN.Stat.UOWN

(bit) mMin(void)
Esta macro se utiliza para encontrar el menor de dos argumentos. Uso tpico: mMin(A, B)
#define mMin(A,B) (A<B)?A:B

1.1.11.3.

Estructuras
31 bytes totales CBW 55 53 42 43h Enviado por el host, el dispositivo se hace eco valor en CSW (asociado a CSW con CBW)

typedef struct _USB_MSD_CBW { dword dCBWSignature; dword dCBWTag; con el

24

Libreras C18 del USB


dword dCBWDataTransferLength; transferir byte bCBWFlags; bits 0 byte bCBWLUN; una byte bCBWCBLength; byte CBWCB[16]; } USB_MSD_CBW; typedef struct { escribir 10 byte Opcode; byte Flags; DWORD LBA; byte GroupNumber; WORD TransferLength; byte Control; } ReadWriteCB; typedef struct { byte Opcode; byte EVPD; byte PageCode; word AllocationLength; byte Control; } InquiryCB; typedef struct { byte Opcode; byte Reserved1; dword LBA; word Reserved2; byte PMI; byte Control; } ReadCapacityCB; typedef struct { byte Opcode; byte Desc; word Reserved; byte AllocationLength; byte Control; } RequestSenseCB; typedef struct { byte Opcode; Nmero de bytes de datos que el host espera Flags CBW, bit 7 = 0 salida de datos del hostdispositivo; bit 7=1 dispositivo-host, el resto de MS1bits son siempre cero, 0 en nuestro caso es sola unidad lgica MS3bits son cero Bloque de comando que ejecuta el dispositivo

/Bloque de comando para leer 10 (0x28) y (0x2a) comandos b7-b5 lectura protegida, b4 DPO, b3 FUA, b2 Reservado, b1 FUA_NV, b0 Obsoleto b4-b0 es el nmero de grupo el resto reservados

Formato del comando Inquiry slo b0 enable vital product data

capacidad de lectura 10

Bloque de direccin lgico Partial medium Indicator slo b0

Respuesta Sense 0x03

Modo Sense 0x1A

25

Documento creado por Slalen para Electronics Strange World


byte DBD; byte PageCode; cdigo Actualmente slo se utiliza b3 como bloque descriptor desactivado b7,b6 PC=pgina de control, b5-b0 pgina de Pgina de Control bits 00=> valor actual, 01=>valores modificables,10=>valor por defecto, 11=>valores guardados byte SubPageCode; byte AllocationLength; byte Control; } ModeSenseCB; typedef struct { byte Opcode; byte Reserved[3]; byte Prevent; byte Control; } PreventAllowMediumRemovalCB; typedef struct { byte Opcode; dword Reserved; byte Control; } TestUnitReadyCB; typedef struct { byte Opcode; byte VRProtect; dword LBA; byte GroupNumber; word VerificationLength; byte Control; } VerifyCB; typedef struct { byte Opcode; byte Immed; word Reserved; byte Start; byte Control; } StopStartCB; typedef struct _USB_MSD_CSW { dword dCSWSignature; dword dCSWTag; dword dCSWDataResidue; CSW 55 53 42 53h firma del paquete de CSW eco dCBWTag del paquete CBW diferencia en los datos esperados (dCBWDataTransferLength) y la cantidad actual procesada/enviada Prevenir el permiso de retirada del medio 0x1E

Slo se previenen b1-b0, el resto reservados

Unidad de prueba disponible 0x00

Verificar 10 Comando 0x2F b7-b5 VRProtect, b4 DPO, b3-b2,Reservado, b1 BYTCHK, b0 Obsoleto Nmero del grupo b4-b0, el resto reservado

STOP_START 0x1B

b7-b4 Condicin de energa, b3-b2 reservedo, b1 LOEJ, b0 Start

26

Libreras C18 del USB


byte bCSWStatus; } USB_MSD_CSW; typedef struct { byte Peripheral; byte Removble; byte Version; byte Response_Data_Format; 00h Comando aprobado, 01h Comando Fallido, 02h Error de fase, el resto obsoleto/reservado

byte AdditionalLength; byte Sccstp; byte bqueetc; byte CmdQue; char vendorID[8]; char productID[16]; char productRev[4]; } InquiryResponse; typedef struct { byte ModeDataLen; byte MediumType; unsigned Resv:4; unsigned DPOFUA:1; unsigned notused:2; unsigned WP:1; byte BlockDscLen; } tModeParamHdr;

Clasificador del perifrico:3; Perifrico_DevType:5; medio removible bit7 = 0 medio no removible, resto reservado versin b7,b6 Obsoleto, b5 Acceso de control coordinado, b4 direccionamiento jerrquico soportado b3:0 respuesta al formato de datos 2 indica que la respuesta esta en el formato definido por spec longitud en bytes de los datos que quedan de la indagacin estndar b7 SCCS, b6 ACC, b5-b4 TGPS, b3 3PC, b2-b1 Reservado, b0 Protegido b7 bque, b6- EncServ, b5-VS, b4-MultiP, b3-MChngr, b2-b1 Obsoleto, b0-Addr16 b7-b6 Obsoleto, b5-WBUS, b4-Sync, b3-Linked, b2 Obsoleto, b1 Cmdque, b0-VS

0 indica que no soporta los bits DPO y FUA 0 indica que no protege la escritura Longitud del Bloque Descriptor

Modo corto del bloque descriptor LBA (ver Pgina 1009, SBC-2)
typedef struct { byte NumBlocks[4]; byte Resv; byte BlockLen[3]; } tBlockDescriptor; /* Page_0 mode page format */ typedef struct { unsigned PageCode:6; unsigned SPF:1; SPC-3 7.4.5 SubPageFormat=0 medio Page_0 formato

reservado

27

Documento creado por Slalen para Electronics Strange World


unsigned PS:1; byte PageLength; byte ModeParam[]; } tModePage; typedef struct { tModeParamHdr Header; tBlockDescriptor BlockDsc; tModePage modePage; } ModeSenseResponse; Parmetros salvables si 2..n bytes del modo parmetro PageLength=n-1 modo parmetros

Formato fijado si el bit Desc de la respuesta sense CBW es 0


typedef union { struct { byte _byte[18]; }; struct { unsigned ResponseCode:7; unsigned VALID:1; byte Obsolete; unsigned SenseKey:4; unsigned Resv:1; unsigned ILI:1; unsigned EOM:1; unsigned FILEMARK:1; DWORD Information; byte AddSenseLen; DWORD CmdSpecificInfo; byte ASC; byte ASCQ; byte FRUC; byte SenseKeySpecific[3];

b6-b0 es el cdigo de respuesta fijado o el formato del descriptor Poner a 1 indica que el campo de informacin tiene un valor vlido Referencia SPC-3 Seccin 4.5.6 Indicador de la longitud incorrecta Fin del medio para los comandos READ y SPACE Tipo de dispositivo o comando especfico (SPC-33.1.18) Nmero de bytes sense adicionales que siguen <=244 depende del comando de la excepcin ocurrida cdigo sense adicional cdigo sense adicional seccin clasificada 4.5.2.1 SPC-3 SKSV son los msb de la clave sense especfica de campo vlido fijado=>SKS vlido. Los 18-n bytes sense adicionales se pueden definir ms tarde de respuesta sense de formato fijado

18bytes }; } RequestSenseResponse;

28

Libreras C18 del USB

1.1.11.4. 1.1.11.5.

Externas
declarado en sdcard.c

extern CSD gblCSDReg;

Prototipos pblicos

void USBCheckMSDRequest(void); void ProcessIO(void); void SDCardInit(void); void MSDInitEP(void);

29

Documento creado por Slalen para Electronics Strange World

1.1.12.

CDC.H: DISPOSITIVOS DE COMUNICACIN

Esta es la librera de la clase CDC. Se definen las transferencias creando funciones para realizarlas. No hay que modificarla.

1.1.12.1. 1.1.12.2.

Incluye Definiciones
0x00 0x01 0x02 0x03 0x04 0x20 0x21 0x22 0x23

#include "system\typedefs.h"

Repuesta de clase especfica:


#define SEND_ENCAPSULATED_COMMAND #define GET_ENCAPSULATED_RESPONSE #define SET_COMM_FEATURE #define GET_COMM_FEATURE #define CLEAR_COMM_FEATURE #define SET_LINE_CODING #define GET_LINE_CODING #define SET_CONTROL_LINE_STATE #define SEND_BREAK

Notificaciones Nota: las notificaciones se obtienen de la interface de comunicacin (Endpoint Interrupcin)


#define NETWORK_CONNECTION #define RESPONSE_AVAILABLE #define SERIAL_STATE 0x00 0x01 0x20

Cdigo de la clase del dispositivo:


#define CDC_DEVICE 0x02

Cdigo de la clase de la interfaz de comunicacin


#define COMM_INTF 0x02

Cdigo de la subclase de la interfaz de comunicacin


#define ABSTRACT_CONTROL_MODEL 0x02

Cdigo del protocolo de control de la clase de la interfaz de comunicacin


#define V25TER 0x01 Comandos comunes AT ("Hayes(TM)")

Cdigo de la clase de la interfaz de datos


#define DATA_INTF 0x0A

Cdigo del protocolo de la clase de la interfaz de datos


#define NO_PROTOCOL 0x00 No necesita un protrocolo de clase especfico

Cdigo selector de las caractersticas de la comunicacin


#define ABSTRACT_STATE 0x01

30

Libreras C18 del USB


#define COUNTRY_SETTING 0x02

Descriptores funcionales Tipos de valor del campo bDscType


#define CS_INTERFACE #define CS_ENDPOINT 0x24 0x25

bDscSubType en descriptores funcionales


#define DSC_FN_HEADER #define DSC_FN_CALL_MGT #define DSC_FN_ACM #define DSC_FN_DLM #define DSC_FN_TELEPHONE_RINGER #define DSC_FN_RPT_CAPABILITIES #define DSC_FN_UNION #define DSC_FN_COUNTRY_SELECTION #define DSC_FN_TEL_OP_MODES #define DSC_FN_USB_TERMINAL 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09

ACM Administracin de control abstracta DLM Direccin de lnea directa

Estados de tranferencia CDC Bulk IN


#define CDC_TX_READY #define CDC_TX_BUSY #define CDC_TX_BUSY_ZLP #define CDC_TX_COMPLETING 0 1 2 3

ZLP: Paquete de longitud cero

BOOL mUSBUSARTIsTxTrfReady(void)
Esta macro se utiliza para comprobar si la clase CDC est disponible para enviar mas datos. Uso tpico: if(mUSBUSARTIsTxTrfReady())
#define mUSBUSARTIsTxTrfReady() (cdc_trf_state == CDC_TX_READY)

(bit) mCDCUsartRxIsBusy(void)
Esta macro se utiliza para comprobar si el Endpoint CDC Bulk OUT est ocupado (controlado por el SIE) o no. Uso tpico: if(mCDCUsartRxIsBusy())
#define mCDCUsartRxIsBusy() CDC_BULK_BD_OUT.Stat.UOWN

(bit) mCDCUsartTxIsBusy(void)
Esta macro se utiliza para comprobar si el Endpoint CDC Bulk IN est ocupado (controlado por el SIE) o no.

31

Documento creado por Slalen para Electronics Strange World Uso tpico: if(mCDCUsartTxIsBusy())
#define mCDCUsartTxIsBusy() CDC_BULK_BD_IN.Stat.UOWN

byte mCDCGetRxLength(void)
Salida: devuelve cdc_rx_len mCDCGetRxLength se utiliza para recuperar el nmero de bytes que se han copiado al buffer del usuario en la ltima llamada a la funcin getsUSBUSART.
#define mCDCGetRxLength() cdc_rx_len

void mUSBUSARTTxRam(byte *pData, byte len)


Precondicin: cdc_trf_state tiene que estar en el estado CDC_TX_READY. El valor de len tiene que se igual o menor de 255bytes. Entrada: pDdata: Puntero al comienzo de la localizacin de los bytes de datos. len: nmero de bytes que se van a transferir. Esta macro se utiliza para transferir datos localizados en la memoria de datos. Utilizar esta macro cuando: 1. La longitud de la transferencia se conoce 2. Los datos no terminan con uno nulo Nota: Esta macro slo manipula la transferencia setup. La transferencia actual la manipula CDCTxService().
#define mUSBUSARTTxRam(pData,len) { pCDCSrc.bRam = pData; cdc_tx_len = len; cdc_mem_type = _RAM; cdc_trf_state = CDC_TX_BUSY; }

void mUSBUSARTTxRom(rom byte *pData, byte len)


Precondicin: cdc_trf_state tiene que estar en el estado CDC_TX_READY. El valor de len tiene que se igual o menor de 255bytes. Entrada: pDdata: Puntero al comienzo de la localizacin de los bytes de datos. len: nmero de bytes que se van a transferir. Esta macro se utiliza para transferir datos localizados en la memoria de programa. Utilizar esta macro cuando: 3. La longitud de la transferencia se conoce 4. Los datos no terminan con uno nulo Nota: Esta macro slo manipula la transferencia setup. La transferencia actual la manipula CDCTxService().

32

Libreras C18 del USB


#define mUSBUSARTTxRom(pData,len) { pCDCSrc.bRom = pData; cdc_tx_len = len; cdc_mem_type = _ROM; cdc_trf_state = CDC_TX_BUSY; }

1.1.12.3.

Estructuras
0x07

Estructura de la lnea de codificacin


#define LINE_CODING_LENGTH typedef union _LINE_CODING { struct { byte _byte[LINE_CODING_LENGTH]; }; struct { DWORD byte byte byte }; } LINE_CODING;

dwDTERate; Estructura de datos compleja bCharFormat; bParityType; bDataBits;

typedef union _CONTROL_SIGNAL_BITMAP { byte _byte; struct { unsigned DTE_PRESENT; [0] No Presente [1] Presente unsigned CARRIER_CONTROL; [0] Desactiva [1] Activa }; } CONTROL_SIGNAL_BITMAP;

Descriptor de cabecera funcional


typedef struct _USB_CDC_HEADER_FN_DSC { byte bFNLength; byte bDscType; byte bDscSubType; word bcdCDC; } USB_CDC_HEADER_FN_DSC;

Descriptor funcional de direccin de control abstracto


typedef struct _USB_CDC_ACM_FN_DSC

33

Documento creado por Slalen para Electronics Strange World


{ byte bFNLength; byte bDscType; byte bDscSubType; byte bmCapabilities; } USB_CDC_ACM_FN_DSC;

Descriptor funcional de unin


typedef struct _USB_CDC_UNION_FN_DSC { byte bFNLength; byte bDscType; byte bDscSubType; byte bMasterIntf; byte bSaveIntf0; } USB_CDC_UNION_FN_DSC;

Descriptor funcional de control de llamadas


typedef struct _USB_CDC_CALL_MGT_FN_DSC { byte bFNLength; byte bDscType; byte bDscSubType; byte bmCapabilities; byte bDataInterface; } USB_CDC_CALL_MGT_FN_DSC;

1.1.12.4.

Externas

extern byte cdc_rx_len; extern byte cdc_trf_state; extern POINTER pCDCSrc; extern byte cdc_tx_len; extern byte cdc_mem_type;

1.1.12.5.

Prototipos publicos

void USBCheckCDCRequest(void); void CDCInitEP(void); byte getsUSBUSART(char *buffer, byte len); void putrsUSBUSART(const rom char *data); void putsUSBUSART(char *data); void CDCTxService(void); #endif CDC_H

34

Libreras C18 del USB

1.1.13.

HID.H: DISPOSITIVO INTERFAZ CON HUMANOS

Esta es la librera de la clase HID. Se definen las transferencias creando funciones para realizarlas. No hay que modificarla.

1.1.13.1. 1.1.13.2.

Incluye Definiciones
0x01 0x02 0x03 0x09 0x0A 0x0B Obtener informe Obtener reposo Obtener protocolo Fijar informe Fijar reposo Fijar protocolo

#include "system\typedefs.h"

Repuestas de clase especficas:


#define GET_REPORT #define GET_IDLE #define GET_PROTOCOL #define SET_REPORT #define SET_IDLE #define SET_PROTOCOL

Tipos de clase de descriptor:


#define DSC_HID #define DSC_RPT #define DSC_PHY 0x21 0x22 0x23 Descriptor HID Descriptor informe

Seleccin de protocolo:
#define BOOT_PROTOCOL #define RPT_PROTOCOL 0x00 0x01 Protocolo de inicio Informe de protocolo

Cdigo de clase de interfaz HID:


#define HID_INTF 0x03 Interfaz HID

Cdigo de subclase de interfaz HID:


#define BOOT_INTF_SUBCLASS 0x01

Cdigo de protocolo de clase de interfaz:


#define HID_PROTOCOL_NONE #define HID_PROTOCOL_KEYBOAD #define HID_PROTOCOL_MOUSE 0x00 0x01 0x02 Ninguno Teclado Ratn

(bit) mHIDRxIsBusy()
Esta macro comprueba si el Endpoint de salida del HID est ocupado (controlado por el SIE) o no. Aplicacin tpica: if(mHIDRxIsBusy())

35

Documento creado por Slalen para Electronics Strange World


#define mHIDRxIsBusy() HID_BD_OUT.Stat.UOWN

(bit) mHIDTxIsBusy()
Esta macro comprueba si el Endpoint de entrada del HID est coupado (controlado por el SIE) o no. Aplicacin tpica: if(mHIDTxIsBusy())
#define mHIDTxIsBusy() HID_BD_IN.Stat.UOWN

byte mHIDGetRptRxLength()
Salida: mHIDGetRptRxLength devuelve un informe de la longitud del receptor HID (hid_rpt_rx_len). La mHIDGetRptRxLength se utiliza para recuperar el nmero de bytes copindolos al buffer de usuario en orden de la ltima llamada a la funcin HIDRxReport.
#define mHIDGetRptRxLength() hid_rpt_rx_len

1.1.13.3.

Estructuras

typedef struct _USB_HID_DSC_HEADER Cabecera del descriptor HID { byte bDscType; Tipo de descriptor word wDscLength; Longitud del descriptor } USB_HID_DSC_HEADER; typedef struct _USB_HID_DSC Descriptor HID { Longitud Tipo de descriptor Bcd del HID byte bLength; byte bDscType; word bcdHID; Cdigo de territorio Nmero del descriptor byte bCountryCode; byte bNumDsc; USB_HID_DSC_HEADER hid_dsc_header[HID_NUM_OF_DSC]; HID_NUM_OF_DSC se define en autofiles\usbcfg.h } USB_HID_DSC;

1.1.13.4.

Externas

extern byte hid_rpt_rx_len;

1.1.13.5.

Prototipos pblicos

void HIDInitEP(void); void USBCheckHIDRequest(void); void HIDTxReport(char *buffer, byte len); byte HIDRxReport(char *buffer, byte len);

1.1.14.

IO_CFG.H

En esta librera se definen los puertos utilizados en la aplicacin USB.

36

Libreras C18 del USB Si no se desea incluir hay que definir el apartado del USB ya que si no, la compilacin dara un error al no definir los puertos Bus Sense y Power Sense.

1.1.14.1. 1.1.14.2.

Incluye Tris
1 0

#include "autofiles\usbcfg.h"

#define INPUT_PIN #define OUTPUT_PIN

1.1.14.3.

USB
TRISAbits.TRISA1 entrada

#define tris_usb_bus_sense

#if defined(USE_USB_BUS_SENSE_IO) #define usb_bus_sense PORTAbits.RA1 #else #define usb_bus_sense 1 #endif #define tris_self_power TRISAbits.TRISA2 entrada

#if defined(USE_SELF_POWER_SENSE_IO) #define self_power PORTAbits.RA2 #else #define self_power 1 #endif

Interfaz del transmisor externo


#define tris_usb_vpo #define tris_usb_vmo #define tris_usb_rcv #define tris_usb_vp #define tris_usb_vm #define tris_usb_oe #define tris_usb_suspnd TRISBbits.TRISB3 TRISBbits.TRISB2 TRISAbits.TRISA4 TRISCbits.TRISC5 TRISCbits.TRISC4 TRISCbits.TRISC1 TRISAbits.TRISA3 Salida Salida Entrada Entrada Entrada Salida Salida

1.1.14.4.

LED
LATD &= 0xF0; TRISD &= 0xF0; LATDbits.LATD0 LATDbits.LATD1 LATDbits.LATD2 LATDbits.LATD3 mLED_1 = 1; mLED_2 = 1; mLED_3 = 1; mLED_4 = 1; mLED_1 = 0; mLED_2 = 0;

#define mInitAllLEDs() #define mLED_1 #define mLED_2 #define mLED_3 #define mLED_4 #define mLED_1_On() #define mLED_2_On() #define mLED_3_On() #define mLED_4_On() #define mLED_1_Off() #define mLED_2_Off()

37

Documento creado por Slalen para Electronics Strange World


#define mLED_3_Off() #define mLED_4_Off() #define mLED_1_Toggle() #define mLED_2_Toggle() #define mLED_3_Toggle() #define mLED_4_Toggle() mLED_3 = 0; mLED_4 = 0; mLED_1 = !mLED_1; mLED_2 = !mLED_2; mLED_3 = !mLED_3; mLED_4 = !mLED_4;

1.1.14.5.

Interruptores
TRISBbits.TRISB4=1;TRISBbits.TRISB5=1; TRISBbits.TRISB4=1; TRISBbits.TRISB5=1; PORTBbits.RB4 PORTBbits.RB5

#define mInitAllSwitches() #define mInitSwitch2() #define mInitSwitch3() //#define sw2 #define sw3

1.1.14.6.

Potencimetro

#define mInitPOT() TRISAbits.TRISA0=1;ADCON0=0x01;ADCON2=0x3C;

1.1.14.7.

SPI: Lneas de Chip Select


Salida Salida

#define tris_cs_temp_sensor TRISBbits.TRISB2 #define cs_temp_sensor LATBbits.LATB2 #define tris_cs_sdmmc TRISBbits.TRISB3 #define cs_sdmmc LATBbits.LATB3

1.1.14.8.

SDMMC
TRISBbits.TRISB4 PORTBbits.RB4 TRISAbits.TRISA4 PORTAbits.RA4 Entrada Entrada

#define TRIS_CARD_DETECT #define CARD_DETECT #define TRIS_WRITE_DETECT #define WRITE_DETECT

38

Libreras C18 del USB

1.1.15.

INTERRUPT.H

En esta librera se incluye todo lo referente a las interrupciones. El usuario la modificar dependiendo de la aplicacin.

1.1.15.1. 1.1.15.2. 1.1.15.3.

Incluye Definiciones Prototipos

#include "system\typedefs.h"

#define mEnableInterrupt() INTCONbits.GIE = 1;

void low_isr(void); void high_isr(void);

39

Documento creado por Slalen para Electronics Strange World

1.1.16. USB_COMPILE_TIME_VALIDATION.H: VALIDACIN DEL TIEMPO DE COMPILADO


Esta librera se utiliza para comprobar errores en la compilacin. Es totalmente opcional.

1.1.16.1.

Incluye

#include "system\typedefs.h" #include "system\usb\usb.h"

1.1.16.2.
#if

Validacin del USB

(EP0_BUFF_SIZE != 8) && (EP0_BUFF_SIZE != 16) && (EP0_BUFF_SIZE != 32) && (EP0_BUFF_SIZE != 64) #error(Tamao del buffer del Endpoint 0 incorrecto, comprueba "autofiles\usbcfg.h") #endif #if defined(HID_INT_OUT_EP_SIZE) #if (HID_INT_OUT_EP_SIZE > 64) #error(El tamao del Endpoint de salida de HID no puede ser mayor de 64, comprueba "autofiles\usbcfg.h") #endif #endif #ifdef HID_INT_IN_EP_SIZE #if (HID_INT_IN_EP_SIZE > 64) #error(El tamao del Endpoint de entrada de HID no puede ser mayor de 64, comprueba "autofiles\usbcfg.h") #endif #endif

1.2.

LIBRERAS DEL MICROPROCESADOR

Al instalar el compilador MPLAB C18 se crea una carpeta llamada lkr, en la cual hay unos archivos que se pueden aadir al proyecto. Estos archivos definen todos los puertos, registros, bits del microprocesador que utilicemos en el proyecto. Es recomendable aadir este archivo ya que todas las libreras trabajan con las definiciones hechas en l.

40

Libreras C18 del USB

2.

MACROS DEL COMPILADOR C18

Una macro es un conjunto de funciones declaradas en un programa. Se declaran por ser funciones muy utilizadas para ahorrar tiempo al programar. Para poder trabajar con las funciones definidas en las macros, hay que definir las libreras. En stas hay un apartado llamado prototipos pblicos en los que se declara la macro como funcin. Las macros que no aparecen en el apartado de prototipos pblicos, son funciones internas que no se pueden llamar desde otro archivo. En este punto se comentan las macros de Microchip relativas al puerto USB. Como en las libreras, aparecen en rojo los datos que hay que modificar en cada aplicacin, en azul los referentes a la clase y en verde todo el cdigo fuente.

2.1.

USBDRV.C: DRIVERS USB

En este archive el fabricante ha creado el cdigo relativo a la comunicacin inicial. En el cual se declaran los estados del USB, los comprueba y determina en cual est la aplicacin.

2.1.1.

INCLUYE

#include <p18cxxx.h> #include "system\typedefs.h" #include "system\usb\usb.h" #include "io_cfg.h"

Se necesita para USBCheckBusStatus()

2.1.2. 2.1.3.

VARIABLES PROTOTIPOS PRIVADOS

#pragma udata

void USBModuleEnable(void); void USBModuleDisable(void); void USBSuspend(void); void USBWakeFromSuspend(void); void USBProtocolResetHandler(void); void USB_SOF_Handler(void); void USBStallHandler(void); void USBErrorHandler(void);

2.1.4. 2.1.4.1.

DECLARACIONES void USBCheckBusStatus(void)

#pragma code

Esta rutina activa/desactiva el mdulo USB comprobado la seal de energa.

41

Documento creado por Slalen para Electronics Strange World


void USBCheckBusStatus(void) {

Deteccin de la conexin/desconexin del bus usb_bus_sense es un puerto de E/S definido en io_cfg.h


#define USB_BUS_ATTACHED #define USB_BUS_DETACHED 1 0 Est el USB conectado? Est el mdulo apagado? Est apagado, actvalo

if(usb_bus_sense == USB_BUS_ATTACHED) { if(UCONbits.USBEN == 0) USBModuleEnable(); } else { if(UCONbits.USBEN == 1) USBModuleDisable(); } end if(usb_bus_sense...)

Est el mdulo encendido? Est encendido, desactvalo

Despus de activar el modulo USB, hay un retardo para que la tensin de las lneas D+ o D- se pongan en alto lo suficiente para que salga de la condicin SE0. La interrupcin de Reset del USB tiene que estar enmascarada hasta que la condicin SE0 est borrada. Esto ayuda a prevenir que el firmware confunda este evento con un reset del host.
if(usb_device_state == ATTACHED_STATE) { if(!UCONbits.SE0) { UIR = 0; UIE = 0; USB UIEbits.URSTIE = 1; UIEbits.IDLEIE = 1; usb_device_state = POWERED_STATE; } end if borrado } end if(usb_device_state == ATTACHED_STATE) } end USBCheckBusStatus

Borra todas las interrupciones del USB Enmascara todas las interrupciones del Desenmascara la interrupcin RESET Desenmascara la interrupcin IDLE Lo dems espera hasta que SE0 est

2.1.4.2.

void USBModuleEnable(void)

Esta rutina activa el mdulo USB. Slo se puede llamar esta rutina desde USBCheckBusStatus().
void USBModuleEnable(void) { UCON = 0;

42

Libreras C18 del USB


UIE = 0; UCONbits.USBEN = 1; usb_device_state = ATTACHED_STATE; } end USBModuleEnable Enmascara todas las interrupciones USB Activa el modulo y une el bus Definido en usbmmap.c y .h

2.1.4.3.

void USBModuleDisable(void)

Esta rutina desactiva el modulo USB. Slo se puede llamar esta rutina desde USBCheckBusStatus().
void USBModuleDisable(void) { UCON = 0; bus UIE = 0; usb_device_state = DETACHED_STATE; } end USBModuleDisable

Desactiva el modulo y desconecta del Enmascara todas las interrupciones USB Definido en usbmmap.c y .h

2.1.4.4.

void USBSoftDetach(void)

Efectos secundarios: El dispositivo se tiene que reenumerar. USBSoftDetach desconecta elctricamente el dispositivo del bus. Se utiliza para dejar de suministrar tensin VUSB a las resistencias pull-up. Las resistencias pull-down en el lado del host pondrn las seales diferenciales en bajo y el host registrar el evento como una desconexin. Como el cable USB no se desconecta fsicamente, la energa suministrada a travs de l la puede detectar el dispositivo. Cuando se llame la funcin USBCheckBusStatus(), se reconectar el dispositivo al bus.
void USBSoftDetach(void) { USBModuleDisable(); } end USBSoftDetach

2.1.4.5.

void USBDriverService(void)

Esta rutina es el corazn del firmware. Controla las interrupciones USB. Nota: Las transiciones de estado del dispositivo son las siguientes: Desconectado->Conectado->Alimentado->Por defecto->Pendiente de direccin> ->Direccionado->Configurado->Listo
void USBDriverService(void) { Punto para continuar dando servicio si el cable del USB no est unido. if(usb_device_state == DETACHED_STATE) return;

Tarea A: Servicio de la interrupcin de actividad


if(UIRbits.ACTVIF && UIEbits.ACTVIE) USBWakeFromSuspend();

43

Documento creado por Slalen para Electronics Strange World


Punto para continuar dando servicio si el dispositivo est en modo suspendido. if(UCONbits.SUSPND==1) return;

Tarea B: Servicio de la Interrupcin Reset del Bus. Cuando se recibe un reset del bus durante el modo suspendido, lo primero hay que activar ACTVIF, una vez que UCONbits.SUSPND est borrado, entonces el bit URSTIF se reafirmar. Esto es porque URSTIF se chequea despus de ACTVIF. El flag de reset USB se enmascara cuando el USB est en estado desconectado o conectado, por lo que no se puede provocar un estado de reset del USB en estos dos estados.
if(UIRbits.URSTIF && UIEbits.URSTIE) USBProtocolResetHandler();

Tarea C: Servicio de otras interrupciones.


if(UIRbits.IDLEIF && UIEbits.IDLEIE) USBSuspend(); if(UIRbits.SOFIF && UIEbits.SOFIE) USB_SOF_Handler(); if(UIRbits.STALLIF && UIEbits.STALLIE) USBStallHandler(); if(UIRbits.UERRIF && UIEbits.UERRIE) USBErrorHandler(); Punto para continuar dando servicio si el bus no ha enviado un reset del bus. Al recibir el reset del bus, el dispositivo cambia al estado por defecto y est listo para comunicarse. if(usb_device_state < DEFAULT_STATE) return;

Tarea D: Servicio de una interrupcin de transaccin completa


if(UIRbits.TRNIF && UIEbits.TRNIE) { USBCtrlEPService slo maneja las transacciones del EP0, ignora todas las transacciones de los otros EP. USBCtrlEPService(); Los dems Endpoint se pueden determinar despus respondiendo a la clase del firmware. Cada driver del dispositivo sabe cuando una transaccin OUT o IN est disponible comprobando el bit de propiedad del buffer. Un EP OUT lo debe controlar siempre el SIE hasta que el dato est disponible. Un EP IN lo debe controlar siempre la CPU hasta que el dato est disponible. Por esta lgica, no es necesario guardar el valor de USTAT de una transaccin de un Endpoint distinto del 0 (non-EP0). UIRbits.TRNIF = 0; } end if(UIRbits.TRNIF && UIEbits.TRNIE) } end USBDriverService

2.1.4.6.

void USBSuspend(void)

void USBSuspend(void) { Nota: No borrar UIRbits.ACTVIF aqu Razn: ACTVIF slo se genera si IDLEIF se ha generado. Es un ratio de generacin de interrupcin de 1:1. Por cada IDLEIF, habr slo un ACTVIF sea cual sea el nmero de transacciones en el bus. Si el ACTIF se borra aqu, puede ocurrir un problema cuando: [ IDLE ][bus activity -> <--- 3 ms -----> ^ ^ ACTVIF=1

44

Libreras C18 del USB


IDLEIF=1 # # # # (#=Banderas de programa de interrogacin) ^ Este ciclo de pregunta mira IDLEIF=1 y ACTVIF=1. Sin embargo, el programa sirve primero IDLEIF porque ACTIVIE=0. Si esta rutina borra el nico ACTIVIF, puede que no salga nunca del modo suspendido. UIEbits.ACTVIE = 1; Activa las interrupciones del bus UIRbits.IDLEIF = 0; UCONbits.SUSPND = 1; Pone el modulo USB en el modo reserva de energa, el reloj SIE inactivo. En este punto el PIC puede ponerse en sleep, reposo, cambiar a un reloj ms lento, etc. /* Seccin modificable */ /* Final de la seccin modificable */ } end USBSuspend

2.1.4.7.

void USBWakeFromSuspend(void)

void USBWakeFromSuspend(void) { Si se cambia la frecuencia de reloj, en este lugar se vuelve a poner la frecuencia original. UCONbits.SUSPND = 0; UIEbits.ACTVIE = 0; UIRbits.ACTVIF = 0; } end USBWakeFromSuspend

2.1.4.8.

void USBRemoteWakeup(void)

Esta funcin la tiene que llamar el usuario cuando el dispositivo se despierte por un estmulo externo que no sea ACTIVIF. Nota: La seccin modificable en esta rutina se puede cambiar dependiendo de las especificaciones de la aplicacin. La implementacin actual bloquea temporalmente otras funciones de ejecucin en un periodo de 1-13ms dependiendo de la frecuencia del ncleo. De acuerdo con las especificaciones del USB 2.0 en la seccin 7.1.7.7, El reinicio remoto del dispositivo tiene que bloquear la seal al menos por 1ms y no ms de 15ms. La idea aqu es utilizar un retraso por contador, usando un valor comn que pueda trabajar con un gran rango de frecuencias del ncleo. Este valor es 1800. Ver la tabla de debajo:
Frec del ncleo (MHz) 48 4 MIP 12 1 Periodo seal RESUME (ms) 1,05 12,6

Estos tiempos pueden ser distintos si se utiliza la optimizacin o el cdigo de instrucciones entendido o cuando se tiene otra interrupcin activa. Asegurarse usando del Stopwatch del MPLAB SIM.
void USBRemoteWakeup(void) {

45

Documento creado por Slalen para Electronics Strange World


static word delay_count; if(usb_stat.RemoteWakeup == 1) funcin { USBWakeFromSuspend(); UCONbits.RESUME = 1; /* Seccin modificable */ Comprueba si el host a activado la reinicio remoto Reinicio del modo suspendido Comienzo de la seal RESUME

/* Final de la seccin modificable */ UCONbits.RESUME = 0; } endif } end USBRemoteWakeup

2.1.4.9.

void USB_SOF_Handler(void)

El host enva un paquete SOF a los dispositivos cada milisegundo. Esta interrupcin puede ser til en las pipes sncronas. Los diseadores pueden implementar una rutina de realimentacin como necesite.
void USB_SOF_Handler(void) { /* Rutina de realimentacin aqu */ UIRbits.SOFIF = 0; } end USB_SOF_Handler

2.1.4.10.

void USBStallHandler(void)

Precondicin: El SIE tiene que haber mandado un paquete STALL al host. El STALLIF se active cada vez que el SIE enva un paquete STALL siempre que un Endpoint lo provoque. Una transaccin Setup invalida la funcin STALL. Un Endpoint paralizado para el STALL cuando recibe un paquete setup. En este caso, el SIE aceptar el paquete Setup y activa la bandera TRNIF para informar el firmware. Una funcin STALL a un pipe Endpoint particular se desactivar automticamente (direccin especfica). Hay varios motivos para que un Endpoint se paralice: 1. Cuando se recibe una repuesta no soportada por el USB. Ejemplo: GET_DESCRIPTOR(DEVICE_QUALIFIER) 2. Cuando un Endpoint est actualmente parado 3. Cuando la clase del dispositivo especifica que Endpoint tiene que paralizarse en repuesta a un evento especfico.

46

Libreras C18 del USB Ejemplo: Clase de dispositivo de almacenamiento masivo Si el CBW no es vlido, el dispositivo parar la pipe Bulk de entrada. Nota: UEPn.EPSTALL tiene que escanear que Endpoint provoca el evento STALL.
void USBStallHandler(void) { Todos los buffer descriptores del Endpoint 0 los controla el SIE, pero al recibir una transaccin Setup, la CPU gobierna el EP0_OUT forzndolo por firmware. if(UEP0bits.EPSTALL == 1) { USBPrepareForNextSetupTrf(); UEP0bits.EPSTALL = 0; } UIRbits.STALLIF = 0; } end USBStallHandler

2.1.4.11.

void USBErrorHandler(void)

El propsito de esta interrupcin es slo por depuracin durante el desarrollo. Chequea UEIR para ver error ha causado la interrupcin.
void USBErrorHandler(void) { UIRbits.UERRIF = 0; } end USBErrorHandler

2.1.4.12.

void USBProtocolResetHandler(void)

Precondicin: Se tiene que haber recibido un reset del bus USB desde el host. Efectos secundarios: Esta rutina purga cualquier transaccin pendiente. Borra la FIFO USTAT. Hay que llamar esta rutina cuando el reset del bus USB se ha recibido. Resetea la direccin del dispositivo a cero, desactiva todos los Endpoints menos el cero, inicializa el EP0 para que est disponible las comunicaciones por defecto, borra todas los flags de interrupcin, desenmascara las interrupciones USB aplicables y reinicializa las variables internas de estado-mquina.
void USBProtocolResetHandler(void) { UEIR = 0; Borra todas los flags de error del USB UIR = 0; Borra todas las interrupciones USB UEIE = 0b10011111; Desenmascara todos los errores de interrupcin USB UIE = 0b01111011; Activa todas las interrupciones menos ACTVIE UADDR = 0x00; Resetea a la direccin por defecto mDisableEP1to15(); Resetea todos los registros UEPn non-EP0 UEP0 = EP_CTRL|HSHK_EN; Inicializa el EP0 como EP Ctrl, ver usbdrv.h while(UIRbits.TRNIF == 1) Borra cualquier transaccin pendiente UIRbits.TRNIF = 0; UCONbits.PKTDIS = 0; Se asegura de que el procesamiento de paquetes est activo

47

Documento creado por Slalen para Electronics Strange World


USBPrepareForNextSetupTrf(); Declarado en usbctrltrf.c usb_stat.RemoteWakeup = 0; Desactiva el flag de estado por defecto usb_active_cfg = 0; Borra la configuracin activa usb_device_state = DEFAULT_STATE; } end USBProtocolResetHandler

2.1.5.

FUNCIN AUXILIAR

void ClearArray(byte* startAdr,byte count) { *startAdr; while(count) { _asm clrf POSTINC0,0 _endasm count--; } end while } end ClearArray

2.2.
2.2.1.

USB9.C
Estas macros establecen la conexin.

INCLUYE

#include <p18cxxx.h> #include "system\typedefs.h" #include "system\usb\usb.h" #include "io_cfg.h"

Requerido para el estado auto-alimentado

2.2.2. 2.2.3.

VARIABLES PROTOTIPOS PRIVADOS

#pragma udata

void USBStdGetDscHandler(void); void USBStdSetCfgHandler(void); void USBStdGetStatusHandler(void); void USBStdFeatureReqHandler(void);

2.2.4.

DECLARACIONES

#pragma code

48

Libreras C18 del USB

2.2.4.1.

void USBCheckStdRequest(void)

Esta rutina chequea el paquete de datos setup para ver si sabe cuando conectarse.
void USBCheckStdRequest(void) { if(SetupPkt.RequestType != STANDARD) return; switch(SetupPkt.bRequest) { case SET_ADR: ctrl_trf_session_owner = MUID_USB9; usb_device_state = ADR_PENDING_STATE; Actualizacin de estado Ver USBCtrlTrfInHandler() en usbctrltrf.c para el prximo paso break; case GET_DSC: ctrl_trf_session_owner = MUID_USB9; if(SetupPkt.bDscType == DSC_DEV) { pSrc.bRom = (rom byte*)&device_dsc; wCount._word = sizeof(device_dsc); Activa la cuenta de datos } else if(SetupPkt.bDscType == DSC_CFG) { pSrc.bRom = (rom byte*)&cfg01; wCount._word = sizeof(cfg01); Activa la cuenta de datos } else if(SetupPkt.bDscType == DSC_STR) { pSrc.bRom = (rom byte*)&sd000; wCount._word = sizeof(sd000); Activa la cuenta de datos } else Esto se necesita para parar la respuesta DEVICE_QUALIFIER ctrl_trf_session_owner = MUID_NULL; usb_stat.ctrl_trf_mem = _ROM; Fija el tipo de memoria break; case SET_CFG: USBStdSetCfgHandler(); break; case GET_CFG: ctrl_trf_session_owner = MUID_USB9; pSrc.bRam = (byte*)&usb_active_cfg; Fija la fuente usb_stat.ctrl_trf_mem = _RAM; Fija el tipo de memoria LSB(wCount) = 1; Activa la cuenta de datos break; case GET_STATUS: USBStdGetStatusHandler(); break; case CLR_FEATURE: case SET_FEATURE: USBStdFeatureReqHandler(); break;

49

Documento creado por Slalen para Electronics Strange World


case GET_INTF: ctrl_trf_session_owner = MUID_USB9; pSrc.bRam = (byte*)&usb_alt_intf+SetupPkt.bIntfID; usb_stat.ctrl_trf_mem = _RAM; LSB(wCount) = 1; break; case SET_INTF: ctrl_trf_session_owner = MUID_USB9; usb_alt_intf[SetupPkt.bIntfID] = SetupPkt.bAltID; break; case SET_DSC: case SYNCH_FRAME: default: break; } end switch } end USBCheckStdRequest

Fija la fuente Fija el tipo de memoria Activa la cuenta de datos

2.2.4.2.

void USBStdGetDscHandler(void)

Esta rutina une la respuesta estndar GET_DESCRIPTOR. Utiliza tablas dinmicamente buscando el tamao del descriptor. Esta rutina no se debe modificar si las tablas usbdsc.c en estn declaradas correctamente.
void USBStdGetDscHandler(void) { if(SetupPkt.bmRequestType == 0x80) { switch(SetupPkt.bDscType) { case DSC_DEV: ctrl_trf_session_owner = MUID_USB9; pSrc.bRom = (rom byte*)&device_dsc; wCount._word = sizeof(device_dsc); Activa la cuenta de datos break; case DSC_CFG: ctrl_trf_session_owner = MUID_USB9; pSrc.bRom = *(USB_CD_Ptr+SetupPkt.bDscIndex); wCount._word = *(pSrc.wRom+1); Activa la cuenta de datos break; case DSC_STR: ctrl_trf_session_owner = MUID_USB9; pSrc.bRom = *(USB_SD_Ptr+SetupPkt.bDscIndex); wCount._word = *pSrc.bRom; Activa la cuenta de datos break; } end switch usb_stat.ctrl_trf_mem = _ROM; end if end USBStdGetDscHandler Fija el tipo de memoria

} }

50

Libreras C18 del USB

2.2.4.3.

void USBStdSetCfgHandler(void)

Esta rutina primero desactiva todos los Endpoints borrando los registros UEP. Configura (inicializa) los Endpoints especificados en la seccin modificable.
void USBStdSetCfgHandler(void) { ctrl_trf_session_owner = MUID_USB9; mDisableEP1to15(); Ver usbdrv.h ClearArray((byte*)&usb_alt_intf,MAX_NUM_INT); usb_active_cfg = SetupPkt.bCfgValue; if(SetupPkt.bCfgValue == 0) usb_device_state = ADDRESS_STATE; else { usb_device_state = CONFIGURED_STATE; /* Seccin modificable */ BootInitEP(); /* Final de la seccin modificable */ } end if(SetupPkt.bcfgValue == 0) } end USBStdSetCfgHandler

2.2.4.4.

void USBStdGetStatusHandler(void)

Esta rutina une la respuesta estndar GET_STATUS.


void USBStdGetStatusHandler(void) { CtrlTrfData._byte0 = 0; CtrlTrfData._byte1 = 0;

Inicializa el contenido

switch(SetupPkt.Recipient) { case RCPT_DEV: ctrl_trf_session_owner = MUID_USB9; _byte0: bit0: Estado auto-alimentado [0] Alimentado por el bus [1] auto-alimentado bit1: Reinicio remoto [0] Desactivado [1] Activado if(self_power == 1) Auto-alimentado definido en io_cfg.h CtrlTrfData._byte0|=0b000000001; Activa bit0 if(usb_stat.RemoteWakeup == 1) CtrlTrfData._byte0|=0b00000010; usb_stat definido en usbmmap.c Activa bit1

break; case RCPT_INTF: ctrl_trf_session_owner = MUID_USB9; No hay datos a actualizar break; case RCPT_EP: ctrl_trf_session_owner = MUID_USB9; _byte0: bit0: Estado parado [0] No parado [1] Parado pDst.bRam = (byte*)&ep0Bo+(SetupPkt.EPNum*8)+(SetupPkt.EPDir*4); if(*pDst.bRam & _BSTALL) Usar _BSTALL como mscara de bit CtrlTrfData._byte0=0x01; Activa bit0 break; end switch

51

Documento creado por Slalen para Electronics Strange World


if(ctrl_trf_session_owner == MUID_USB9) { pSrc.bRam = (byte*)&CtrlTrfData; usb_stat.ctrl_trf_mem = _RAM; LSB(wCount) = 2; } end if(...) } end USBStdGetStatusHandler

Fija fuente Fija el tipo de memoria Activa la cuenta de datos

2.2.4.5.

void USBStdFeatureReqHandler(void)

Esta rutina une las repuestas estndar SET y CLEAR FEATURES.


void USBStdFeatureReqHandler(void) { if((SetupPkt.bFeature==DEVICE_REMOTE_WAKEUP)&&(SetupPkt.Recipient==RCPT_DE V)) { ctrl_trf_session_owner = MUID_USB9; if(SetupPkt.bRequest == SET_FEATURE) usb_stat.RemoteWakeup = 1; else usb_stat.RemoteWakeup = 0; } end if if((SetupPkt.bFeature==ENDPOINT_HALT)&&(SetupPkt.Recipient==RCPT_EP)&& (SetupPkt.EPNum!=0)) { ctrl_trf_session_owner = MUID_USB9; Se tiene que calcular la direccin en este punto pDst.bRam = (byte*)&ep0Bo+(SetupPkt.EPNum*8)+(SetupPkt.EPDir*4); if(SetupPkt.bRequest == SET_FEATURE) *pDst.bRam = _USIE|_BSTALL; else { if(SetupPkt.EPDir == 1) // IN *pDst.bRam = _UCPU; else *pDst.bRam = _USIE|_DAT0|_DTSEN; } end if } end if } end USBStdFeatureReqHandler

52

Libreras C18 del USB

2.3.
2.3.1.

USBCTRLTRF.C
Estas macros controlan las transferencias.

INCLUYE

#include <p18cxxx.h> #include "system\typedefs.h" #include "system\usb\usb.h"

2.3.2.

VARIABLES
Estado de la transferencia de control Controlador de la sesin de transferencia actual Puntero a la fuente de datos Puntero al destino de los datos Contador de datos

#pragma udata byte ctrl_trf_state; byte ctrl_trf_session_owner; POINTER pSrc; POINTER pDst; WORD wCount;

2.3.3.

PROTOTIPOS PRIVADOS

void USBCtrlTrfSetupHandler(void); void USBCtrlTrfOutHandler(void); void USBCtrlTrfInHandler(void);

2.3.4. 2.3.4.1.

DECLARACIONES void USBCtrlEPService(void)

#pragma code

Precondicin: USTAT est cargada con una direccin de Endpoint vlida. USBCtrlEPService chequea tres tipos de transacciones que conoce como tratarlas y lo hace: 1. EP0 SETUP 2. EP0 OUT 3. EP0 IN Ignora los dems tipos.
void USBCtrlEPService(void) { if(USTAT == EP00_OUT) { if(ep0Bo.Stat.PID == SETUP_TOKEN) USBCtrlTrfSetupHandler(); else USBCtrlTrfOutHandler(); } else if(USTAT == EP00_IN) USBCtrlTrfInHandler(); } end USBCtrlEPService

EP0 SETUP EP0 OUT

EP0 IN

53

Documento creado por Slalen para Electronics Strange World

2.3.4.2.

void USBCtrlTrfSetupHandler(void)

Precondicin: El buffer SetupPkt est cargado con un dato vlido de Setup. Esta rutina es una tarea para despachar y tiene tres estados. 1. Inicializa la transferencia de control de estados mquina. 2. Llama cada vez al mdulo que sabe como servir la respuesta Setup del host. Ejemplo de mdulo: USB9, HID, CDC, MSD, Se aade una nueva clase, la tabla ClassReqHandler en usbdsc.c se tiene que actualizar para llamar todas las clases de unin disponibles. 3. Una vez que el mdulo se arriesga a chequear si el responsable de servir la respuesta, en el estado 3 chequea la direccin de la transferencia para determinar como preparar el EP0 para la transferencia de control. Nota: El firmware del USB de Microchip tiene tres estados distintos para el control de los estados mquina: 1. WAIT_SETUP 2. CTRL_TRF_TX 3. CTRL_TRF_RX Mirar en el manual del firmware como cambia de un estado a otro. Una transferencia de control se compone de varias transacciones USB. Cuando se transfieren datos con muchas transacciones, es importante guardar los datos fuente, datos destino y cuenta de datos. Estos tres parmetros se guardan en pSrc, pDst y wCount. Un flag se utiliza para ver si la fuente de los datos es de la RAM o de la ROM.

2.3.4.3.
{ byte i;

void USBCtrlTrfSetupHandler(void)

Estado 1 ctrl_trf_state = WAIT_SETUP; ctrl_trf_session_owner = MUID_NULL; wCount._word = 0; Estado 2 USBCheckStdRequest(); /* Seccin Modificable */

Fijar el dueo a NULL

Ver system\usb9\usb9.c

Insertar otra respuesta de unin de clase de dispositivo USB aqu /* Fin de la seccin modificable */ Estado 3 USBCtrlEPServiceComplete(); } end USBCtrlTrfSetupHandler

2.3.4.4.

void USBCtrlTrfOutHandler(void)

Esta rutina une una transaccin OUT de acuerdo con el estado de la transferencia de control que est actualmente activa.

54

Libreras C18 del USB Nota: Si la transferencia de control es del host al dispositivo, hay que notificar el dueo de la sesin cada transaccin OUT para dar servicio a los datos recibidos.
void USBCtrlTrfOutHandler(void) { if(ctrl_trf_state == CTRL_TRF_RX) { USBCtrlTrfRxService(); No preocuparse de reescribir el bit _KEEP porque si est activo, TRNIF no se generar en primer lugar. if(ep0Bo.Stat.DTS == 0) ep0Bo.Stat._byte = _USIE|_DAT1|_DTSEN; else ep0Bo.Stat._byte = _USIE|_DAT0|_DTSEN; } else CTRL_TRF_TX USBPrepareForNextSetupTrf(); } end USBCtrlTrfOutHandler

2.3.4.5.

void USBCtrlTrfInHandler(void)

Esta rutina une una transaccin IN de acuerdo con el estado de la transferencia de control que est actualmente activa. Nota: Si se fija la direccin de respuesta no modificar la actual hasta que se complete la transferencia de control. El final de la transferencia de control para una repuesta de cambio de direccin es una transaccin IN. Por lo tanto se necesita para servir esta situacin cuando la condicin es correcta. La macro mUSBCheckAdrPendingState se define en usb9.h y est diseada para servir este evento.
void USBCtrlTrfInHandler(void) { mUSBCheckAdrPendingState();

Se tiene que comprobar si est en ADR_PENDING_STATE

if(ctrl_trf_state == CTRL_TRF_TX) { USBCtrlTrfTxService(); if(ep0Bi.Stat.DTS == 0) ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN; else ep0Bi.Stat._byte = _USIE|_DAT0|_DTSEN; } else CTRL_TRF_RX USBPrepareForNextSetupTrf(); } end USBCtrlTrfInHandler

2.3.4.6.

void USBCtrlTrfTxService(void)

Precondicin: pSrc, wCount, y usb_stat.ctrl_trf_mem estn configurados correctamente.

55

Documento creado por Slalen para Electronics Strange World Hay que llamar esta rutina en dos casos. Uno desde USBCtrlEPServiceComplete() y otro desde USBCtrlTrfInHandler(). Hay que tener cuidado con el control de una transferencia sobre mltiples transacciones USB. Nota: Esta rutina trabaja con Endpoints sncronos mayores que 256bytes y aqu se muestra un ejemplo de cmo tratar BC9 y BC8. En realidad, un Endpoint de control no puede ser mayor de 64bytes.
void USBCtrlTrfTxService(void) { byte byte_to_send; Primero, hay que calcular cuantos bytes de datos se envan. if(wCount._word < EP0_BUFF_SIZE) byte_to_send = wCount._word; else byte_to_send = EP0_BUFF_SIZE; ep0Bi.Cnt = byte_to_send; Resta el nmero de bytes enviados a los del total. wCount._word -= byte_to_send; pDst.bRam = (byte*)&CtrlTrfData; Fija el puntero destino while(byte_to_send) { if(usb_stat.ctrl_trf_mem == _ROM) { *pDst.bRam = *pSrc.bRom; pSrc.bRom++; } else { *pDst.bRam = *pSrc.bRam; pSrc.bRam++; }//end if else pDst.bRam++; byte_to_send--; } end while } end USBCtrlTrfTxService

2.3.4.7.

void USBCtrlTrfRxService(void)

Precondiciones: pDst y wCount tienen que estar configurados correctamente. pSrc siempre es &CtrlTrfData y usb_stat.ctrl_trf_mem es _RAM. wCount tiene que estar configurado como 0 al principio de cada transferencia de control. Esta rutina no est completada. Comprueba una nueva versin del firmware.
void USBCtrlTrfRxService(void) { byte byte_to_read; byte_to_read = ep0Bo.Cnt; Acumula el nmero total de bytes ledos wCount._word = wCount._word + byte_to_read; pSrc.bRam = (byte*)&CtrlTrfData;

56

Libreras C18 del USB


while(byte_to_read) { *pDst.bRam = *pSrc.bRam; pDst.bRam++; pSrc.bRam++; byte_to_read--; } end while(byte_to_read) } end USBCtrlTrfRxService

2.3.4.8.

void USBCtrlEPServiceComplete(void)

Esta rutina consigue que la tarea en servicio sea una repuesta setup. Esta tarea sirve para configurar los controles del Endpoint apropiadamente para una situacin dada. Hay tres: a. No hay unin para la respuesta, in este caso hay que mandar un STALL. b. El host ha respondido con una lectura de transferencia de control, los Endpoints se necesitan para determinar el camino. c. El host ha respondido con una escritura de transferencia de control o no se necesita un estado de control de datos, los Endpoints se necesitan para determinar el camino. Se resume el procesamiento del paquete borrando el bit PKTDIS.
void USBCtrlEPServiceComplete(void) { if(ctrl_trf_session_owner == MUID_NULL) { Si ninguno sabe cmo dar servicio a esta respuesta, entonces se para. * If no one knows how to service this request then stall. Tiene que preparar el EP0 para que reciba la siguiente transaccin SETUP. ep0Bo.Cnt = EP0_BUFF_SIZE; ep0Bo.ADR = (byte*)&SetupPkt; ep0Bo.Stat._byte = _USIE|_BSTALL; ep0Bi.Stat._byte = _USIE|_BSTALL; } else El modulo demanda el control de la sesin de transferencia. { if(SetupPkt.DataDir == DEV_TO_HOST) { if(SetupPkt.wLength < wCount._word) wCount._word = SetupPkt.wLength; USBCtrlTrfTxService(); ctrl_trf_state = CTRL_TRF_TX; Control de lectura: <SETUP[0]><IN[1]><IN[0]>...<OUT[1]> | <SETUP[0]> 1. Prepara EP OUT para responder a una terminacin temprana NOTA: Si algo va mal durante la transferencia de control, puede que el host no enve la ltima fase de estado. Cuando pasa esto, pueden ocurrir dos cosas dependiendo del host: a) El host enva un RESET

57

Documento creado por Slalen para Electronics Strange World b) El host puede mandar una nueva transaccin SETUP sin enviar primero un
RESET. Para que el caso b) comunique correctamente, el EP OUT tiene que configurarse para recibir una transaccin OUT de longitud cero o una nueva transaccin SETUP. Como la transaccin SETUP necesita que el bit DTS sea DAT0, el estado de longitud cero necesita que el bit DTS sea DAT1, la comprobacin del bit DTS por hardware tiene que desactivarse. En este caso el SIE puede aceptar cualquiera de las dos transacciones. Adems, el byte Cnt se tiene que fijar para prepararse para el dato SETUP (8bytes o mas), y el buffer de direccin tiene que apuntar al SetupPkt. ep0Bo.Cnt = EP0_BUFF_SIZE; ep0Bo.ADR = (byte*)&SetupPkt; ep0Bo.Stat._byte = _USIE; Nota: DTSEN es 0 2. Prepara el EP IN para una transferencia de datos, Cnt tiene que estar inicializado para ser el responsable de una respuesta de dueo. ep0Bi.ADR = (byte*)&CtrlTrfData; ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN; } else (SetupPkt.DataDir = HOST_TO_DEV) { ctrl_trf_state = CTRL_TRF_RX; Control Escritura: <SETUP[0]><OUT[1]><OUT[0]>...<IN[1]> | <SETUP[0]> 1. Prepara el EP IN para responder ante una finalizacin temprana. Es lo mismo que una respuesta a un paquete de longitud cero para una transferencia de control sin fase de datos. ep0Bi.Cnt = 0; ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN; 2. Prepara el EP OUT para recibir datos. ep0Bo.Cnt = EP0_BUFF_SIZE; ep0Bo.ADR = (byte*)&CtrlTrfData; ep0Bo.Stat._byte = _USIE|_DAT1|_DTSEN; } end if(SetupPkt.DataDir == DEV_TO_HOST) } end if(ctrl_trf_session_owner == MUID_NULL) El bit PKTDIS se activa cuando se recibe una transaccin Setup. Borrar para resumir el procesamiento del paquete. UCONbits.PKTDIS = 0; } end USBCtrlEPServiceComplete

2.3.4.9.

void USBPrepareForNextSetupTrf(void)

La rutina fuerza al EP0 OUT que est listo para una nueva transaccin Setup, y fuerza a que la CPU controle el EP0 IN.
void USBPrepareForNextSetupTrf(void) { ctrl_trf_state = WAIT_SETUP; ep0Bo.Cnt = EP0_BUFF_SIZE; ep0Bo.ADR = (byte*)&SetupPkt; ep0Bo.Stat._byte = _USIE|_DAT0|_DTSEN; usbmmap.h ep0Bi.Stat._byte = _UCPU; } end USBPrepareForNextSetupTrf

Ver usbctrltrf.h Definido en usbcfg.h Inicializacin EP0 buff dsc, ver

EP0 IN buffer inicializacin

58

Libreras C18 del USB

2.4.

USBDSC.C: DESCRIPTORES USB

Este archivo contiene la informacin de los descriptores USB. Se utiliza junto al archivo usbdsc.h. Cuando se aade o remueve un descriptor del men de configuracin de los descriptores, ej. CFG01, el usuario debe cambiar la estructura del descriptor definida en el archivo usbdsc.h. La estructura se utiliza para calcular el tamao del descriptor, ej. sizeof(CFG01). Una configuracin tpica de los descriptores consiste en: La mnima configuracin del descriptor (USB_CFG_DSC) Uno o ms descriptores de interfaz (USB_INTF_DSC) Uno o ms descriptores de Endpoint (USB_EP_DSC) Nombres convenidos: Tipo USB_CFG_DSC se nombra cdxx, donde xx es el nmero de configuracin. Este nmero debera ser el mismo que el valor del ndice actual de esta configuracin. Tipo USB_INTF_DSC se nombra i<yy>a<zz>, donde yy es el nmero de la interfaz y zz es el nmero de la interfaz alterna. Tipo USB_EP_DSC se nombra ep<##><d>_i<yy>a<zz>, donde ## es el nmero del Endpoint y d es la direccin de transferencia. El nombre de la interfaz se tiene que listar como un sufijo para identificar que interfaz pertenece al Endpoint. Ejemplo: Si un dispositivo tiene una configuracin, dos interfaces, la interfaz 0 tiene dos Endpoints (IN y OUT), y la interfaz 1 tiene un Endpoint (IN). Entonces la estructura en usbdsc.h tiene que ser: #define CFG01 rom struct { USB_CFG_DSC USB_INTF_DSC USB_EP_DSC USB_EP_DSC USB_INTF_DSC USB_EP_DSC } cfg01 cd01; i00a00; ep01o_i00a00; ep01i_i00a00; i01a00; ep02i_i01a00;

Ver que la jerarqua de los descriptores sigue a las especificaciones de necesidad del USB. Todos los Endpoint que pertenecen a una interfaz se tienen que listar inmediatamente despus que la interfaz. Rellenar los valores del descriptor en el archivo usbdsc.c: [Descriptor de Configuration (USB_CFG_DSC)]

59

Documento creado por Slalen para Electronics Strange World El atributo de configuracin tiene que tener la definicin _DEFAULT como mnimo. Se pueden aadir opciones adicionales al tributo _DEFAULT. Las opciones disponibles son _SELF y _RWU. Estas definiciones se encuentran en el archivo usbdefs_std_dsc.h. El _SELF dice al host del USB que este dispositivo es autoalimentado. El _RWU dice al host del USB que el dispositivo soporta el reinicios remoto. [Descriptor del Endpoint (USB_EP_DSC)] Suponer el siguiente ejemplo: sizeof(USB_EP_DSC),DSC_EP,_EP01_OUT,_BULK,64,0x00 Los dos primeros parmetros son auto-explicativos. Especifican la longitud del descriptor del Endpoint (7) y el tipo de descriptor. El siguiente parmetro identifica el Endpoint, las definiciones se encuentran en usbdefs_std_dsc.h y tienen la siguiente convencin: _EP<##>_<dir> donde ## es el nmero del endpoint y dir es la direccin de la transferencia. dir tiene el valor de OUT o IN. El siguiente parmetro especifica el tipo de Endpoint. Las opciones disponibles son _BULK, _INT, _ISO, y _CTRL. El _CTRL no se utiliza normalmente porque el Endpoint de transferencia de control por defecto no se define en los descriptores USB. Cuando se utiliza la opcin _ISO, se pueden aadir opciones adicionales. Ejemplo: _ISO|_AD|_FE Esto describe el Endpoint como una pipe sncrona con los atributos adoptivo y realimentacin. Ver usbdefs_std_dsc.h y las especificaciones del USB por ms detalles. El siguiente parmetro define el tamao del Endpoint. El ltimo parmetro es el intervalo de muestreo. Aadir un String al USB Una matriz de string descriptor debe tener el siguiente formato: rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={ sizeof(sdxxx),DSC_STR,<text>}; La estructura proporciona un medio al compilador de C para calcular la longitud del string descriptor sdxxx, donde xxx es el nmero de ndice. Los dos primeros bytes del descriptor son su longitud y tipo. El resto <text> son strings de texto que tienen que estar en formato unicode. El formato unicode se obtiene declarando cada carcter como un tipo de letra. Todo el texto string se declara como una matriz de letras con el nmero de caracteres igual a <size>. <size> se tiene que contar manualmente y meter en las declaraciones de la matriz. Ejemplo: Si el string es USB, entonces el string descriptor debe ser: (Utilizando ndice 02) rom struct{byte bLength;byte bDscType;word string[3];}sd002={ sizeof(sd002),DSC_STR,'U','S','B'};

60

Libreras C18 del USB Un proyecto USB puede que tenga varios strings y el firmware soporta el control de mltiples strings como una bsqueda en tabla. La bsqueda en tabla se define: rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002}; La declaracin de arriba tiene 3 strings, sd000, sd001 y sd002. Los strings se pueden aadir o borrar. sd000 es un string descriptor especial, define el idioma, normalmente es ingls americano (US English (0x0409)). El ndice del string debe ser igual que el ndice de posicin de la matriz USB_SD_Ptr, &sd000 tiene que estar en la posicin USB_SD_Ptr[0], &sd001 tiene que estar en la posicin USB_SD_Ptr[1] y as sucesivamente. La bsqueda en tabla USB_SD_Ptr la utiliza la funcin de unin string en usb9.c. El esquema de bsqueda en tabla tambin se aplica a la descriptor de configuracin. Un dispositivo USB puede tener varios descriptores de configuraciones, ej. CFG01, CFG02, etc. Para aadir un descriptor de configuracin, el usuario tiene que implementar una estructura similar a CFG01. El siguiente paso es aadir el nombre del descriptor de configuracin, ej. cfg01, cfg02; a la bsqueda en tabla USB_CD_Ptr. USB_CD_Ptr[0] es muy fcil poner el titular ya que la configuracin 0 es el estado no configurado de acuerdo con las especificaciones del USB. Los tipos de descriptor especficos se definen en: system\usb\usbdefs\usbdefs_std_dsc.h La informacin de configuracin se define en: autofiles\usbcfg.h

2.4.1.

INCLUYE

#include "system\typedefs.h" #include "system\usb\usb.h"

2.4.2.

CONSTANTES

#pragma romdata Descriptor del dispositivo rom USB_DEV_DSC device_dsc= { sizeof(USB_DEV_DSC), DSC_DEV, 0x0200, 0x00, 0x00, 0x00, EP0_BUFF_SIZE, 0x04D8, 0x0000,

Tamao del descriptor en bytes Descriptor tipo DEVICE Nmero de versin del USB en formato BCD Cdigo de Clase Cdigo Subclase Cdigo Protocolo Tamao de paquete mximo para el EP0, ver usbcfg.h ID Fabricante ID Producto

61

Documento creado por Slalen para Electronics Strange World


0x0001, 0x01, 0x02, 0x00, 0x01 Nmero de versin del dispositivo en formato BCD String ndice de fabricante String ndice del producto String ndice del nmero de serie del dispositivo Nmero de configuraciones posible

};

Descriptor de configuracin 1 CFG01={ Descriptor de configuracin sizeof(USB_CFG_DSC), DSC_CFG, sizeof(cfg01), 1, 1, 0, _DEFAULT|_RWU, 50, Descriptor de la interfaz sizeof(USB_INTF_DSC), DSC_INTF, 0, 0, 1, HID_INTF, BOOT_INTF_SUBCLASS, HID_PROTOCOL_MOUSE, 0,

Tamao del descriptor en bytes Tipo del descriptor CONFIGURACIN Longitud total de datos de esta configuracin Nmero de interfaces en esta configuracin Valor del ndice de esta configuracin String ndice de configuracin Atributos, ver usbdefs_std_dsc.h Consumo mximo de corriente (2X mA)

Tamao del descriptor en bytes Tipo de descriptor INTERFACE Nmero de Interface Nmero alterno de configuracin Nmero de Endpoints en esta interfaz Cdigo de la Clase Cdigo de la Subclase Cdigo del Protocolo String ndice de interfaz

}; rom struct{byte bLength;byte bDscType;word string[1];}sd000={ sizeof(sd000),DSC_STR,0x0409}; rom struct{byte bLength;byte bDscType;word string[25];}sd001={ sizeof(sd001),DSC_STR, 'M','i','c','r','o','c','h','i','p',' ', 'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'}; rom struct{byte bLength;byte bDscType;word string[22];}sd002={ sizeof(sd002),DSC_STR, 'M','o','u','s','e',' ','I','n',' ','a',' ',

Descriptor de Clase Especfica HID sizeof(USB_HID_DSC), Tamao del descriptor en bytes DSC_HID, Tipo del descriptor HID 0x0101, Nmero de versin especfica HID en formato BCD 0x00, Cdigo del pas (0x00 en los no soportados) HID_NUM_OF_DSC, Nmero de la clase del descriptor, ver usbcfg.h DSC_RPT, Tipo del informe del descriptor sizeof(hid_rpt01), Tamao del informe del descriptor Descriptor del Endpoint sizeof(USB_EP_DSC),DSC_EP,_EP01_IN,_INT,HID_INT_IN_EP_SIZE,0x0A

62

Libreras C18 del USB


'C','i','r','c','l','e',' ','D','e','m','o'}; rom struct{byte report[HID_RPT01_SIZE];}hid_rpt01={ 0x05, 0x01, Pgina de uso (Escritorio genrico) 0x09, 0x02, Uso (Ratn) 0xA1, 0x01, Coleccin (Aplicacin) 0x09, 0x01, Uso (Puntero) 0xA1, 0x00, Coleccin (Fsica) 0x05, 0x09, Pgina de uso (Botones) 0x19, 0x01, Uso mnimo (01) 0x29, 0x03, Uso mximo (03) 0x15, 0x00, Mnimo lgico (0) 0x25, 0x01, Mximo lgico (0) 0x95, 0x03, Cuenta del informe (3) 0x75, 0x01, Tamao del informe (1) 0x81, 0x02, Entrada (Dato, Variable, Absoluto) 0x95, 0x01, Cuenta del informe (1) 0x75, 0x05, Tamao del informe (5) 0x81, 0x01, Entrada (Constante); 5 bit de relleno 0x05, 0x01, Uso de pgina (Escritorio genrico) 0x09, 0x30, Uso (X) 0x09, 0x31, Uso (Y) 0x15, 0x81, Mnimo lgico (-127) 0x25, 0x7F, Mximo lgico (127) 0x75, 0x08, Tamao del informe (8) 0x95, 0x02, Cuenta del informe (2) 0x81, 0x06, Entrada (Dato, Variable, Relativo) 0xC0, 0xC0}; Fin de la coleccin rom const unsigned char *rom USB_CD_Ptr[]={&cfg01,&cfg01}; rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002}; rom pFunc ClassReqHandler[1]= { &USBCheckHIDRequest }; #pragma code

2.5.

USBMMAP.C

Este archivo es el que controla la memoria del USB, sirve para asignar la memoria en cada instante a los Endpoint. Utiliza los tiempos de compilacin de usbcfg.h instantneamente para los Endpoints y sus buffers. Cada Endpoint necesita fijar un registro del buffer descriptor (BDT). Un BDT tiene 4bytes de longitud y una memoria especfica en la RAM para cada Endpoint. El BDT del EP0 OUT est entre las direcciones 0x400 a 0x403, el BDT del EP0 IN en 0x404 a0x407, el del EP1 OUT 0x408 a 0x40B y as sucesivamente. Estas localizaciones son correctas con el Buffer Ping-Pong en Modo 0. Estas localizaciones

63

Documento creado por Slalen para Electronics Strange World estn conectadas en el chip. Al hacerlas instantneas, ej. volatile far BDT ep0Bo, es para proporcionar al compilador de C un camino para direccionar cada variable directamente. Esto es muy importante porque cuando se puede acceder a un registro directamente, se ahorra tiempo de ejecucin y se reduce el tamao de programa. Los Endpoints se definen con el nmero de Endpoint y la direccin de transferencia. Para simplificar, usbmmap.c slo utiliza el nmero del Endpoint del esquema de direccionamiento de los registros BDT. Con este mtodo si MAX_EP_NUMBER es 1, tenemos cuatro BDTs instantneamente: uno para EP0IN, otro para EP0OUT, que se tiene que inicializar instantneamente para las transferencias de control por defecto, y otros dos para EP1IN y EP1OUT. El nombre convenido es ep<#>B<d> donde # es el nmero del Endpoint y d es la direccin de transferencia, que puede ser <i> o <o>. El control de la memoria USB utiliza MAX_EP_NUMBER, definido en usbcfg.h, para saber que Endpoints se necesitan instantneamente. Representa el nmero mximo de Endpoints que se direccionan, no cuantos Endpoints se utilizan. Como los BDTs para los Endpoints tienen la direccin asignada en el Bank 4 en hardware, configurar este valor con un dato muy grande puede que se utilice inadecuadamente la RAM. Por ejemplo, en una aplicacin se utiliza los EP0 y EP4, el MAX_EP_NUMBER es 4, y no 2. Los Endpoints del medio (EP1, EP2 y EP3) no se utilizan, y los 24bytes de memoria asociados se pierden. No tiene mucho sentido saltar Endpoints, pero la decisin final la tiene el usuario. El paso siguiente es asignar los BDTs instantneos a las distintas funciones del USB. El firmware asume que cada funcin del USB sabe que Endpoint utiliza, ej. la transferencia de control por defecto sabe que utiliza el EP0IN y el EP0OUT. Una clase HID puede elegir que Endpoint utiliza, pero una vez elegido tiene que saber el nmero. La asignacin de los Endpoints de las funciones del USB se gobiernan en usbcfg.h. Esto ayuda a prevenir errores de tener ms de una funcin USB con el mismo Endpoint. La seccin Distribucin de los Endpoints en usbcfg.h proporciona un ejemplo de cmo distribuir los Endpoints del USB con funciones USB. Se puede cambiar la configuracin en esta seccin. No hay una forma correcta de configuracin y los usuarios tienen que elegir el mtodo ms adecuado para la aplicacin. Normalmente, un usuario mapear lo siguiente para una funcin de interfaz: 1. 2. 3. 4. El ID de la interfaz USB Los registros de control de los Endpoint (UEPn) El registro BDT (ep<#>B<d>) El tamao del Endpoint.

Ejemplo: Suponer una clase de dispositivo foo, que utiliza un Endpoint de salida de 64bytes y un Endpoint de entrada de 64bytes, entonces: #define FOO_INTF_ID #define FOO_UEP #define FOO_BD_OUT #define FOO_BD_IN #define FOO_EP_SIZE 0x00 UEP1 ep1Bo ep1Bi 64

64

Libreras C18 del USB El mapeo anterior elige la clase foo para utilizarse con el Endpoint 1. El nombre es arbitrario y se puede elegir otro que no sea FOO_???????. Como idea abstracta, el cdigo para la clase foo se tiene que usar en las definiciones abstractas de FOO_BD_OUT,FOO_BD_IN y o ep1Bo o ep1Bi. Ver que el tamao del Endpoint definido en el archivo usbcfg.h se utiliza de nuevo en el archivo usbmmap.c. Esto muestra que los dos archivos estn muy relacionados. El buffer del Endpoint para cada funcin USB se localiza en el rea del puertodual RAM y como despus se tiene que hacer instantneos los BDTs. Un ejemplo de declaracin es: volatile far unsigned char[FOO_EP_SIZE] data; La palabra volatile dice al compilador que no funcione ningn cdigo de optimizacin en esta variable porque el contenido lo tiene que modificar el hardware. La palabra far dice que la variable no se localiza en el rea de RAM Accesible (0x0000x05F). Para que la variable sea accesible globalmente con otros ficheros, se tiene que declarar en el archivo de cabecera usbmmap.h como una definicin externa, como extern volatile far unsigned char[FOO_EP_SIZE] data; Conclusin: Las dependencias entre usbcfg y usbmmap se pueden mostrar como: usbcfg[MAX_EP_NUMBER] -> usbmmap usbmmap[ep<#>B<d>] -> usbcfg usbcfg[EP size] -> usbmmap usbcfg[abstract ep definitions] -> usb9/hid/cdc/etc class code usbmmap[endpoint buffer variable] -> usb9/hid/cdc/etc class code El mapeo proporciona una manera directa de direccionado de BDT y un buffer del Enpoint. Esta forma utiliza menos punteros, y se equipara con un cdigo de programa ms rpido y pequeo.

2.5.1.

INCLUYE

#include "system\typedefs.h" #include "system\usb\usb.h"

2.5.2.

VARIABLES GLOBALES DEL USB


Estados del dispositivo: Desconectado, Conectado, ... Flags globales del USB Valor de la configuracin actual Matriz para guardar los datos de la configuracin actual alterna para cada ID interfaz

#pragma udata byte usb_device_state; USB_DEVICE_STATUS usb_stat; byte usb_active_cfg; byte usb_alt_intf[MAX_NUM_INT];

2.5.3.

LOCALIZACIONES DE VARIABLES FIJAS DEL USB

#pragma udata usbram4=0x400 Ver, usb4: 0x400-0x4FF(256-byte) Seccin A: Tabla del Buffer Descriptor - 0x400 - 0x4FF(max)

65

Documento creado por Slalen para Electronics Strange World


- MAX_EP_NUMBER se define en autofiles\usbcfg.h - BDT data type se define en system\usb\usbmmap.h #if(0 <= MAX_EP_NUMBER) volatile far BDT ep0Bo; Endpoint #0 BD Out volatile far BDT ep0Bi; Endpoint #0 BD In #endif #if(1 <= MAX_EP_NUMBER) volatile far BDT ep1Bo; volatile far BDT ep1Bi; #endif #if(2 <= MAX_EP_NUMBER) volatile far BDT ep2Bo; volatile far BDT ep2Bi; #endif #if(3 <= MAX_EP_NUMBER) volatile far BDT ep3Bo; volatile far BDT ep3Bi; #endif #if(4 <= MAX_EP_NUMBER) volatile far BDT ep4Bo; volatile far BDT ep4Bi; #endif #if(5 <= MAX_EP_NUMBER) volatile far BDT ep5Bo; volatile far BDT ep5Bi; #endif #if(6 <= MAX_EP_NUMBER) volatile far BDT ep6Bo; volatile far BDT ep6Bi; #endif #if(7 <= MAX_EP_NUMBER) volatile far BDT ep7Bo; volatile far BDT ep7Bi; #endif #if(8 <= MAX_EP_NUMBER) volatile far BDT ep8Bo; volatile far BDT ep8Bi; #endif #if(9 <= MAX_EP_NUMBER) volatile far BDT ep9Bo; volatile far BDT ep9Bi;

Endpoint #1 BD Out Endpoint #1 BD In

Endpoint #2 BD Out Endpoint #2 BD In

Endpoint #3 BD Out Endpoint #3 BD In

Endpoint #4 BD Out Endpoint #4 BD In

Endpoint #5 BD Out Endpoint #5 BD In

Endpoint #6 BD Out Endpoint #6 BD In

Endpoint #7 BD Out Endpoint #7 BD In

Endpoint #8 BD Out Endpoint #8 BD In

Endpoint #9 BD Out Endpoint #9 BD In

66

Libreras C18 del USB


#endif #if(10 <= MAX_EP_NUMBER) volatile far BDT ep10Bo; volatile far BDT ep10Bi; #endif #if(11 <= MAX_EP_NUMBER) volatile far BDT ep11Bo; volatile far BDT ep11Bi; #endif #if(12 <= MAX_EP_NUMBER) volatile far BDT ep12Bo; volatile far BDT ep12Bi; #endif

Endpoint #10 BD Out Endpoint #10 BD In

Endpoint #11 BD Out Endpoint #11 BD In

Endpoint #12 BD Out Endpoint #12 BD In

#if(13 <= MAX_EP_NUMBER) volatile far BDT ep13Bo; volatile far BDT ep13Bi #endif #if(14 <= MAX_EP_NUMBER) volatile far BDT ep14Bo; volatile far BDT ep14Bi; #endif

Endpoint #13 BD Out Endpoint #13 BD In

Endpoint #14 BD Out Endpoint #14 BD In

#if(15 <= MAX_EP_NUMBER) volatile far BDT ep15Bo; Endpoint #15 BD Out volatile far BDT ep15Bi; Endpoint #15 BD In #endif Seccin B: Espacio del Buffer del EP0 - Dos areas definidas para el buffer: A. CTRL_TRF_SETUP - Tamao = EP0_BUFF_SIZE definido en autofiles\usbcfg.h - La estructura de datos detallada permite el direccionamiento directo de bits y bytes. B. CTRL_TRF_DATA - Tamao = EP0_BUFF_SIZE definido en autofiles\usbcfg.h - La estructura de datos detallada permite el direccionamiento directo de los 8 bytes primeros. - Los dos tipos se definen en system\usb\usbdefs\usbdefs_ep0_buff.h volatile far CTRL_TRF_SETUP SetupPkt; volatile far CTRL_TRF_DATA CtrlTrfData; Seccin C: Buffer CDC #pragma udata usbram5a=0x500 //See Linker Script,usb5:0x500#if defined(USB_USE_CDC) volatile far unsigned char cdc_notice[CDC_INT_EP_SIZE]; volatile far unsigned char cdc_data_rx[CDC_BULK_OUT_EP_SIZE]; volatile far unsigned char cdc_data_tx[CDC_BULK_IN_EP_SIZE]; #endif #pragma udata

67

Documento creado por Slalen para Electronics Strange World

2.6.

USBGEN.C: USB GENRICO

En este archivo se han creado todas las funciones de transferencia de los datos que desee el usuario en la clase genrica.

2.6.1.

INCLUYE

#include <p18cxxx.h> #include "system\typedefs.h" #include "system\usb\usb.h" #ifdef USB_USE_GEN

2.6.2.

VARIABLES

#pragma udata byte usbgen_rx_len;

2.6.3. 2.6.4. 2.6.4.1.

DECLARACIONES API DEL USUARIO void USBGenInitEP(void)

#pragma code

USBGenInitEP inicializa Endpoints genricos, buffer de los descriptores, estados mquina internos y variables. Hay que llamarla despus de que el host haya enviado una repuesta SET_CONFIGURATION. Ver USBStdSetCfgHandler() en usb9.c como ejemplo.
void USBGenInitEP(void) { usbgen_rx_len = 0; USBGEN_UEP = EP_OUT_IN|HSHK_EN; Activa 2 pipes de datos No hay que iniciar Cnt para las pipes de entrada. Razn: El nmero de bytes enviados al host vara de una transaccin a otra. Cnt tiene que ser igual al nmero exacto de bytes a transmitir en una transaccin IN dada. Este nmero de bytes slo se conoce una vez que los datos hayan sido enviados. USBGEN_BD_OUT.Cnt = sizeof(usbgen_out); Fija el tamao del buffer USBGEN_BD_OUT.ADR = (byte*)&usbgen_out; Fija la direccin del buffer USBGEN_BD_OUT.Stat._byte = _USIE|_DAT0|_DTSEN; Fija el estado USBGEN_BD_IN.ADR = (byte*)&usbgen_in; USBGEN_BD_IN.Stat._byte = _UCPU|_DAT1; } end USBGenInitEP Fija la direccin del buffer Fija el estado del buffer

2.6.4.2.

void USBGenWrite(byte *buffer, byte len)

Precondicin: mUSBGenTxIsBusy() tiene que devolver falso.

68

Libreras C18 del USB El valor de len tiene que ser igual o menor que USBGEN_EP_SIZE. Para un Endpoint interrupcin/bulk, el tamao mximo del buffer es de 64bytes. Entrada: buffer: Puntero a la localizacin de inicio de los bytes de datos. len: Nmero de bytes a transmitir. Esta macro se utiliza para transferir datos de la memoria de datos. Aplicacin tpica: if(!mUSBGenTxIsBusy()) USBGenWrite(buffer, 3);
void USBGenWrite(byte *buffer, byte len) { byte i; El valor de len tiene que ser igual o menor que USBGEN_EP_SIZE. Esta comprobacin fuerza que se cumpla la precondicin. if(len > USBGEN_EP_SIZE) len = USBGEN_EP_SIZE; Copia de los datos del buffer del usuario al buffer de la ram-dual. for (i = 0; i < len; i++) usbgen_in[i] = buffer[i]; USBGEN_BD_IN.Cnt = len; mUSBBufferReady(USBGEN_BD_IN); } end USBGenWrite

2.6.4.3.

byte USBGenRead(byte *buffer, byte len)

Precondicin: El valor del argumento de entrada len tiene que ser menor que el tamao mximo del Endpoint responsable de la recepcin del informe de datos del host para la clase HID. El argumento de entrada buffer debe apuntar al rea de buffer que sea mayor o igual que len.

69

Documento creado por Slalen para Electronics Strange World Salida: El nmero de bytes copiados al buffer. Efectos secundarios: el acceso a la variable pblica usbgen_rx_len se actualiza con el nmero de bytes copiados al buffer. Una vez llamado USBGenRead, la recuperacin de usbgen_rx_len se puede hacer llamando la macro mUSBGenGetRxLength(). USBGenRead copia un string de los bytes recibidos a travs de un Endpoint OUT a una localizacin especificada por el usuario. Es una funcin que espera a recibir los datos si no estn disponibles. Devuelve 0 para notificar que no hay datos disponibles. Nota: Si el nmero actual de bytes recibidos es mayor que el nmero de bytes esperados (len), slo se copian el nmero de bytes esperados al buffer. Si el nmero de bytes recibidos es menor que el nmero de bytes esperados (len), se copian los bytes recibidos al buffer.
byte USBGenRead(byte *buffer, byte len) { usbgen_rx_len = 0; if(!mUSBGenRxIsBusy()) { Ajusta el nmero de bytes que se esperan al nmero de bytes recibidos. if(len > USBGEN_BD_OUT.Cnt) len = USBGEN_BD_OUT.Cnt; Copia los datos de la ram-dual al buffer del usuario for(usbgen_rx_len = 0; usbgen_rx_len < len; usbgen_rx_len++) buffer[usbgen_rx_len] = usbgen_out[usbgen_rx_len]; Prepara la ram-dual para la prximo transaccin OUT. USBGEN_BD_OUT.Cnt = sizeof(usbgen_out); mUSBBufferReady(USBGEN_BD_OUT); } end if return usbgen_rx_len; } end USBGenRead #endif def USB_USE_GEN

70

Libreras C18 del USB

2.7.

MSD.C: USB ALMACENAMIENTO MASIVO

En este archivo se han creado todas las funciones de transferencia de los datos que desee el usuario en la clase MSD.

2.7.1.

INCLUYE

#include <p18cxxx.h> #include "system\typedefs.h" #include "system\usb\usb.h" #include<string.h> #ifdef USB_USE_MSD

2.7.2.

VARIABLES
Toma valores MSD_WAIT, MSD_DATA_IN o SD_DATA_OUT

#pragma udata byte MSD_State;

USB_MSD_CBW gblCBW; byte gblCBWLength; SDCSTATE gblFlag; RequestSenseResponse gblSenseData; byte *ptrNextData;

El nmero de bloques o la longitud son globales porque para cada comando READ_10 y WRITE_10 se tiene que verificar que el ltimo LBA es menor que gblNumBLKS.
DWORD gblNumBLKS=0x00,gblBLKLen=0x00;

Respuesta estndar para saber que commando est en la ROM.


const rom InquiryResponse inq_resp = { 0x00, Dispositivo perifrico conectado, acceso directo al bloque del 0x80, dispositivo removible. 0x04, versin = 00=> no cumple ningn estndar, 4=> SPC-2 0x02, respuesta en formato especificado por SPC-2 0x20, n-4 = 36-4=32= 0x20 0x00, sccs etc. 0x00, bque=1 y cmdque=0, indica que la cola simple 00 est obsoleta, pero en el caso de otro dispositivo, usamos 00 0x00, 00 obsoleto, 0x80 para tareas bsicas de cola "Microchp", este es el T10 asignado ID del fabricante "Mass Storage ", "0001" };

2.7.3.

PROTORIPOS PRIVADOS

void MSDCommandHandler(void); void MSDInquiryHandler(void);

71

Documento creado por Slalen para Electronics Strange World


void MSDReadCapacityHandler(void); void MSDReadHandler(void); void MSDWriteHandler(void); void MSDModeSenseHandler(void); void MSDMediumRemovalHandler(void); void MSDRequestSenseHandler(void); void MSDTestUnitReadyHandler(void); void MSDVerifyHandler(void); void MSDStopStartHandler(void); byte IsMeaningfulCBW(void); byte IsValidCBW(void); void PrepareCSWData(void); void SendData(byte*, byte); void SendCSW(void); void ResetSenseData(void); void MSDDataIn(void); void MSDDataOut(void); extern SDC_Error MediaInitialize(SDCSTATE*); extern void SocketInitialize(void); extern SDC_Error SectorRead(dword, byte*); extern SDC_Error SectorWrite(dword, byte*); extern SDC_Error CSDRead(void); extern int DetectSDCard (void); extern byte IsWriteProtected(void);

2.7.4. 2.7.5. 2.7.5.1.

DECLARACIONES RESPUESTAS ESPECFICAS DE LA CLASE void USBCheckMSDRequest(void)

#pragma code

Esta rutina une el RESET estndar y el comando de repuesta recibido en el EP0 de control GET_MAX_LUN.

2.7.5.2.

void ProcessIO(void)

Precondicin: Se han llamado MSDInitEP() y SDCardInit(). MSDInitEP() se llama desde USBStdSetCfgHandler(void)(usb9.c) SDCardInit() se llama desde InitializeSystem() en main.c Esta rutina se llama desde loop continuos de main.c.

72

Libreras C18 del USB Todos los comandos de transporte Bulk en el Endpoit 1 se unen aqu: MSD_State contiene el estado actual del mdulo de almacenamiento masivo. En el estado MSD_WAIT: Espera al bloque de comando de cubierta (CBW) del Endpoint1. Si se recibe un CBW vlido y significativo, dependiendo del comando recibido MSD_State cambia a MSD_DATA_IN si el dato se enva al host (para todos comandos adems del WRITE_10). MSD_DATA_OUT si el host est esperando a mandar datos (slo en el caso de WRITE_10). Al finalizar el comando de estado de transferencia de datos de cubierta (CSW) se enva llamando SendCSW().

2.7.5.3.

void MSDInitEP(void)

Esta rutina se llama desde USBStdSetCfgHandler(void) inicializa Bulk-IN y Bulk-OUT, los Endpoints MSD_BD_IN y MSD_BD_OUT Tamao = 64B (Ver usbmmap.c y usbdefs_std_dsc.h para las definiciones de los Enspoints.

2.7.5.4.

void SDCardInit(void)

Efectos secundarios: gblFlag se actualiza de acuerdo con la Inicializacin. MSD_State se fija a MAD_WAIT. Esta rutina se llama desde InitializeSystem() en main.c. Inicializa la tarjeta SD y si tiene algn problema en la inicializacin todos los LEDs se encienced. Tambin fija MSD_State = MSD_WAIT

2.7.5.5.

void MSDCommandHandler(void)

Esta rutina se llama desde ProcessIO() cuando MSD_State=MSD_WAIT. Esta funcin decodifica el comando CBW y actua consecuentemente. Si el CBW no est soportado se fija el dato Sense, el estado de CSW se pone en comando fallido (bCSWStatus=01h).

2.7.5.6.

void SendCSW(void)

Esta funcin enva el CSW y fija el estado a MSD_WAIT. Tambin cambia MSD_BD_OUT para que apunte a msd_csw (estructura para leer CSW). Notar que esto ha cambiado en el estado MSD_DATA_OUT para que apunte a msd_buffer para que lea datos del host.

2.7.5.7.

void SendData(byte* dataAddr, byte dataSize)

Esta funcin enva dataSize bytes de datos empezando en la direccin dataAddr.

2.7.5.8.

void MSDDataIn(void)

Esta funcin enva 512B de datos en el msd_buffer al host en trozos de 64B usando MSD_BD_IN. Hay varias condiciones; cuando los datos que se envan son menores que MSD_EP:SIZE y cuando se comprueba la condicin de error bCSWStatus=0x01. En caso de error 0 se llenan y se envan los datos del tamao esperado por el host dCBWDataTransferLength is sent.

73

Documento creado por Slalen para Electronics Strange World

2.7.5.9.

void IsValidCBW()

Comprueba si el CBW es vlido de acuerdo con las especificaciones de la clase almacenamiento masivo. Se considera un CSW vlido si: 1. Se recibe en estado MS_WAIT 2. La longitud de CBW es 1Fh (MSD_CBW_SIZE) 3. dCBWSignature es igual a 0x43425355h

2.7.5.10.

void IsMeaningfulCBW()

Comprueba si el CBW recibido es significativo de acuerdo con las especificaciones de la clase almacenamiento masivo. Un CSW se considera significativo si: 1. No se fijan bits reservados 2. bCBWLUN contiene un LUN vlido soportado por el dispositivo 3. bCBWCBLength y CBWCB tienen concordancia bInterfaceSubClass

con

2.7.5.11.

void PrepareCSWData()

Esto prepara el dato de estado del CSW copiando el dCSWTag del CBWTage y fijando la firma de vlido CSW=53425355h

2.7.5.12.

void MSDInquiryHandler(void)

Esta funcin prepara la repuesta del comando INQUIRY. La repuesta se copia de la ROM al msd_buffer y CSWStatus, se fijan los valores CSWDataResidue.

2.7.5.13.

void ResetSenseData(void)
Sense, inicializando la estructura

Esta rutina resetean el dato RequestSenseResponse gblSenseData.

2.7.5.14.

void MSDReadCapacityHandler()

Esta funcin procesa el dato del registro CSD (leido durante la inicializacin de la tarjeta SD) para encontrar el nmero de bloques (gblNumBLKS) y la longitud del bloque (gblBLKLen). Este dato se copia a msd_buffer y se prepara para responder al comando Leer Capacidad.

2.7.5.15.

void MSDReadHandler(void)

Decodifica el CBWCB del comando READ(10) para calcular el inicio LBA y la longitud de la transferencia (nmero de bloques a leer). Leyendo bloques de 512B de datos de la tarjeta SD en msd_buffer (llamando SectorRead). Si se lee satisfactoriamente (sdcValid), los datos se envan al host en trozos de 64B (MSD_IN_EP_SIZE) (ver MSDDataIN()). Esto se repite para el nmero de bloques TransferLength. En el caso de error bCSWStatus se fija a 0x01 y dato Sense con la clave de dato NOT READY y se prepara el cdigo apropiado ASC, ASCQ.

74

Libreras C18 del USB

2.7.5.16.

void MSDDataOut(void)
con

Efectos secundarios: MSD_BD_OUT.ADR se incrementa MSD_OUT_EP_SIZE (para leer los 64B siguientes en msd_buffer). Esta funcin lee 64B (MSD_OUT_EP_SIZE) de EP1 OUT MSD_BD_OUT.

2.7.5.17.

void MSDWriteHandler()

Decodifica el CBWCB del comando WRITE(10) para calcular el comienzo de LBA y la longitud de la transferencia (nmero de bloques que se escriben). Lee los bloques TransferLength de datos, 1 bloque=512B en un momento en msd_buffer. Los datos del host, 64B en MSD_BD_OUT, se reciben en el msd_buffer (ver MSDDataOut()). El puntero MSD_BD_OUT.ADR se manipula para llenar los 512B del msd_buffer y cuando todos los datos se escriben en la tarjeta SD llamando la funcin Sector Write() (ver sdcard.c). En caso de error bCSWStatus se fija a 0x01 y dato Sense con la clave de dato NOT READY se prepara el cdigo apropiado ASC, ASCQ.

2.7.5.18.

void MSDRequestSenseHandler(void)

Esta funcin prepara el Dato Sense para responder al comando Respuesta Sense. El contenido de la estructura RequestSenseResponse se copia a msd_buffer y se fija un satisfactorio bCSWStatus=0x00.

2.7.5.19.

void MSDModeSenseHandler()

Esta funcin prepara para responder al comando Modo Sense. Se implementa una respuesta bsica en esta versin del cdigo 00h y 0x03 es el tamao del dato (en bytes) que sigue.

2.7.5.20.

void MSDMediumRemovalHandler()

Esta funcin prepara la respuesta al comando Prevent Allow Medium Removal. No se espera una respuesta de datos slo se espera un CSW con comando de ejecucin de estado. Como no se puede controlar la retirada del medio, repondemos con un Success CSW.

2.7.5.21.

void MSDTestUnitReadyHandler()

Esta funcin prepara la respuesta al comando Test Unit Ready. No se espera respuesta de datos, slo se enva un CSW basado en el estado actual de la tarjeta SD se fija un valor de estado de error o de satisfactorio.

2.7.5.22.

void MSDVerifyHandler()

Esta funcin prepara la respuesta al comando Verify. No se espera respuesta de datos, respondemos con un CSW satisfactorio. El comando no se procesa en esta versin del cdigo.

2.7.5.23.

void MSDStopStartHandler()

Esta funcin prepara la respuesta al comando Start Stop Unit. No se espera respuesta de datos, respondemos con un CSW satisfactorio. El comando no se procesa en esta versin del cdigo.

75

Documento creado por Slalen para Electronics Strange World

2.8.

CDC.C: USB DISPOSITIVO DE COMUNICACIN

En este archivo se han creado todas las funciones de transferencia de los datos que desee el usuario en la clase CDC.

2.8.1.

INCLUYE

#include <p18cxxx.h> #include "system\typedefs.h" #include "system\usb\usb.h" #ifdef USB_USE_CDC

2.8.2.

VARIABLES
Longitud total rx Estados definidos en cdc.h Puntero dedicado a la fuente Puntero dedicado al destino Longitud total tx _ROM, _RAM

#pragma udata byte cdc_rx_len; byte cdc_trf_state; POINTER pCDCSrc; POINTER pCDCDst; byte cdc_tx_len; byte cdc_mem_type;

LINE_CODING line_coding; Buffer para almacenar lneas de informacin CONTROL_SIGNAL_BITMAP control_signal_bitmap;

SEND_ENCAPSULATED_COMMAND y GET_ENCAPSULATED_RESPONSE se necesitan para responder de acuerdo a las especificaciones CDC. Sin embargo, realmente no se empieza a usar aqu, se utiliza un buffer por comodidad.
#define dummy_length 0x08 byte dummy_encapsulated_cmd_response[dummy_length];

2.8.3.

DECLARACIONES
#pragma code

2.8.4. 2.8.4.1.

RESPUESTAS ESPECFICAS DE LA CLASE void USBCheckCDCRequest(void)

Esta rutina chequea el paquete de datos setup para ver si este sabe como manipularlo.

76

Libreras C18 del USB

2.9.

API DEL USUARIO void CDCInitEP(void)

2.9.1.1.

CDCInitEP inicializa los Endpoints CDC, buffer descriptores, estados internos mquina y variables. Se tiene que llamar despus de que el host haya enviado una repuesta SET_CONFIGURATION. Ver USBStdSetCfgHandler() en usb9.c para ejemplos.

2.9.1.2.

byte getsUSBUSART(char *buffer, byte len)

Precondicin: El valor del argumento de entrada len tiene que ser menor que el tamao mximo del Endpoint responsable de la recepcin de datos bulk del host para la clase CDC. El argumento de entrada buffer tiene que apuntar a un rea mayor o igual que el tamao especificado por len. Entrada: Buffer: Puntero a donde se guardan los datos recibidos. len: El nmero de bytes esperados. Salida: El nmero de bytes copiados al buffer. Efectos secundarios: Se actualiza la variable de acceso pblico cdc_rx_len con el nmero de bytes copiados al buffer. Para recuperar esta variable llamamos a la macro mCDCGetRxLength(). getsUSBUSART copia un string de bytes recibidos a travs del Endpoint OUT CDC Bulk a una localizacin especificada por el usuario. Es una funcin de no bloqueo. No espera a los datos si no estn disponibles. Devuelve un 0 para notificar que no hay datos disponibles. Nota: Si el nmero actual de bytes recibidos es mayor que el nmero de bytes esperados (len), slo se copian el nmero de bytes esperados. En cambio, si es menor el nmero de los recibidos, se copian todos.

2.9.1.3.

void putsUSBUSART(char *data)


El string de caracteres que apunta data tiene que ser igual o menor de

Precondicin: cdc_trf_state tiene que estar en el estado CDC_TX_READY. 255bytes. Entrada: data: Puntero a un string de datos terminado con nulo. Si no se encuentra, se envan 255bytes al host. putsUSBUSART escribe un string de datos al USB incluyendo caracteres nulos. Utilizar esta versin, puts, para transferir datos localizados en la memoria de datos. Nota: El mecanismo de transferencia para dispositivo-a-host (put) es ms flexible que el de host-a-dispositivo (get). Puede manipular un string de datos mayor que el tamao mximo del Endpoint In bulk. Se utiliza un estado mquina para transferir un long string de datos a travs de mltiples transacciones USB. Ver CDCTxService() para ms detalles.

2.9.1.4.

void putrsUSBUSART(const rom char *data)

Precondicin: cdc_trf_state tiene que estar en el estado CDC_TX_READY. 77

Documento creado por Slalen para Electronics Strange World El string de caracteres que apunta data tiene que ser igual o menor de 255bytes. Entrada: data: Puntero a un string de datos terminado con nulo. Si no se encuentra, se envan 255bytes al host. putrsUSBUSART escribe un string de datos al USB incluidos los caracteres nulos. Utilizar esta versin, puts, para transferir datos localizados en la memoria de programa. Nota: El mecanismo de transferencia para dispositivo-a-host (put) es ms flexible que el de host-a-dispositivo (get). Puede manipular un string de datos mayor que el tamao mximo del Endpoint In bulk. Se utiliza un estado mquina para transferir un long string de datos a travs de mltiples transacciones USB. Ver CDCTxService() para ms detalles.

2.9.1.5.

void CDCTxService(void)

CDCTxService une las transacciones dispositivo-a-host. Hay que llamar a esta funcin una vez por cada loop del programa Main.

78

Libreras C18 del USB

2.10.

HID.C: USB INTERFAZ CON HUMANOS

En este archivo se han creado todas las funciones de transferencia de los datos que desee el usuario en la clase HID.

2.10.1.

INCLUYE

#include <p18cxxx.h> #include "system\typedefs.h" #include "system\usb\usb.h" #ifdef USB_USE_HID

2.10.2.

VARIABLES

#pragma udata byte idle_rate; byte active_protocol; byte hid_rpt_rx_len;

[0] Protocolo de inicio [1] Protocolo de informe

2.10.3.

PROTOTIPOS PRIVADOS

void HIDGetReportHandler(void); void HIDSetReportHandler(void);

2.10.4.

DECLARACIONES

#pragma code

2.10.5. 2.10.5.1.

RESPUESTAS ESPECFICAS DE LA CLASE void USBCheckHIDRequest(void)

Esta rutina chequea el paquete de datos especfico para ver si sabe como manipularlo.

2.10.6. 2.10.6.1.

API DEL USUARIO void HIDInitEP(void)

HIDInitEP inicializa los Endpoints HID, buffer descriptores, estados internos mquina y variables. Se tiene que llamar despus de que el host haya enviado una repuesta SET_CONFIGURATION. Ver USBStdSetCfgHandler() en usb9.c para ejemplos.

79

Documento creado por Slalen para Electronics Strange World

2.10.6.2.

void HIDTxReport(char *buffer, byte len)

Precondicin: mHIDTxIsBusy() tiene que devolver falso. El valor de len tiene que ser menor o igual que HID_INT_IN_EP_SIZE. Para un Endpoint interrupcin, el tamao del buffer mximo es de 64bytes. Entrada: buffer: Puntero al comienzo de la localizacin de bytes de datos. len: Nmero de bytes que se van a transferir. Utilizar esta macro para tranferir datos localizados en la memoria de datos. Aplicacin tpica:
if(!mHIDTxIsBusy()) HIDTxReport(buffer, 3);

2.10.6.3.

byte HIDRxReport(char *buffer, byte len)

Precondicin: El valor del arguemento de entrada len tiene que ser menor que el tamao mximo del Endpoint responsable de la recepcin de datos del host USB para la clase HID. El argumento de entrada buffer tiene que apuntar a un rea mayor o igual al tamao especificado por len. Entrada: buffer: Puntero al lugar donde se guardan los datos recibidos. len: Nmero de bytes que se esperan. Salida: Nmero de bytes copiados al buffer. Efectos secundarios: Se actualiza la variable de acceso pblico hid_rpt_rx_len con el nmero de bytes copiados al buffer. Para recuperar esta variable llamamos a la macro mHIDGetRptRxLength(). HIDRxReport copia un string de bytes recibidos a travs del Endpoint OUT HID a una localizacin especificada por el usuario. Es una funcin de no bloqueo. No espera a los datos si no estn disponibles. Devuelve un 0 para notificar que no hay datos disponibles. Nota: Si el nmero actual de bytes recibidos es mayor que el nmero de bytes esperados (len), slo se copian el nmero de bytes esperados. En cambio, si es menor el nmero de los recibidos, se copian todos.

80

Libreras C18 del USB

2.11.

MAIN.C

Este es el archivo de inicio. En l se incluyen las funciones necesariar para establecer la comunicacin USB y las relativas a la aplicacin del usuario.

2.11.1.

INCLUYE
Requerido Requerido Requerido

#include <p18cxxx.h> #include "system\typedefs.h" #include "system\usb\usb.h" #include "io_cfg.h"

#include "system\usb\usb_compile_time_validation.h" #include "user\user_mouse.h"

Opcional Modificable

2.11.2. 2.11.3.

VARIABLES PROTOTIPOS PRIVADOS

#pragma udata

static void InitializeSystem(void); void USBTasks(void);

2.11.3.1.

Remapeo de vectores

extern void _startup (void); #pragma code _RESET_INTERRUPT_VECTOR = 0x000800 void _reset (void) { _asm goto _startup _endasm }

2.11.3.2.
#pragma code

Declaraciones

void main(void)
void main(void) { InitializeSystem(); while(1) { USBTasks() ProcessIO(); } end while } end main

USB Tasks Aqui se llama al programa del usuario

static void InitializeSystem(void)

81

Documento creado por Slalen para Electronics Strange World InitializeSystem es una rutina centralizada de inicializacin. Todas las rutinas de inicializacin se llaman desde aqu.
static void InitializeSystem(void) { ADCON1 |= 0x0F;

Por defecto todos los pines en digital

#if defined(USE_USB_BUS_SENSE_IO) tris_usb_bus_sense = INPUT_PIN; Ver io_cfg.h #endif #if defined(USE_SELF_POWER_SENSE_IO) tris_self_power = INPUT_PIN; #endif mInitializeUSBDriver(); UserInit(); } end InitializeSystem Ver usbdrv.h inicializacin del usuario

void USBTasks(void)
Precondicin: Se tiene que haber llamado InitializeSystem Da vueltas dando servicio a las tareas USB.
void USBTasks(void) {

Da servicio al Hardware
USBCheckBusStatus(); if(UCFGbits.UTEYE!=1) USBDriverService(); } end USBTasks se tiene que utilizar el mtodo obtener Mtodo interrupcin u obtener

82

Libreras C18 del USB

2.12.

INTERRUPT.C

En este archivo se declaran la parte del programa que se ejecuta durante una interrupcin.

2.12.1.

INCLUYE

#include <p18cxxx.h> #include "system/typedefs.h" #include "system/interrupt/interrupt.h"

2.12.2.

VECTORES DE INTERRUPCIN

#pragma code high_vector=0x08 void interrupt_at_high_vector(void) { _asm goto high_isr _endasm } #pragma code #pragma code low_vector=0x18 void interrupt_at_low_vector(void) { _asm goto low_isr _endasm } #pragma code

2.12.3. 2.12.3.1.

DECLARACIONES void high_isr(void)

#pragma interrupt high_isr void high_isr(void) { }

2.12.3.2.

void low_isr(void)

void low_isr(void) { } #pragma code

83

Vous aimerez peut-être aussi