I have designed system based on STM32L151. It uses usb for powering/charging and communicating to laptop. My system uses Embedded File System (SPI, 8MB) without RTX, USB(CDC Class), given by ST. I have typical problem and did not find any answer on net and from ST. As long I do not any request from PC on USB to system, things are OK, i.e. I can store and send the file from system to laptop on USB. But if I send any request from Laptop like configuration/reading of file etc, sending file to PC does not work. While digging, I found that lower level fopen function generate hard fault exception, hinting wrong memory access (data address invalid). It happens only when there is req from host, else device can send file without any problem to host by system keypad operation. I suspect that when EP_OUT is called, it is damaging the RAM area, which used by fopen function, like file information etc. I am new to USB, much can not do myself. I have 2K Stack and 1K heap, no of files opened at a time are 2. Is anybody, faced problem like this, if yes, how they solved. Is there any simple example to handle similar case, I do not need serial handling in system. Thanks in advance.
> Is there any way to use Circular buffer implementation for CDC/USB to speed the transmission and save RAM.
On the ST CDC example, EP1_IN_Callback() splits data on large buffer, USART_Rx_Buffer, into 64 bytes (or less) packet. You may extend this implemntation into a cyclic buffer. A couple of problems you may meet with are,
1-1) word (two-bytes) access of USB RAM The data on the cyclic buffer is copied to the USB RAM using UserToPMABufferCopy() When the data on the buffer spans from the end of cyclic buffer to the top of the buffer (buffer wrap around), you may need a trick to do this job, for example, - copy the data into a temporary buffer once, and apply UserToPMABufferCopy() to this temporary buffer. The access to the USB RAM is restricted to word access. If the first portion of the data has odd number, you need to bind it with the later portion before UserToPMABufferCopy() is applied.
1-2) CDC bulk IN transfer requires short-packet termination. A large size transfer is split into 64 bytes (or less) packets on the USB line. When a transfer ends with a 64 bytes packet, bulk IN endpoint requires a ZLP (Zero-Length Packet), to indicate transfer termination.
// send ZLP SetEPTxCount(ENDP1, 0); SetEPTxValid(ENDP1);
1-3) Start trigger of transfer. EP1_IN_Callback() is called just when a transaction (packet) finishes. To start a sequence of transactions, your firmware has to call EP1_IN_Callback() explicitly.
On EP3_OUT_Callback(), you'll implement another cyclic buffer, like EP1_IN_Callback() Here are another problems on this implementation.
2-1) word access PMAToUserBufferCopy() (in USB_SIL_Read()) expects a target buffer, alligned in word boundary. You'll need some trick to copy the packet into odd address.
2-2) Flow control When the cyclic buffer is full, the copy from the USB RAM to the buffer is deferred until the data on the buffer is consumed. Your firmware has to give chances to poll this condition in SOF interrupt.
> Does KEIL USB library uses Circular buffer? Keil doesn't have USB CDC example for STM32L15x (nor STM32F103x, which has almost same USB peripheral)
> How to increase the size of Tx/Rx Packet and Place of changes in files.
On the device side, firmware exchanges 64 bytes (or less) packets over the USB peripheral. To move large-size transfer, your firmware has to split/gather the packets into full transfer. On the PC side, PC host controller does this job. Your PC application doesn't need to be aware of the packet size, at all. PC application can send/ receive large size transfer in single write/read call.
Tsuneo