Dodgy MCU vendor code - Page 1
Forum section: electronics / general

author: AlfBaz
author_rank: Super Contributor
timestamp: January 16, 2014, 03:35:43 pm
content: So I'm trying to get some example usb cdc code to work on an STM32f4 discovery board using some of their example code and I'm getting a hard fault.I'm sending a 1024 byte buff to the host by calling one of their data tx functions. my buffer is copied into the usb's buffer who's max size is 2048This is their codeCode:uint16_t VCP_DataTx(uint8_t* Buf, uint32_t Len){uint32_t i;for (i = 0; i < Len; i++) {APP_Rx_Buffer[APP_Rx_ptr_in++] = *(Buf + i);}/* To avoid buffer overflow */if(APP_Rx_ptr_in == APP_RX_DATA_SIZE) {APP_Rx_ptr_in = 0;}return USBD_OK;}It seems to me the only way that construct would work is if I only sent one byte at a time which defeats the purpose of having the Len param.Curious, I did a quick search and found an earlier version of this file on githubCode:while (i < Len) {APP_Rx_Buffer = *(Buf + i);APP_Rx_ptr_in++;i++;/* To avoid buffer overflow */if (APP_Rx_ptr_in == APP_RX_DATA_SIZE)APP_Rx_ptr_in = 0;}Looks like they may have spotted the closing brace on the for statement if they placed the opening one on the next line.

