Presentation
Intro to USB - USB in nutshell (teach thing give demo in pyUSB)
Hub connected to USB function. one host many function (diagramn). host communicate by sending packets to host. Each USB transaction consists of serveral packets mainly token packet, data packet and status packet.
There are four types of packets - Token packet (sub divided into in our setup), data pacekt (sub divided into data0 and data1) , handhshake packet (sub divided into ACK, NAK, STALL, start of frame packet
Each packet has certain fields
Sync PIDvalue (4bit decide what kind of packet/subpacket) - 7bit address of device (127 devices) - 4-bit Endpoint (16end point possible) - Cycle redudency check - End of teoken
he Universal Serial Bus specification defines four transfer/endpoint types,
Because ther is so many ways, you define something called USB class
Device descroptor (e device descriptor includes information such as what USB revision the device complies to, the Product and Vendor IDs used to load the appropriate drivers and the number of possible configurations the device can have.)
- Configuration descriptor (power options)
-- interface descriptor
-- Endpoint descriptor
Demo descriptor
lsusb -vv
connect atmel avrisp2 connector and go through device descroptor
For example you could have a multi-function fax/scanner/printer device. Interface descriptor one could describe the endpoints of the fax function, Interface descriptor two the scanner function and Interface descriptor three the printer function. Unlike the configuration descriptor, there is no limitation as to having only one interface enabled at a time.
Go detail each function has address and endpoints. Every device has E0 in and E0out, rest depends upon your device. Host come to know about it with device descriptor.
- Start with pyUSB, tell how all devices are connected, getting there ID etc.
https://github.com/walac/pyusb/blob/master/docs/tutorial.rst
Implementation
Hardware consideration - 3.3V schottky diode, pull-up resisotr
Zener diodes come with a broad range of characteristics, especially at low currents, results may not be reproducible.
http://vusb.wikidot.com/hardware
Hardware consideration - 3.3V schottky diode, pull-up resisotr
Zener diodes come with a broad range of characteristics, especially at low currents, results may not be reproducible.
http://vusb.wikidot.com/hardware
Software :Firmware-only Implimentation
V-USB
Demo - Easylogger/keyboard
http://www.obdev.at/products/vusb/easylogger.html
http://codeandlife.com/2012/02/22/v-usb-with-attiny45-attiny85-without-a-crystal/
- Change fabISP crystal to 12MHz
- Change fabISP crystal to 12MHz
Demo-
Download from here
Go to examples, change makefile use what you are using, fuses etc. Burn the code. This will do
Download from here
Go to examples, change makefile use what you are using, fuses etc. Burn the code. This will do
Dedicated USB-Controller
atmega32u4 has in built usb-driver (search datasheet) show datasheet connection, inbuilt 3.3V regulator. Now every vendor has there own library files. Fortunately, for avr there is free library called lufa
LUFA tutorial
http://www.mcqn.com/weblog/running_lufa_at90usbkey2_ubuntu
- Download LUFA .zip file extract t. you need doxygen for documentation in ubutu type
sudo apt-get install doxygen
once installed navigate to root directory of LUFA and type
make doxygen
- Download LUFA .zip file extract t. you need doxygen for documentation in ubutu type
sudo apt-get install doxygen
once installed navigate to root directory of LUFA and type
make doxygen
navigate to root/LUFA/Documentation
note - there are many documentaiton in the website look for your version. For latest below is the link
http://www.fourwalledcubicle.com/files/LUFA/Doc/140928/html/
-call with "make all" to rebuild everything, "make clean" to clean everything,
note - there are many documentaiton in the website look for your version. For latest below is the link
http://www.fourwalledcubicle.com/files/LUFA/Doc/140928/html/
-call with "make all" to rebuild everything, "make clean" to clean everything,
Demo
Mouse done
keyboard - done
Virtual port - done
serial port as ttyACM0
- AnalogOut (show in device system setting - sound)
- virtual serial port
-- before using any demo you would need its documentation file. go to perticular demo folder and run "make doxygen" this will create a folder called "Documentaiton" and inside it html, and run index.html
Board file, Drivers/Board has various .h files which provide corresponding .h file for various boards. For example if Drivers/Board/joystic.h is included in project and board is say USBKEY then this "Dirvers/Board/Joystic.h" will provide path for "AVR8/USBKEY/Joystic.h" . if the file is not there then it will look for "Board/Joystic.h" so if adding some hardware to say micro inorder for it to be include create folder "Board" inside "Driver/Board" folder and keep all header file.
-- before using any demo you would need its documentation file. go to perticular demo folder and run "make doxygen" this will create a folder called "Documentaiton" and inside it html, and run index.html
Board file, Drivers/Board has various .h files which provide corresponding .h file for various boards. For example if Drivers/Board/joystic.h is included in project and board is say USBKEY then this "Dirvers/Board/Joystic.h" will provide path for "AVR8/USBKEY/Joystic.h" . if the file is not there then it will look for "Board/Joystic.h" so if adding some hardware to say micro inorder for it to be include create folder "Board" inside "Driver/Board" folder and keep all header file.
- LUFA keyboard mouse sparkfun tutorial
commands
lsusb
- lists all usb devices in linux
First off you need to install the tools required to compile things for AVR chips, and the programmer used to flash the devices:
$ sudo apt-get install gcc-avr binutils-avr avr-libc avrdude
http://www.nongnu.org/avr-libc/user-manual/install_tools.html
Blinky example
#include#define F_CPU 1000000UL // 1 MHz #include int main() { DDRB |= 1; // LED on PB0 while(1) { PORTB |= 1; // Turn LED on _delay_ms(500); PORTB &= ~1; // Turn LED off _delay_ms(500); } return 1; }
Introduction
Developing USB devices is a two part job, one side you have to develop USB perhipheral device (called "USB function" according to usb standards) and a USB host. Here, we will use libusb/pyusb for host side programing and STM32F4Discovery board for USB function. We will first start with USB host programing and then gradually move to developing usb peripheral devices
USB Host Programming
USB is host centric. USB host initiate all transaction and controls all data communication. Host sends data in from of packets.
| USB Host | --> packet --> packet --> packet --> | USB Peripheral device |
Each packet has bits for
Sync | Packet ID | Address of Device | End Point | Cycle Redundancy | End of Packet |
Sync - To sync with clock. It consist of 8 bits for FS and 32 bits for HS usb. The last two bits tell when packet ID starts.
Packet ID - Determines group of packete and also specify which packet in that group
These packets can be classified into four types of "packet -group"
1 - Token Packet - It send at the beginning of every communication and indicate type of transaction to follow.
2- Data Packet - It carries the data to be transfered i.e. payload
3 - Handshake Packet - Acknowledge data or report error
4 - Special Packet -
Open terminal and type following command:
lsusb -vv
This will output list of all the usb function connected to your computer. Lets write driver for one of these device.
Install pyUSB
sudo apt-get update
sudo apt-get install libusb-dev
sudo apt-get install python
sudo apt-get install python-usb
sudo apt-get install python-pip
sudo pip install --upgrade pyusb
To test success full installation
python
import usb.core
dev = usb.core.find()
dev
dev
The loading of the appropriate driver is done using a PID/VID (Product ID/Vendor ID) combination. The VID is supplied by the USB Implementor's forum at a cost
Isochronous allows a device to reserve a defined amount of bandwidth with guaranteed latency
USB supports Control, Interrupt, Bulk and Isochronous transfers.
Start with this
http://www.beyondlogic.org/usbnutshell/usb3.shtml
While developing always thinks in term of host. For example IN packate for device is host asking for input data or read data.
Editing the VCP for Discovery board code
- In code when you send a data, the code will sent it to Tx, Rx will recieve it and intrupt code will be executed, now Rx recieving code should be thre in the intruppt code else the uC will not come out of intruppt.
Developing Driver
the output should be something like
To test VendorID and ProductID of your devices, simply create "getdevices.py" with following code
#!/usr/bin/python
import sys
import usb.core
# find USB devices
dev = usb.core.find(find_all=True)
# loop through devices, printing vendor and product ids in decimal and hex
for cfg in dev:
sys.stdout.write('Decimal VendorID=' + str(cfg.idVendor) + ' & ProductID=' + str(cfg.idProduct) + '\n')
sys.stdout.write('Hexadecimal VendorID=' + hex(cfg.idVendor) + ' & ProductID=' + hex(cfg.idProduct) + '\n\n')
import sys
import usb.core
# find USB devices
dev = usb.core.find(find_all=True)
# loop through devices, printing vendor and product ids in decimal and hex
for cfg in dev:
sys.stdout.write('Decimal VendorID=' + str(cfg.idVendor) + ' & ProductID=' + str(cfg.idProduct) + '\n')
sys.stdout.write('Hexadecimal VendorID=' + hex(cfg.idVendor) + ' & ProductID=' + hex(cfg.idProduct) + '\n\n')
save it and run it
python getdevices.py
You will get a list of connected devices. Connect a STM32Disc board (after uploading VCP code) device and run the code again. A new entry will appear in the list. This is your products VendorID and productID. Most likely it will be
VendorID = 0x483 and ProductID = 0x5740
Now, open VCP project and in usbd_desc.c change the entry
#define USBD_VID 0x0482
save and recompile and burn it to board. run the getdevices.py again and you should see the vendorID updated.
VCP implimentation is FS. During running code DIEPCTL1 and DOEPCTL1 changes value when data sent from terminal.
Device descriptor can have many configuration( although most of them just have one configuration), this can be check my value bNumConfiguration. Each configuration can have multiple interfaces.
STM32 VCP code is detected as ttyACM0 (ls /dev)
Once you connect the board, Ubuntu will read the device descriptor and based on entry in "bDevcieClass" for CDC its 02h and hence in VCP code in usbd_cdc_core.c its its set as 0x02. To make sure OS doesn't load default COM port driver, change this value to 0xFF (which means class code is vendor specified, see here) . SB defines class code information that
is used to identify a device’s functionality and to nominally load a
device driver based on that functionality. SB defines class code information that is used to identify a device’s functionality and to nominally load a device driver based on that functionality. There are two places on a device where class code information can be placed.One place is in the Device Descriptor, and the other is in Interface Descriptors
- a serial port may have set two Interrupt endpoints for transferring data in and out and then a control endpoint for setting the baud rate. For stm32f4 vcp, The CDC core uses two endpoint/transfer types:
● Bulk endpoints for data transfers (1 OUT endpoint and 1 IN endpoint). EP1 out (bulk) and EP1 IN (bulk)
● Interrupt endpoints for communication control (CDC requests; 2 IN endpoint). EP2 IN (interrupt type).
- a serial port may have set two Interrupt endpoints for transferring data in and out and then a control endpoint for setting the baud rate. For stm32f4 vcp, The CDC core uses two endpoint/transfer types:
● Bulk endpoints for data transfers (1 OUT endpoint and 1 IN endpoint). EP1 out (bulk) and EP1 IN (bulk)
● Interrupt endpoints for communication control (CDC requests; 2 IN endpoint). EP2 IN (interrupt type).
#define CDC_IN_EP 0x81 /* EP1 for data IN */
#define CDC_OUT_EP 0x01 /* EP1 for data OUT */
#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */
configuration descriptor and all other descriptor is defined in library usbd_cdc_core.c. You can varify the output of lsusb -vv with the data in this file.
ediging usbd_cdc_core.c
- removed HS core code.
ST Library
usbd_cdc_core.c manages all CDC communication and uses lower level drive to access hardware. usbd_cdc_core.c talks to usbd_cdc_vcp.c using following structure -
typedef struct _CDC_IF_PROP
{
uint16_t (*pIf_Init) (void);
uint16_t (*pIf_DeInit) (void);
uint16_t (*pIf_Ctrl) (uint32_t Cmd, uint8_t* Buf, uint32_t Len);
uint16_t (*pIf_DataTx) (uint8_t* Buf, uint32_t Len);
uint16_t (*pIf_DataRx) (uint8_t* Buf, uint32_t Len);
}
CDC_IF_Prop_TypeDef;
above structure is defined in usbd_cdc_core.h , is defined as
extern CDC_IF_Prop_TypeDef APP_FOPS;
in usbd_cdc_core.c and in usbd_conf.h defines APP_FOPS as VCP_FOPS. In short usbd_cdc_core.c is accessing functions defined in usb_cdc_vpc.c files.
in STM32F4 USB_Rx_Buffer(unsignedchar[64]) stores all the data. So if you send dev.write(1,'test',1) then this buffer if wateched in watch window will show you 'test'. App_Rs_Buffer (unsignedchar[2048]) stores data that is to be sent to host.
Functions defined in usb_dcd.c
DCD_EP_Tx - Transmit data over USB
- 03/19/14
USB1 has only bulk interrupts, pyusb can send data.
- While defining descriptor make sure wTotalLength is properly set. I was removing other times form descriptor keeping wTotalLength same which created read problem. Modified the code so that it can return exactly what I typed. Modified cdc_vcp.c functions.
03/21/14
An unsigned char is a (unsigned) byte value (0 to 255). In code USB_Rx_Buffer is [64] and each of the bite value can be seen in debug mode if you expand it.
Adding USB capability to your project
-Files needed
-- usbd_conf.h
To change USB IN data size change
#define APP_RX_DATA_SIZE 20 /* Total size of IN buffer: in 2048 */
#define APP_FOPS VCP_fops
--usbd_desc.c - Defines usb descriptor and string format.
#define USBD_VID 0x0483
#define USBD_PID 0x5740
--usb_regs.h
change
#define USB_OTG_FS_MAX_PACKET_SIZE 64
#define USB_OTG_MAX_EP0_SIZE 64
usbd_cdc_core.c
"__ALIGN_BEGIN uint8_t USB_Rx_Buffer [CDC_DATA_MAX_PACKET_SIZE] __ALIGN_END
__ALIGN_BEGIN uint8_t APP_Rx_Buffer [APP_RX_DATA_SIZE] __ALIGN_END ;
usbd_cdc_vcp.c/.h
usbd_usr.c/h For user application interface.
Note - usbd_cdc_core.c talks to usbd)cdc_vcp.c using CDC_IF_Prop_TypeDef pointer which is defined in usbd_cdc_core.h
ediging usbd_cdc_core.c
- removed HS core code.
ST Library
usbd_cdc_core.c manages all CDC communication and uses lower level drive to access hardware. usbd_cdc_core.c talks to usbd_cdc_vcp.c using following structure -
typedef struct _CDC_IF_PROP
{
uint16_t (*pIf_Init) (void);
uint16_t (*pIf_DeInit) (void);
uint16_t (*pIf_Ctrl) (uint32_t Cmd, uint8_t* Buf, uint32_t Len);
uint16_t (*pIf_DataTx) (uint8_t* Buf, uint32_t Len);
uint16_t (*pIf_DataRx) (uint8_t* Buf, uint32_t Len);
}
CDC_IF_Prop_TypeDef;
above structure is defined in usbd_cdc_core.h , is defined as
extern CDC_IF_Prop_TypeDef APP_FOPS;
in usbd_cdc_core.c and in usbd_conf.h defines APP_FOPS as VCP_FOPS. In short usbd_cdc_core.c is accessing functions defined in usb_cdc_vpc.c files.
in STM32F4 USB_Rx_Buffer(unsignedchar[64]) stores all the data. So if you send dev.write(1,'test',1) then this buffer if wateched in watch window will show you 'test'. App_Rs_Buffer (unsignedchar[2048]) stores data that is to be sent to host.
Functions defined in usb_dcd.c
DCD_EP_Tx - Transmit data over USB
- 03/19/14
USB1 has only bulk interrupts, pyusb can send data.
- While defining descriptor make sure wTotalLength is properly set. I was removing other times form descriptor keeping wTotalLength same which created read problem. Modified the code so that it can return exactly what I typed. Modified cdc_vcp.c functions.
03/21/14
An unsigned char is a (unsigned) byte value (0 to 255). In code USB_Rx_Buffer is [64] and each of the bite value can be seen in debug mode if you expand it.
Adding USB capability to your project
-Files needed
-- usbd_conf.h
To change USB IN data size change
#define APP_RX_DATA_SIZE 20 /* Total size of IN buffer: in 2048 */
#define APP_FOPS VCP_fops
--usbd_desc.c - Defines usb descriptor and string format.
#define USBD_VID 0x0483
#define USBD_PID 0x5740
--usb_regs.h
change
#define USB_OTG_FS_MAX_PACKET_SIZE 64
#define USB_OTG_MAX_EP0_SIZE 64
usbd_cdc_core.c
"__ALIGN_BEGIN uint8_t USB_Rx_Buffer [CDC_DATA_MAX_PACKET_SIZE] __ALIGN_END
__ALIGN_BEGIN uint8_t APP_Rx_Buffer [APP_RX_DATA_SIZE] __ALIGN_END ;
usbd_cdc_vcp.c/.h
usbd_usr.c/h For user application interface.
Note - usbd_cdc_core.c talks to usbd)cdc_vcp.c using CDC_IF_Prop_TypeDef pointer which is defined in usbd_cdc_core.h
The Setup Packet
Every USB device must respond to setup packets on the default pipe. The setup packets are used for detection and configuration of the device, setting device address, requesting device descriptor or checking the status of a endpoint.
In STM32 this is taken care by structure usb_setup_req and is defined in usb_core.h.
typedef struct usb_setup_req {
uint8_t bmRequest;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} USB_SETUP_REQ;
uint8_t bmRequest;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} USB_SETUP_REQ;
Request type can be standard (further divided into standard, interface and endpoint) or Class specific.
This structure is used in setup stage function USBD_SetupStage() decide if its standard device request, interface request or endpoint request and accordingly calls the functions.
This structure is used in usbd_cdc_core.c to take care of cdc class specific requests. This class specific request are then handle by usb_cdc_vcp.c
To change packet size of IN/OUT EP change following value in usbd_conf.h
#define CDC_DATA_MAX_PACKET_SIZE 64
#define APP_RX_DATA_SIZE 2048
Starting a Keil Project From Scratch
Create a Folder "Project Name" and inside it create folder "MDK-ARM" . We want to keep all the files seperate from uVision folder so that the project can be easily ported to new IDE.
1. Select Project > New uVision Project
2. Select Device for Target ‘Target 1’ - STMicroelectronics > STM32F407VG
2. Select Device for Target ‘Target 1’ - STMicroelectronics > STM32F407VG
In Manage run time environment - do nothing
Go to project- manage-component, environments groups and rename Target1 and group. Create main.c and save it one folder outside location of "MDK-ARM"
Note - When writing tutorial, first mention directory structure as it can be confusing.
copy "Utilities" folder in "Project Name" folder. Now add "stm32f4_discovery.c" to the "User" group, this file is inside Utilities" folder
Crate a new group"MDK-ARM" in "Project Target", copy startup_stm32f4xx.s inside "MDK-ARM" folder and add this file to newly created "MDK-ARM" group.
While adding usb to other project make sure to add usb interrupt functions interrupt file in in stm32f4xx_it (both in .c and .h)
/**
* @brief This function handles EXTI15_10_IRQ Handler.
* @param None
* @retval None
*/
#ifdef USE_USB_OTG_FS
void OTG_FS_WKUP_IRQHandler(void)
{
if(USB_OTG_dev.cfg.low_power)
{
*(uint32_t *)(0xE000ED10) &= 0xFFFFFFF9 ;
SystemInit();
USB_OTG_UngateClock(&USB_OTG_dev);
}
EXTI_ClearITPendingBit(EXTI_Line18);
}
#endif
/**
* @brief This function handles OTG_FS Handler.
* @param None
* @retval None
*/
void OTG_FS_IRQHandler(void)
{
USBD_OTG_ISR_Handler (&USB_OTG_dev);
}
* @brief This function handles EXTI15_10_IRQ Handler.
* @param None
* @retval None
*/
#ifdef USE_USB_OTG_FS
void OTG_FS_WKUP_IRQHandler(void)
{
if(USB_OTG_dev.cfg.low_power)
{
*(uint32_t *)(0xE000ED10) &= 0xFFFFFFF9 ;
SystemInit();
USB_OTG_UngateClock(&USB_OTG_dev);
}
EXTI_ClearITPendingBit(EXTI_Line18);
}
#endif
/**
* @brief This function handles OTG_FS Handler.
* @param None
* @retval None
*/
void OTG_FS_IRQHandler(void)
{
USBD_OTG_ISR_Handler (&USB_OTG_dev);
}
No comments:
Post a Comment