I am trying to run the example USB Stack code from the Baremetal SDK on the iMX6SL. I had hoped to use the CDC stack in an application but I cannot get the example code to run:
.../sdk/common/usb_stack/Device/app/cdc/virtual_com.c
I cannot get this code to run, does the usb_stack work with the iMX6SL? If not, is there any example code for the iMX6SL? I see the the sdk/drivers/usb/src/ files, but that code is not setup to handle an interrupt driven flow and it also is very specific the the HID class of devices. I has hoping to quickly get a CDC class going.
There is a packed structure that is defined in usb_devapi.h:
typedef struct _USB_EP_STRUCT
{
uint_8 ep_num; /* endpoint number */
uint_8 type; /* type of endpoint */
uint_8 direction; /* direction of endpoint */
USB_PACKET_SIZE size __attribute__ ((packed)) ; /* buffer size of endpoint */
} __attribute__ ((packed)) USB_EP_STRUCT, *USB_EP_STRUCT_PTR;
That is causing bad code to be generated. Using ARM gcc 4.8.3 creates code in several places that tries to access the 'size' attribute (which is a 16-bit halfword) and causes a misaligned data abort on the iMX6SL
For example, in the reset handler:
usb_class.c: void USB_Reset_Service (...)
and
usb_driver.c: uint_8 _usb_device_init_endpoint (...)
│0x80086c48 <_usb_device_init_endpoint+88> ldrb r3, [r11, #-25]
│0x80086c4c <_usb_device_init_endpoint+92> strb r3, [r11, #-20]
>│0x80086c50 <_usb_device_init_endpoint+96> ldrh r3, [r11, #-28] ;
│0x80086c54 <_usb_device_init_endpoint+100> strh r3, [r11, #-17] ; <------------- This is a half-word instruction on a byte aligned data address: 0x82272697
Note:
I have tried to call the following, but I still get the error.
//! @brief Disable aborts on unaligned accesses.
void disable_strict_align_check(void);
Solved! Go to Solution.
After digging through the SDK code, it looks like the final two changes I had to make were to invalidate/clean the cache before reading or writing to the data in the queuehead and to disable zero length transfers (ZLT) for incoming transfers, apparently windows does not support ZLT with the specified driver.
I am still struggling with this code for USB CDC support. Can someone tell me what the best source is for a bare metal USB stack for iMX6SL (ported and tested for iMX6)?
The one in the usb_stack directory does not seem to work well. For any non-trivial use I am getting the following error on reading data from Windows:
received usb error irq on device 0
And It will not even enumerate in Linux.
After digging through the SDK code, it looks like the final two changes I had to make were to invalidate/clean the cache before reading or writing to the data in the queuehead and to disable zero length transfers (ZLT) for incoming transfers, apparently windows does not support ZLT with the specified driver.
Hi Nathan
Many thanks for your posts on this subject -- there is not much help for bare metal programmers... :-(
How did you get past the "received usb error irq on device 0" ? If I type slowly on the terminal, then the characters get correctly echoed;
However, if I enter several characters (by pasting a string into the terminal), the iMX6 runs into that error. Where did you disable the ZLT? I tried all of them I found, but without success.
Thanks and regards,
-Rob
Sorry, I don't have the code handy now, but I believe that I delayed priming the next transfer by ~ 9/115200 seconds to emulate the throughput of an RS232 @ 115200 baud, That kept the windows side from bombarding the mx6 with data.
Hi Nathan
In the meantime I have manged to get the virtual com example running -- it needed quite some debugging hours to get it running stable.
Here are some notes for our bare-metal fellows:
Conclusion:
- do not use Freescale's SDK for USB
- do not use Microsofts' usbser.sys (aka virtual com).
- ask Freescale for abetter quality SDK!
Regards,
-Urs
UPDATE: I was able to get past my previous problem by enabling the MMU and DISABLING ARM Strict Alignment checking:
//! @brief Disable aborts on unaligned accesses.
void disable_strict_align_check(void);
The disable_strict_align_check(void) was failing before because I had the MMU turned off for debugging.
It looks like the class API changed some and the CDC Demo App was not updated. I have made some progress with the CDC demo, but I had to make the following updates:
Index: cpu/imx6sl/sdk/common/usb_stack/Device/app/cdc/user_config.h
===================================================================
--- cpu/imx6sl/sdk/common/usb_stack/Device/app/cdc/user_config.h (revision 535)
+++ cpu/imx6sl/sdk/common/usb_stack/Device/app/cdc/user_config.h (working copy)
@@ -23,7 +23,7 @@
#if (defined MCU_MK70F12) || (defined __MCF52277_H__)
#define HIGH_SPEED_DEVICE (0)
#else
- #define HIGH_SPEED_DEVICE (0)
+ #define HIGH_SPEED_DEVICE (1)
#endif
#if (defined MCU_MK20D7) || (defined MCU_MK40D7)
Index: cpu/imx6sl/sdk/common/usb_stack/Device/app/cdc/virtual_com.c
===================================================================
--- cpu/imx6sl/sdk/common/usb_stack/Device/app/cdc/virtual_com.c (revision 535)
+++ cpu/imx6sl/sdk/common/usb_stack/Device/app/cdc/virtual_com.c (working copy)
@@ -26,6 +26,7 @@
#include "usb_cdc.h" /* USB CDC Class Header File */
#include "virtual_com.h" /* Virtual COM Application Header File */
#include <stdio.h>
+#include "user_config.h"
#if (defined _MCF51MM256_H) || (defined _MCF51JE256_H)
#include "exceptions.h"
@@ -51,7 +52,7 @@
* Global Variables
****************************************************************************/
#if HIGH_SPEED_DEVICE
-uint_32 g_cdcBuffer[DIC_BULK_OUT_ENDP_PACKET_SIZE>>1];
+uint_8 g_cdcBuffer[DIC_BULK_OUT_ENDP_PACKET_SIZE>>1];
#endif
/*****************************************************************************
@@ -256,11 +257,15 @@
}
else if((event_type == USB_APP_SEND_COMPLETE) && (start_transactions == TRUE))
{
+ /**
+ * Looks like the API changed, Class functions expect a pointer to the controller ID
+ */
+ uint8_t TEMP_CONTROLLER_ID = CONTROLLER_ID;
/* Previous Send is complete. Queue next receive */
#if HIGH_SPEED_DEVICE
- (void)USB_Class_CDC_Interface_DIC_Recv_Data(CONTROLLER_ID, g_cdcBuffer, DIC_BULK_OUT_ENDP_PACKET_SIZE);
+ (void)USB_Class_CDC_Interface_DIC_Recv_Data(&TEMP_CONTROLLER_ID, g_cdcBuffer, DIC_BULK_OUT_ENDP_PACKET_SIZE);
#else
- (void)USB_Class_CDC_Interface_DIC_Recv_Data(CONTROLLER_ID, NULL, 0);
+ (void)USB_Class_CDC_Interface_DIC_Recv_Data(&TEMP_CONTROLLER_ID, NULL, 0);
#endif
}
@@ -300,7 +305,9 @@
}
else if(event_type == USB_APP_CDC_CARRIER_DEACTIVATED)
{
- start_transactions = FALSE;
+ //start_transactions = FALSE;
+ // Windows terminal + CDC driver do not send the CARRIER_ACTIVATED, so set it to true anyway for testing
+ start_transactions = TRUE;
}
}
return;
Index: cpu/imx6sl/sdk/common/usb_stack/Device/source/driver/usb_devapi.h
===================================================================
--- cpu/imx6sl/sdk/common/usb_stack/Device/source/driver/usb_devapi.h (revision 535)
+++ cpu/imx6sl/sdk/common/usb_stack/Device/source/driver/usb_devapi.h (working copy)
@@ -313,7 +313,8 @@
}ALIGN USB_EP_STRUCT, *USB_EP_STRUCT_PTR;
#if (defined(__CWCC__)||defined(__GNUC__))
- #pragma options align = reset
+ //#pragma options align = reset
+ #pragma pack()
#elif defined(__IAR_SYSTEMS_ICC__) || defined(__CC_ARM)
#pragma pack()
#endif