author: C
author_rank: Super Contributor
timestamp: January 17, 2014, 02:52:51 am
content: QuestionAm I reading that code correctlyCode:if(APP_Rx_ptr_in == APP_RX_DATA_SIZE) {APP_Rx_ptr_in = 0;The second example has a loop around this codeso your incoming data is copied to APP_Rx_Buffer until the above is true then index gets reset to 0 and you then overwrite copied data and overwrite copied data until you reach the end of your incoming dataThis sounds like a data loss to meWhile the first example is a buffer over run possibility and always says it's good with that above code only happening to reset the index on the rare times it matches on exit?C

author: AlfBaz
author_rank: Super Contributor
timestamp: January 17, 2014, 04:34:30 am
content: Yeah I'm at a bit of a loss to explain the thinking (or not) behind it either. I've looked at all references to APP_Rx_ptr_in index variable throughout the entire project and nowhere is it decremented, only assigned to zero if itsequalto the max buffer size, so unless you only ever send equal multiples that add to the max buff size your screwed!It would prevent an overrun in the second example (which is an earlier version!) but your point about over-writing comes into play. The only thing I can think of (still looking into it) is that some periodic usb isr transfers the contents into the actual USB buffer and is transmitted before it's over-written, but this scenario seems lame even by my standards

author: C
author_rank: Super Contributor
timestamp: January 17, 2014, 05:22:23 am
content: Is this example the same for all the different versions of chips with USB?Just wondering if someone had a "better idea" when they code checked for operation on the F4 from the previous examples that work on the older chips.C

author: zapta
author_rank: Super Contributor
timestamp: January 17, 2014, 05:39:47 am
content: Quote from: AlfBaz on January 16, 2014, 03:35:43 pmIn your case, the overflow will be correct and will happen after every other send. This may be the scenario that they used to test. If you can send arbitrary sizes that their code is incorrect.Even the original code seems to be sloppy for a driver. They could compute the overflow before the loop and do the copying using one or two memcpy rather than incrementing indexes and comparing on each iteration.

author: AlfBaz
author_rank: Super Contributor
timestamp: January 17, 2014, 10:39:26 am
content: Quote from: C on January 17, 2014, 05:22:23 amThe newer version is example code + libraries that accompany F105xx, F107xx, F2xx and F4xx OTG host and device library User Manual.The library section is almost identical to the one you d/l for the F4 series except it has extra files that help interface to lower levels if you want to run a virtual com port.The example project is meant to convert your dev board into a usb->RS232 converter and judging from one of the header files supports a plethora of ST dev boards depending on the symbols you define

author: amyk
author_rank: Super Contributor
timestamp: January 17, 2014, 11:49:17 am
content: I have no idea what they were thinking when they wrote that... if APP_Rx_ptr_in ever goes beyond the buffer it never gets reset again, and in the first loop you can easily do that and copy past the end of the buffer. Maybe the code relies on you always transferring APP_RX_DATA_SIZE bytes?

author: C
author_rank: Super Contributor
timestamp: January 17, 2014, 12:48:44 pm
content: I may get this correct.This is the the transmit out function that should1. take a max of a very huge number of bytes and a min byte count of 0 but you could live with 1 byte.2. In the case of #1 being greater then USB max packet transmit sizeFill any remaining space in a partially filled buffer thenloop reducing the count of #1 by the USB max packet transmit size. And then shift to #4 for remaining data.3. For #2 this could be directly to the output packet buffer or to a number of packet buffers of which there would probably be a limited amount.4. in the case of #1 being less than or equal to USB max packet transmit size.You have option of transmitting a short packet now or buffering the less than max packet data and adding a transmit delay for no longer then X amount of time in the hopes that more input data will arrive to fill the packet before that time. And this timing would have to be done in a safe way to prevent a race condition.5. At some point there will exist more data to go out then buffer space so there will be a need for some kind of delay loop to allow this back log to clear. This will create problems that will have to be handled. A lock up due to USB cable being disconnected while trying to transmit comes to mind.And to add to the fun, the above could be an intermediate chunk of code that is taking it's input data from a circular buffer and you have a second chunk of code preforming the same actions getting the data in to the circular buffer.And the reason for all this is to get it in a standard format for the USB controller to transmit and out of the control of the main program which could if it still had control could delete the data before or during the USB transmission.And then you need to handle all the errors that could happen even if this was rock solid code, one error like USB cable being disconnected before or during this data output. And for this error handling there could be a the need to know what was transmitted with no errors. What to do with the buffered data on reconnection. And a whole other what to do's.And to me this all sounds like a very common need for USB. Moving data to/from hardware, buffers and program data.With USB having many data streams possible, I would think that a better software design would allow for more then one virtual serial port from the start. You could then easily put to use the many serial ports these chips have.So thisCode:uint16_t VCP_DataTx(uint8_t* Buf, uint32_t Len)would be written asCode:uint16_t VCP_DataTx(uint8_t Port, uint8_t* Buf, uint32_t Len)C

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: January 17, 2014, 01:21:36 pm
content: Yes the example code does 'seem' borked.Does the vanilla example work as expected?I assume it somehow does, so you might be able to step through it, or even just see how the function is called.Maybe Len is always some magically correct number.I've been having a bit of a battle with STM example code too, but luckily nothing was wrong with the STM libraries, just the example.

author: AlfBaz
author_rank: Super Contributor
timestamp: January 17, 2014, 02:05:25 pm
content: Hey C, thanks very much for that. Some very good techniques for handling a buffer in any function. At this point in time I need to get my head around the peripherals method of transmitting data. I need to read the data sheet and decipher what the lib does with APP_Rx_Buffer. From what I have seen so far it takes the address of that buffer and embeds it deep in a bunch of obscure structures so it's difficult to follow the code as it appears that an isr somewhere uses this data via the multiple structure paths.To compound the matter I have just found that the index and buffer are also used for received data, where I imagined there would be separate buffers for IN and OUT endpointsQuote from: HackedFridgeMagnet on January 17, 2014, 01:21:36 pmYes it does work but I've gotten rid of all the UART stuff as I don't need it. This may be half the problem. The deleted code may well have just sent single bytes to the USB host as it received it from the UART and is why (if they bothered testing the code) they may not have picked up on this bodgie function.Stepping through the code can be a bit troublesome as the USB device needs to respond to the host immediately and I'm pretty sure when GDB halts the processor the peripherals (USB in this case) are halted also

author: C
author_rank: Super Contributor
timestamp: January 17, 2014, 02:22:16 pm
content: Try this idea on for size.This is suppose to be a virtual serial port.A true virtual serial port would have the same software functions and act like just like a real serial port.They should just work the same. Great software gives you the option of having hardware modem control lines or not.For USB there could be some optional calls and data that would allow you to tap into the extra benefits of a USB virtual serial port that some other virtual serial port or real serial port might not have.For a real serial port if you called or try to mess with modem control bits and that port does not support modem control you should get an error. This same idea could easily be added to the usb additions.You might pass the "what port" as an extra data field to functions. If this is too much over head you could use functions where this data becomes a part of the function's name. Real good software would let the running software redirect a port in real time. And while this sounds more complicated, I think the real result would actually be better software with less errors.So while you were learning how to get your software working with their USB virtual serial port, you would also be learning what it takes to get your software working with their real serial port software.Just an IdeaC

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: January 18, 2014, 01:38:58 am
content: Dont know if this will help much but, just trying to compare to other examples:From Atollic's file usbd_cdc_vcp.c for the Generic media access Layer example STM3210C-EVAL_USB_Device_VCPCode:/*** @brief EVAL_COM_IRQHandler** @param None.* @retval None.*/void EVAL_COM_IRQHandler(void){if (USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET){/* Send the received data to the PC Host*/VCP_DataTx (0,0);}/* If overrun condition occurs, clear the ORE flag and recover communication */if (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_ORE) != RESET){(void)USART_ReceiveData(EVAL_COM1);}}static uint16_t VCP_DataTx (uint8_t* Buf, uint32_t Len){if (linecoding.datatype == 7){APP_Rx_Buffer = USART_ReceiveData(EVAL_COM1) & 0x7F;}else if (linecoding.datatype == 8){APP_Rx_Buffer = USART_ReceiveData(EVAL_COM1);}APP_Rx_ptr_in++;/* To avoid buffer overflow */if(APP_Rx_ptr_in == APP_RX_DATA_SIZE){APP_Rx_ptr_in = 0;}return USBD_OK;}Love the call, ignoring the 0 parameters without mention, but comment on the obvious.Code:/* Send the received data to the PC Host*/VCP_DataTx (0,0);Yikes, doesn't make a whole lot of sense either. Maybe you need to access the buffer directly.

author: AlfBaz
author_rank: Super Contributor
timestamp: January 18, 2014, 08:24:24 am
content: Code:VCP_DataTx (0,0);WTF?!? sending a function a null pointer, that's very clever especially that the function doesn't check for nullAside from that it seems that my earlier assumption about sending 1 byte at a time was correctThis code seems more like pseudo code, in that it doesn't work but shows you what functions to use where.usbd_cdc_cdp.c and all the incarnations floating around seem to be modified versions of usbd_cdc_if_template.c which is included in the standard STM32F libraryWhat I find really stupid and wasteful is the array declared for internal use in the cdc module. You call the tx func with a pointer to a buff that then gets transferred to this internal buffer who's address is then give to the USB peripheral to transmit it's data so you are reserving two memory buffs and wasting time transferring between them.However, seeing that this example code is meant for UART to USB it seems designed to autonomously send data from the UART to USB via ISR's and this "internal" buffer. That being the case the need for it to be 2048 bytes long is beyond me, unless there was a half arsed attempt to allow this function to be called by the user code to send arbitrary data not related to the UART

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: January 18, 2014, 09:53:13 am
content: It seems appalling to me too.I got a reliable a usb cdc using a different example. But it only works in 64 bit packets, 'short packet format' I think it was called.I did get the debugging going but it was an issue, I think it was ok as long as you don't have a breakpoint in the isr.It was using version 4.0 of the usb device driver. STM32F1.It callsCode:/******************************************************************************** Function Name : Send DATA .* Description : send the data received from the STM32 to the PC through USB* Input : None.* Output : None.* Return : None.*******************************************************************************/bool CDC_Send_DATA (uint8_t *ptrBuffer, uint32_t Send_length){/*if max buffer is Not reached*/bool result = false;if(Send_length <= VIRTUAL_COM_PORT_DATA_SIZE){/*Sent flag*/result = true;/* send packet to PMA*/UserToPMABufferCopy((unsigned char*)ptrBuffer, ENDP1_TXADDR, Send_length);SetEPTxCount(ENDP1, Send_length);SetEPTxValid(ENDP1);}return result;}Which seems a lot better quality code.Are you using this version of the driver? If you can I would.I have forgotten if or why it is limited to 64 bits but it does work albeit a bit slowly for large transfers.There is another mode designed for large transfers but once this was going I never bothered.

author: AlfBaz
author_rank: Super Contributor
timestamp: January 19, 2014, 02:12:29 am
content: I have no idea what version I'm using. The way ST organise their software offerings is a bit haphazard from what I can see.They probably released a version with the microcontroller and when they released the discovery boards, modifications and/or enhancements where introduced into the libs available at the discovery boards page but didn't update the zip package on the micro pageThen you gohereand appnotes are accompanied with source that include different versions of the lib againDo you have a link for the code you showed?As for the "64bit" packet limit are you sure it's not 64 byte? That would make sense if they are using interrupt transfer endpoints which are limited to 64 bytes at a rate of 1 interrupt somewhere within 1ms which limits the transfer rate to 64kBytes per second and is generally associated with HID class. CDC class uses bulk endpoints and shouldn't have this 64 byte packet limitation

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: January 19, 2014, 06:50:42 am
content: Sorry meant 64 byte.http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/PF258157That is the latest usb driver for F1, F3 and L1 series.I really didn't think it would be any better than the latest F4 driver, but it does seem so, I can't see any equivalent for F4.I think your thread title summed it up.

author: C
author_rank: Super Contributor
timestamp: January 19, 2014, 09:49:12 am
content: Ok I have not looked at everything so probably missing some things.You have the USB controller hardware which has endpoints and you have all the USB documentation saying what happens on the wire.Note also that USB is packet based and the order of packets can be important.A big part of the problem is stating what you are trying to setup as a USB Device.Comes down to you have a choice of doing things the way defined in the USB documents and hope that the pc end has support for that way of doing things or using the information in the USB documents to say I am doing my own thing an having to supply host side software as well.So here you have the USB controler that could be different or the same for different mpu's.I think all the examples are using ST's software on the pc side so what is happening needs to match up to what this software expects if it is used at pc side.From what I have read so farFrom UM1021 User manualhttp://www.st.com/st-web-ui/static/active/en/resource/technical/document/user_manual/CD00289278.pdfPage 56 is start ofCommunication device class(CDC)Class Subclass Specification for PSTN DevicesThis driver implements the following aspects of the specificationso this area might be worth a readalso later in section 6.10.5UM0424 VirtualComport_Loopback Doc ID 13465 Rev 12 53/85http://www.st.com/st-web-ui/static/active/en/resource/technical/document/user_manual/CD00158241.pdfpage 497 Virtual COM port demoThis is usb to serial port8 VirtualComport_Loopbackthis is USB to software with the software in this case echo receive to transmitso echo what the pc sends back to pcThink this might be a better starting point for a program on the STM32 to talk with a pc.I have read that circular buffers are used someplace but I have not seen any hints of this yet in the code I have looked at.A FIFO could be one or more linear buffers or a circular buffer.I do not remember if DMA can do circular buffers, but I do remember DMA being able to bounce between to linear buffers.You could have data being received with DMA or interrupts bouncing between two linear buffers when a buffer is full. Then dump the full buffer in a larger circular buffer. And then go from circular buffer to two linear buffers to transmit out other interface.As crazy as this sounds, it could give the main program more time.And what you may want in the end is many of the examples all working at the same time.c

author: AlfBaz
author_rank: Super Contributor
timestamp: January 19, 2014, 11:09:43 pm
content: Quote from: HackedFridgeMagnet on January 19, 2014, 06:50:42 amHi Hacke'd thanks for the link. From a cursory glance at that library it seems good enough but only uses a portion of the F4 USB peripherals capability which really isn't such a big deal.It only gives you device capabilities and at FS only. The latest F4 libraries give you Host, Device, High Speed, Full speed and OTG.Given that most of the time you want to be a device and unless you employ an external phy chip, the built phy can only do FS so you don't need HS support.Having said that I believe HS mode is the only mode that allows you to use DMA as the data source/sink. From what I can tell you can use HS mode but at FS speeds through the internal phy giving you access to DMA at FS speeds, without the external phy.

author: AlfBaz
author_rank: Super Contributor
timestamp: January 20, 2014, 12:03:15 am
content: Quote from: C on January 19, 2014, 09:49:12 amThe only ST host software that I have seen is a exe that installs a virtual com port. There may be other drivers for their other examples but so far I've only been playing around with HID and CDC. With the HID I managed to substitute windows standard mouse driver with libusb and read in values into my PC software. I still don't fully understand the use of libusb and standard classes. The example code for HID enumerates the device as a joystick but after I substituted the standard windows driver with libusb I don't know that the device needs to respond to standard HID class requests anymore because (if I'm right) my PC side program is now acting as the driverQuoteI have downloaded all of the relevant documentation for the CDC class. I don't know that I want to go down that rabbit whole. If all I had were the libraries and no example code, then yes, I would need to implement these specs to establish the CDC class but the example has already done that for me. All I need to do is expose/create an interface to its data tx/rx functions, which prompted me to create this postQuoteWhilst it may be expedient to utilise the library accompanying UM0424 it doesn't supply a path to use all of the USB peripherals abilities as I stated in the previous post. While I don't need those capabilities right now, I may need them in the future so I'd rather come to grips with the latest F4 driversQuoteI believe that the buffer pointed to at the start of the thread may in fact be a circular buffer. If it wraps back around to the start the data written there previously should already have been transmitted. What I haven't checked yet is if the lower level driver code (or maybe hardware) know to wrap back to 0 if the index reaches the buff's max size

