Hi everyone,
I'm working on a project to connect a Hauwai E3531i-2 Surf Stick to the
frdmk64F-board (a dev board for the Cortex M4 from NXP) via USB and I
ran into difficulties with the CDC-Host Stack. My goal is to send
AT-Commands like a Terminal Tool via the USB-Port. For testing purpose
and because it was in the example all the data gets streamed to a
Terminal(Putty/Terra Term/HTerm) on my Computer. Where I also send the
Data from.
I'm working with Kinetis Design Studio(KDS) 3.2 and Kinetis Software
Develpment Kid (KSDK)2.2 and got the USB-Host BM examples CDC and MSD
running and modified them for my purpose. I rewrote the enumeration
process so I can differ between different Classes automatically and do
Init and Task accordingly.
With this Stick it necessary to first connect him as am Mass Storage
because by default it enumerates as an MSD containing the drivers for
Windows. So I connect it as an MSD-Device and send a
"ModeSwitch"-Command. The Linux users will be familiar with this
procedure. The Stick then disconnects itself and will be enumerated as a
Vendor Specific Device (Class: 0xFF). Unfortunately not as a CDC Device.
So long so good, just like it does in Linux where I now could send the
AT commands via Terminal e.g. MiniCom. Now my code loads the
CDC-Component it runs just like the CDC-Host example from this point. I
get a few errors:
The Interrupt Pipe fails to be established
Line State is "ok", but all Values are zero.
data transfer error with code 10
The example by itself doesn't do anything visible from this point on.
After some trying I got to a point where I got it kind of running. It's
highly unstable, but I think I found something. The Problem seems to
come from the Buffer struct
1 |
|
2 | typedef struct _usb_uart_buffer_struct
|
3 | {
|
4 | uint8_t buffer[USB_HOST_SEND_RECV_PER_TIME];
|
5 | uint32_t dataLength;
|
6 | struct _usb_uart_buffer_struct *next;
|
7 | } usb_uart_buffer_struct_t;
|
and the corresponding Variables
1 |
|
2 | usb_uart_buffer_struct_t g_EmptyBuffer[USB_HOST_CDC_BUFFER_NUM];
|
3 | usb_uart_buffer_struct_t g_EmptySendBuffer[USB_HOST_CDC_BUFFER_NUM];
|
4 | usb_uart_buffer_struct_t *g_EmptyQueue;
|
5 | usb_uart_buffer_struct_t *g_EmptySendQueue;
|
6 | usb_uart_buffer_struct_t *g_CurrentUartRecvNode;
|
7 | usb_uart_buffer_struct_t *g_UsbSendQueue;
|
8 | usb_uart_buffer_struct_t *g_UsbSendNode;
|
9 | usb_uart_buffer_struct_t *g_CurrentUsbRecvNode;
|
10 | usb_uart_buffer_struct_t *g_UartSendQueue;
|
11 | usb_uart_buffer_struct_t *g_UartSendNode;
|
They are used to store the data coming for the USB-Pipes and the Debug
Terminal in this example. As you can see they are a sort of List
containing the Data in a Buffer, the Number of Bytes in the Buffer and a
Pointer to the next List element.
But at some point the next Element and the current Element is NULL and
from this point onward I can't receive any more messages. A reset of the
Buffers helps but this causes other errors. This is the code I got kind
of running.
1 |
|
2 | case kRunIdle:
|
3 | if (g_AttachFlag)
|
4 | {
|
5 |
|
6 | {
|
7 | if (!g_UsbSendBusy)
|
8 | {
|
9 | if(g_UsbSendQueue)
|
10 | {
|
11 | g_UsbSendNode = getNodeFromQueue(&g_UsbSendQueue);
|
12 | if (g_UsbSendNode)
|
13 | {
|
14 | g_UsbSendBusy = 1;
|
15 | USB_HostCdcDataSend(g_cdc.classHandle, (uint8_t *)&g_UsbSendNode->buffer[0],
|
16 | g_UsbSendNode->dataLength, USB_HostCdcDataOutCallback, &g_cdc);
|
17 |
|
18 | }
|
19 | }
|
20 | else
|
21 | {
|
22 | if (g_EmptySendQueue)
|
23 | {
|
24 |
|
25 | g_CurrentUsbRecvNode = getNodeFromQueue(&g_EmptySendQueue);
|
26 | // if (g_CurrentUsbRecvNode)
|
27 | {
|
28 | NoReceivCounter = 0;
|
29 | g_CurrentUsbRecvNode->next = NULL;
|
30 | g_CurrentUsbRecvNode->dataLength = USB_HOST_SEND_RECV_PER_TIME;
|
31 | USB_HostCdcDataRecv(g_cdc.classHandle, (uint8_t *)&g_CurrentUsbRecvNode->buffer[0],
|
32 | g_CurrentUsbRecvNode->dataLength, USB_HostCdcDataInCallback, &g_cdc);
|
33 |
|
34 | }
|
35 | }
|
36 | else
|
37 | {
|
38 | NoReceivCounter++;
|
39 | }
|
40 | }
|
41 | }
|
42 |
|
43 | if (!g_UartSendBusy)
|
44 | {
|
45 | if(g_UartSendQueue)
|
46 | {
|
47 | g_UartSendNode = getNodeFromQueue(&g_UartSendQueue);
|
48 |
|
49 | if (g_UartSendNode)
|
50 | {
|
51 | g_txfer.buffer = g_UartSendNode->buffer;
|
52 | g_txfer.size = g_UartSendNode->dataLength;
|
53 | g_UartSendBusy = 1;
|
54 | USB_UartSendNonBlocking((USB_UartType *)BOARD_DEBUG_UART_BASEADDR, &g_UartHandle, &g_txfer);
|
55 | }
|
56 | }
|
57 | }
|
58 | g_UartActive++;
|
59 |
|
60 | if (g_UartActive > USB_HOST_UART_RECV_TIMEOUT_THRSHOLD)
|
61 | {
|
62 | g_UartActive = 0;
|
63 |
|
64 | USB_BmEnterCritical(&usbOsaCurrentSr);
|
65 | if ((g_CurrentUartRecvNode) && (g_CurrentUartRecvNode->dataLength))
|
66 | {
|
67 | insertNodeToQueue(&g_UsbSendQueue, g_CurrentUartRecvNode);
|
68 | g_CurrentUartRecvNode = getNodeFromQueue(&g_EmptyQueue);
|
69 | }
|
70 | USB_BmExitCritical(usbOsaCurrentSr);
|
71 | }
|
72 |
|
73 | }
|
74 | }
|
75 | if (NoReceivCounter > 90000 )
|
76 | {
|
77 | USB_HostCdcInitBuffer();
|
78 | NoReceivCounter = 0;
|
79 | }
|
80 | break;
|
It basically comes from the host_cdc.c File in the example. I added some
if conditions and the reset part between Line 22 to 39 and bevor the
break. This causes the Buffers to be reinitialised after a specific
amount of NULL received. As far as I understand the Text the
g_EmptySendQueue contains the data I get from the Stick via USB but I
have basically no clue how it gets in this Buffer.
With this I get the code running until I get an assertion error:
1 |
|
2 | ASSERT ERROR " xfer->dataSize ": file "../drivers/fsl_uart.c" Line "715" function name "UART_TransferSendNonBlocking"
|
I think this comes from some Interrupts firing while doing the
reinitialisation or because some Flags aren't reset and the Code thinks
it still has to send the Data.
But I get failures in USB_HostCdcDataRecv in usb_host_cdc.c
1 |
|
2 | if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
|
3 | {
|
4 | #ifdef HOST_ECHO
|
5 | usb_echo("error to get transfer DataRecv\r\n");
|
6 | #endif
|
7 | return kStatus_USB_Error;
|
8 | }
|
In the USB_HostMallocTransfer function the Transfer Header seems to be
missing. This error comes comes really really often, but when I "mute"
it, it runs quite good. The amount of these messages scales witch the
Counter NoReceivCounter and the Makro in host_cdc.h
1 |
|
2 | /*! @brief buffer number used to data transfer */
|
3 | #define USB_HOST_CDC_BUFFER_NUM 10U
|
I'm not very familiar with USB and been working with Controllers for
just half a year. So any information could help.
Now I am wondering why do I have to reset the Buffers and how can I do
it without causing the errors.
How exactly is the Data received? How does it get inside the Buffers? I
can't find anything related in the code.
I have the feeling that it can't be this hard to get this running, it
feels like maybe just some settings are wrong and now I try cure the
symptoms but the sickness should be in plain sight.
This is my first post so if I missed some important Information I'm
happy to provide them.
Cheers
Bastian