Hi, I’m looking at the Atmel, Philips & STMicro ARM7 devices with USB interfaces. I note that the current FreeRTOS supports the USB interface on the Atmel AT91SAM7 family, but not on either the Philips or STMicro device families. I was wondering whether anyone had done any work in this area, or whether there were technical reasons why it hasn’t yet been done. e.g. I’ve come across a few problems with USB on the Philips LPC2148, specifically when using the ULINK JTAG port on the Keil MCB2140 board. I’m happy to contribute a USB port on either (or both) of these devices but don’t want to "re-invent" the wheel if someone is already addressing this. Any advice would be appreciated. Regards, David Henretty
I’m not aware of anybody currently providing USB samples with FreeRTOS for these other devices, but there is absolutely no technical reason why it cannot be done. FreeRTOS provides sample drivers, normally for a UART, the structure of which can be copied for any peripheral. You can simply use the sample interrupt driven UART driver as a frame work, then put in your own USB code. I’m sure sample USB code will be available for the LPC and STR devices somewhere. Try the Yahoo groups for LPC code. Regards.
Thanks for the prompt response Richard – much appreciated. Sample USB code for HID, Bulk and Isochronous endpoints is provided with the Keil board (or on the Keil website). However, these are standalone examples – the issue is porting the USB control code (driver) to FreeRTOS, as has already been done on the Atmel device. I’ll take a look at the UART driver as you suggest and see what is involved in porting the sample code to work under FreeRTOS. There appear to be specific issues with the Philips device in that all the provided examples work fine until I attempt to load them using the ULINK JTAG interface. This usually fails or ends up in "hyperspace" after single-stepping a few instructions. I’m not sure what the cause is; it may be related to interrupts or a hardware interaction between the USB and JTAG interfaces. I had no such problems with the Atmel board and IAR tools. I don’t yet have an STMicro kit, so can’t comment on it. Regards, David.
In theory it should be a matter of: + Creating an ISR that simply services the USB interrupt by receiving data from the hardware, posting the data to a queue, then clearing the interrupt. The ISR should therefore be small and fast. + Creating a task that receives data from the queue, processes it, and if necessary generates data in response. The structure and syntax for the ISR can be obtained from the UART example (for example, how to define the ISR, how to send data to a queue from the ISR, how to cause a context switch from within the ISR if necessary, etc.) which is compiler dependent. Hopefully the code required to service the hardware will be obtained from the Keil example. This will go into the ISR. Again, hopefully the code required to parse the descriptors, generate data in response, etc. will also be obtained from the Keil example. This part of the code can go in a task. See the SAM7 USB example also for more information. Regards.
Richard, you mentioned the ISR (which should be quick) would read data available from the USB hardware, then send to a queue. I wonder how this relates to a recent statement that the FreeRTOS queue is more complex than needed for simply queuing bytes from a serial port because it adds event-tracking overhead. Does that apply here, that it would be better to use a simple revolving buffer to pass the bytes from the interrupt?
What using the queue gives you is a way of guaranteeing that the received bytes would be processed immediately should the ISR end by Yielding (forcing a context switch). A task can block on a queue waiting for data to arrive. If the ISR posts onto the queue then the task will unblock. If at that point it is the highest task in the system able to run, then it will run on the next context switch, which by following the UART examples can be within the ISR. This gives you a sort of second level interrupt (conceptually). The main processing happens at task level so you don’t have to worry about having interrupts disabled or alternatively nesting interrupts, but the ISR and data processing happen sequentially, and the interrupted task does not execute again until the data processing is complete. Placing data into a simple circular buffer does not automatically wake a task that might be waiting for the data. This means the task might not process the data immediately upon at the end of the ISR. It is therefore really application dependent as to which is best for you. You can have a faster interrupt, or an automatic way of prioritising processing. If you do not need to immediately process received characters then the simple buffer might be better for you. Regards.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.