author: C
author_rank: Super Contributor
timestamp: January 21, 2014, 12:02:29 am
content: Lets forget STM32 for just a bit but I will add this back later.If you want to be lazy while also making USB to work at it's best you follow all the rules that are defined in the USB.org' s documents as this is the standard.Not a free lunch as some things in these documents may not be supported on all operating systems.Note that in these documents there are a lot of places where you change form having to only create software for one end of USB to having to create software for both ends.I may be wrong here but I think Microsoft did their own thing for a network adapter connected over USB. If true then at the USB network adapter end the adapter would start up usb using the rules by usb.org and in the process take one of the user defined options and then match the user defined part to what Microsoft expects.So what I am trying to say is if you make what happens on the wires correct then you are good. If you find an example for the device end that is good then the only difference you have to allow for is the difference between that device controller and it's software and what you have.For USB everything is packets. If you transmit the correct packet at the correct time you are good on the transmit side. On the receiving side you need to understand the received packet and do what is required for that packet.So at a very dumb level you are just sending and receiving packets. Now to make it easer for the MPU, to give more time for other things and/or to allow faster TX & RX of the packets at a higher speed they add a controller. This controller will add limits. For example at the raw level you only have the limits as defined by USB.ORG while a controller could reduce the limits to some of these.If I am reading things correct an interface descriptor has 4 bits with an additional bit to say IN/OUT. So a device could have 16 interfaces in the IN direction and 16 in the out direction. A quick look at the STM32 controller documents says you do not get to use this many with a STM32 controller. So if you are looking at code created for a controller that has more endpoints then the STM32 then you have a big problem to solve. If the original controller has less or equal then this could be no problem.When you try to combine examples you could run out of endpoints. You could have enough endpoints to be a standard keyboard but not enough to be a keyboard & mouse. If you have enough for this you might go over the limit adding audio. No matter what you do at some point you will run into a limit in trying to add things.All matter of tricks could be used to solve this.. Disconnect and reconnect as a keyboard & mouse, Disconnect and reconnect as a audio device. Not a great trick if you want both(sound & keyboard) at the same time. If you add software on the host end you could create a funnel that would let you use less endpoints. Now you have two chunks of code to maintain. So it's a great idea to match up with USB.ORG but in doing this there could be a support delay on a host OS on new things. An some host OS may have a better idea.So ST's host side software may have added to windows things that Microsoft did not support from USB.ORG when ST created this. You could also have ST's host side doing it own thing that is different from USB.ORG.So it's all a matter of of getting what you have to send the correct packets.I would guess that adding libusb to the host side could add problems as the creators would not have the inside knowledge that microsoft has. If could be sower but it could also be faster. From what I know it will probably match what is on the wires for USB.ORG.So to simplify, Any example ST supplies for a STM32 has that hardware controller in mind while trying to match the on the wire part of USB. Great programming on ST's part says that they may need to make some foundation changes if the hardware controller is changed but at a higher level a packet is just a packet and when sent or received will act the same. So you need to look at how far up the hardware change required changing the foundation software. Also note here this is a great time to also make the foundation better.So looking at a virtual serial port. You have a bunch of examples. Some are a tunnel between USB and a true serial port. To do this correctly the host side needs to be able to change the baud rate & handshake lines. The host side needs to be informed of the input handshake lines changing on the actual serial port. Now while you do not directly have a baud rate to a chunk of software code you do have a limit. I think as the host changes the baud rate it also changes the rate of getting the "to host packets". So while you do not need the baud rate change packet, working with this packet makes things work better on the host side while also allowing minor changes on the STM32. For the handshake lines you could look for a USB.ORG option to say you do not have any or You could just use the virtual handshake lines. Think of what happens on the PC host end. If you just have a serial port with just the tx & rx wires, one of the few ways for something connected to this with a fast baud rate is to use XON/XOFF characters to control the flow. Neat idea but at the device end you how have to watch that the data you are trying to say does not use these two bytes or that they are changed to something different. Different means a matching change back chunk of software on the PC end and the PC end also needs to not use them to the device. So again Virtual handshake lines could be a huge gain while having little in extra problems.When you get this working you might start getting a string trying to talk to the modem. The commands to find out what kind of modem is connected. For this I would look in USB.ORG's documents for a bit that says "I am a plain serial port" or "I am a terminal" to stop the host sending these.A general rule I have when working with interrupt code is to not change a variable in both sections. Doing this leads to big problems. You also have to watch that when changing a variable that it happens all at once. Not a big problem for a 32-bit machine but could be a big problem if a 32 bit value was actually changed by 4 8-bit writes and a interrupt could happen between the 4 writes. So order can be important and in talking to a controller one change will say all the rest of the fields are good. This should be the last change to the controller when everything else is set.A circular buffer will have an IN pointer & an OUT pointer & a size. one of these pointers will only be changed in the interrupt code with the other in the non interrupt code or a different interrupt code section. The order you read the two values could also important. If you are putting in new data the value from the OUT pointer could change at any time.For what I see in the ST USB controller the idea is a array of many linear buffers. Yes they are bunched together so the to PC buffers is one big block of ram. But here you need to remember that it takes time to send over USB so while this is one big block a part of it will be in the control of the USB to PC part of the controller and if you write in to this section that is in use you are over writing data before it can be sent.If you have a big backlog going to the PC there could be no space. Depending on the time there could be space at both ends while the middle section has not been sent yet.So a lot of care needs to be in the send to PC side. It will be much easer to do this right from the start then to try to find these kinds of errors at a latter date.From my memory, Receive from pc side has two interrupts or status flags. One is this receive buffer is full process it. The other is one or more receive buffers is full. Now the last thing in processing a receive buffer full should be telling the controller that this buffer is now empty and only then a check for more full buffers.While working with one side you need to keep in mind that the other side could be so fast that 0 time is taken in the other side and what could happen if this is the case. While the other extreme could be like it took an hour. Your main line code could have an interrupt happen even in the middle of a C instruction as one C instruction can be many machine instructions. And while a interrupt code section will not have this problem even here it could get interrupted by a higher priority interrupt.So you have the base library you want to use but it may not have a good example for what you want while a different base library has an example.For USB you have some packet data that says I want to use This to do this to HID rules. A second example could say I want to use this to do this to CDC rules. To merge the two examples you have to not have a resource conflict while getting your software to process both packets with a possible change of resources. I would expect the examples to leave out the capability to easily switch resources.For you an older code library for the STM32 is most likely using the same hardware or a small change to the hardware. I would look and cheat. You have a file for that old library example that does the main part of the example. Don't copy any of ether library and start a new project with just this one file. Let the compiler errors help you build the foundation files Get some nice errors saying ___ file is missing, do a quuck compare the old library file vs new library file. Add a file and comment out all the functions. Get more nice errors. function __ missing. You can then check that Old function really matches new function before UN-commenting a function. Here compiler errors can be a very good friend.C

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: January 21, 2014, 12:27:18 am
content: Interesting post C. Thanks for taking the time to write your thoughts.QuoteIncidentally I had just been doing a lot of this sort of stuff to get my SDIO working with FatChans library. It was a struggle.But I must admit it is nice when the vendor code is a bit more straightforward or sensible and so everytime you add a feature it isn't necessarily a major learning experience.Any closer AlfBaz?

author: C
author_rank: Super Contributor
timestamp: January 21, 2014, 02:33:40 am
content: I am not sure if this idea will work in all c compilersBack in my pascal code days it was a sign of poor code to use the same types all over the place.In pascal when you are defining a pointer to something it becomes unique to what it points at.In pascal it is very easy to give with a type of byte a new type name.When you do this in pascal, You get a nice error message if you try to use something with the old type name and the new type name.In simple terms the compiler can do a better job of checking your code for errors.So back to AlfBaz original post, if you changeCode:uint16_t VCP_DataTx(uint8_t* Buf, uint32_t Len)toCode:uint16_t VCP_DataTx(uint8_t* Buf, uint32_LEN_t Len)will the compiler give you an error message if the caller does not match this new type name?Doing this would take added typedef statement.Code:typedef uint32_t uint32_LEN_t;while this sounds like more work, it's very nice if during the compile the compiler catches a dumb error vs spending the time trying to find the dumb error in debug modeMy previous post was just using the compiler to assist but you do need to give it something to work with if you want to get it's assistance.C

author: dannyf
author_rank: Super Contributor
timestamp: January 21, 2014, 12:13:13 pm
content: QuoteIt will work - I do it all the time - but it can be extremely risky and when that happens difficult to debug. I used it in the fix_fft port of mine for "short" (16-bit vs. 32-bit). It took me a week plus to track it down.I think sometimes a well-documented device-specific limitation is better than a generic solution that works 99% of the time - if you end up in that 1%, it is hell to get out.

author: AlfBaz
author_rank: Super Contributor
timestamp: January 21, 2014, 02:21:44 pm
content: Quote from: C on January 21, 2014, 02:33:40 amUnder what conditions should that generate a warning or error? I just tried it quickly and so long as the type is the same as the original base type gcc doesn't seem to care (-Wall enabled)For example if it create a typedef with some arbitrary name of type unsigned char, it doesn't char what typedef'd name I put there so long as it's a unsigned char typeAs for this library code, I have it working but I still have the same concerns raised by C about over-writing data before it's sent. I have yet to find some mechanism either in the library code or the hardware that can somehow indicate the USB peripheral's progress through the buffer. It's taking me a while to get through it as I'm also messing around with PC side code. Being a USB n00b I'm essentially trying to create a template/workflow for adding usb to future project... you know, include these, add that lib path, define these...C, with regards to your comments about sticking to the specs or not, from the little that I've learnt so far, if you want to connect yourdeviceto a PC you have 3 choices.Use a standard OS generic driver, so that you don't have to create your own and then use the OS's API to interface with that driver. For example the file system for an msc device or mouse, keyboard or joystick functions for HID devices (I think I may have mentioned this before but I believe there may be an even more generic HID api for windows)Roll your own driver which involves kernel mode code and on some systems (Yes I'm looking at you Windows8) drivers wont install unless signedUse already signed drivers with extensive api for user space such as winusb, libusb etcI'll start off by ruing out choice number 2. If you go with option 1 you'll need to implement or adhere to that classes specification as it would be a safe bet the OS sticks to it. If you go with option 3 then it would seem you only have to worry about what transfer type you need interrupt, bulk or isochronous. Depending the the device application you may be able to get away with just control transfer.Even with this last choice you would still have to follow the underlying USB specs especially in the mandatory control transfers or else the OS will fail its enumeration or get stuck trying to decide which driver to use. The device hardware peripheral will handle most of the low level stuff but depending on who's peripheral you are using will also dictate how much you have to implement. With all of this in mind you have to define all of the required descriptors, interfaces etc which is what these libraries and example code can provide

author: C
author_rank: Super Contributor
timestamp: January 21, 2014, 07:48:43 pm
content: AlfBaz,Let talk about the last part of you post firstFor thinking about itYou have a STM32 with a usb controller and a SD card slot.Just how lazy can you get? How easy can you be and make this work?You really do not want any thing windows here. You do not want anything linux here ether or OS-x.What you really want to happen is when you connect this to a USB host , it is mass storage for every operating system that does USB.Create no software anywhere else, no special files, no host config just plug it in and it works.I like trying to be lazy especially if the above is the result. I can do a little more work on the stm32 side if the above is the result.The simple answer is the one common thing for all above is sticking to the rules that USB.ORG has for a USB mass storage device. It is really that simple and that complicated.Any small difference here and you could have problems. Remember that some very good programmers have worked on some of those host sides and the host may have very great error checking and error handling built in to what they have created so that their side will try to work around all the crap.A little digging and you can find where someone a "small big name" has created a USB mouse. Just one minor problem they swapped the X and Y of the mouse and shipped a huge number. Could something like this be the reasion what you have working but have some odd things happening because something like this allowing it to work when it should not?Try to get a logical understanding of what is really happening to create the error or problem or even the feeling you might have. Really use what you already know against the problem. I have a whole bunch of USB flash dirves. That first one, the really old one, all ways takes a long time to show as a drive and you see a pop-up stating it's name the first time it is used with a host. The later flash drives wam bang drive ready. Simple answer is that old drive is not standard flash drive an needs a driver or a patch of the os to function.You can patch almost anything but if you really want an easy lazy time match USB.ORG. for the usb part.So when you are creating something you need to really look to see if that is the host patching around your crap. It is actually easer and cheaper for everyone if your crap is correct. When you are having a problem with usb don't start changing the host look at the problem is it your crap or the host's crap that is the problem.Patching the host is just like trying to read a second backup tape with the same drive that ate the first backup tape.When you get rid of the errors, you may still think of your snuff as being crap but nothing keeping you from using it as a foundation for making it better crap. I tend to treat all my software as crap. I could do this better but do not have the time now. This part could be better but the compiler is crap at this. This section needs better error handling. This section of code I have no idea how it could be so bad, it works but what a mess it is. For this part I have no idea how to do it!!!Get this part working and you have a great usb mass storage device. Every thing is just great until you plug in that sd card in to a pc with a sd card slot. Really use that error. Think on this You crap is working just fine, no problems. But you really did create the error on that host that is trying to read the sc card you crap created.Don't patch it or hack something together, try to put in place the best foundation to curer the problem. If you use what you know, that sd card could have many different file systems if it was used on a pc first. Just quick think there is fat, fat32, ntsf and a whole lot of others. It could be a little more work now but a good foundation would allow for more then one type of file system.With todays OS's there should be no need to add software or config for a mouse, a keyboard, an audio device or mass storage.Done correctly a virtual serial port will show up on the host as a serial port for any program that can do serial over USB.If you have mass storage working via the stm32 what would keep the STM32 from reading and writing files? What would keep the STM32 from reading a file and reprogramming it self.I have no idea where you want to get to, but think ahead even further.getting big herehave an idea for usb overrun to followFor compilers note that the default that I have seen is to turn off most error checking so that you get fast compile times.First thing I would do is to turn on any option that can report or identify an error with a compiler or linker. Use the errors to save you time in the long run.C

author: C
author_rank: Super Contributor
timestamp: January 21, 2014, 09:37:42 pm
content: AlfBaz,Did not catch if you said which of the 3 stm32F4 discovery boards you haveThis is for the STM32F401xB/CUSB on-the-go full-speed (OTG_FS) RM0368page 778/833IN data transfers?Packet writeThis section describes how the application writes data packets to the endpoint FIFO when dedicated transmit FIFOs are enabled.In polling mode, the application monitors the status of the endpoint transmit dataFIFO by reading the OTG_FS_DTXFSTSx register, to determine if there is enoughspace in the data FIFO.Think this is what you need to prevent an over runI would first scan the library you have to see if this is used some place.C

author: AlfBaz
author_rank: Super Contributor
timestamp: January 21, 2014, 10:20:11 pm
content: In regards to your first post, I think you misunderstand my design requirements. I want to be able to communicate with the device from the PC. The intention has always been to create software on the PC sideI want to be able to either control the device, provide it with data or consume its data. I have no immediate plans to build some standard consumer gizmo such as a mouse, mass storage device or audio player. I simply want to use USB where in the past I may have opted for a 232 port and have the ability to transfer data/control in a fashion that best suites my custom application.QuoteI have the F407 and F429QuoteThank you very much, I'll look for a reference to that in the library code although for some reason they have changed the names of the register names in the code as compared to the datasheet

author: C
author_rank: Super Contributor
timestamp: January 22, 2014, 02:00:45 am
content: my post about the mass storage was just a great example of what you should expect when you apply it to what you are doing.just replace mass storage for serial port. It should just work.Just about all OS's have a terminal program like hyperterminal for windows.You should work at this level with out adding code or any config on the host system.Your usb serial port should just automatically show up in these programs serial port list just by you connecting your usb device to that new host.QuoteI think the same is true for matching st's var names to var's defigned in usb doc's. I did notice that some of the usb orgs names are in the comments.F407 and F429 are very niceIf it was me and I needed to write software for both the PC side and the stm32 side and I had a usb connection like this, I think I would save the first virtual serial for a simple serial consolesend the needed data between the two(PC & F4) in packets and skip trying to encode/decode to a serial stream.It is very easy to send and receive packets of data with USB. Once you have a good foundation in place it gets very simple in fact.C

author: C
author_rank: Super Contributor
timestamp: January 26, 2014, 12:13:23 am
content: Hi AlfBazIf you are still having problems, I have an Idea but you probably already thought of this.One thing I have found is quick and easy tests make it easer to put in quick test patches to assist in converting something you have to a new purpose.One of the virtual serial port examples I looked at is the the EVAL board version of chip you have on the discovery board. A true USB to physical serial port example.The discovery board does not have the driver chip of the eval version but still has that serial port. If that port & it's pins are not in use on the discovery board you could easily add and remove a jumper between Tx & Rx pins of the mpu which would cause an echo back to the PC while connected.You could get a good idea that the example works on the discovery board doing this.Next step could then be to add the software equal of a OR gate in the Rx data stream of the serial port just do not use the second port of the or yet. Still have the echo and the patch is good.Add a Tee connection to the TX data stream of the serial port, leave the second port of Tee unused. Still have the echo and the patch is good.Connect the second output of the above Tee to the second input of above OR. Now with jumper on the pins you have a double echo when in place and a single echo with it out.When you have this, change the above Tee to not send data any longer to the serial port. This should drop you back to a single echo even with the jumper in place.When you stop sending the data to the serial port you open up seeing bugs in your patches or original code to do with speed over runs or overwrites that would not happen with the serial port slowing the data down. I would try sending some big files out and capture the echo so that you could use PC software to look for errors at this point. Note here that there could also be problems created by a pause between two larger files.When you get to this point just do the same steps to the control and status paths of the serial port.I do not think you are currently in such a need for program space that you really need to remove the serial port part of the software but is would be good to compare your inserted patches to the standard serial port library and adjust the positions if different. I would guess that virtual serial port uses standard serial port library or a small change of it.When you get to this point change the above Software OR and Tee above to a 4 pole double throw switch in software so that you have USB to physical serial port switched to internal software only serial port. The four are control data, status data, Tx data & Rx data.Just an idea, I have found a bunch of small steps that you can test is faster then the a big hack to get to what you want.C

author: AlfBaz
author_rank: Super Contributor
timestamp: January 26, 2014, 03:01:27 pm
content: Thanks for the tips C, I appreciate your help.The reason I was using the virtual com port example wasn't so I could do usb to serial, its because it was the only example showing the use of the CDC class. The fact that the majority of the extra code on top of the standard libraries code was designed for USB to 232 and my subsequent stripping of the UART code is the cause of the issues I pointed out in the start.It's all working fine at the moment but I haven't gotten around to "stress testing" the DataTx function to see if the USB port sends data slow enough that I can corrupt unsent data by sending to much, to quickly from the main application. If it does I'll look into adding another user call back function, triggered in the ISR, to the ones already there, using the register you suggested earlier to set or clear an "atomic" flag