Forum: µC & Digital Electronics USB Host CDC connection (to Surf Stick) on a frdmk64F (Cortex M4)

Author: Bastian S. (b_s)
Posted on:

Rate this post
0 useful
not useful
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
typedef struct _usb_uart_buffer_struct 
 uint8_t buffer[USB_HOST_SEND_RECV_PER_TIME]; 
 uint32_t dataLength; 
 struct _usb_uart_buffer_struct *next; 
} usb_uart_buffer_struct_t;  
and the corresponding Variables
usb_uart_buffer_struct_t g_EmptyBuffer[USB_HOST_CDC_BUFFER_NUM]; 
 usb_uart_buffer_struct_t g_EmptySendBuffer[USB_HOST_CDC_BUFFER_NUM]; 
usb_uart_buffer_struct_t *g_EmptyQueue; 
 usb_uart_buffer_struct_t *g_EmptySendQueue; 
usb_uart_buffer_struct_t *g_CurrentUartRecvNode; 
usb_uart_buffer_struct_t *g_UsbSendQueue; 
 usb_uart_buffer_struct_t *g_UsbSendNode; 
 usb_uart_buffer_struct_t *g_CurrentUsbRecvNode; 
usb_uart_buffer_struct_t *g_UartSendQueue; 
 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.
case kRunIdle: 
            if (g_AttachFlag) 
                if (!g_UsbSendBusy) 
               g_UsbSendNode = getNodeFromQueue(&g_UsbSendQueue); 
               if (g_UsbSendNode) 
                   g_UsbSendBusy = 1; 
                   USB_HostCdcDataSend(g_cdc.classHandle, (uint8_t *)&g_UsbSendNode->buffer[0], 
                              g_UsbSendNode->dataLength, USB_HostCdcDataOutCallback, &g_cdc); 
                     if (g_EmptySendQueue) 
                         g_CurrentUsbRecvNode = getNodeFromQueue(&g_EmptySendQueue); 
//                   if (g_CurrentUsbRecvNode) 
                           NoReceivCounter = 0; 
                    g_CurrentUsbRecvNode->next = NULL; 
                    g_CurrentUsbRecvNode->dataLength = USB_HOST_SEND_RECV_PER_TIME; 
                    USB_HostCdcDataRecv(g_cdc.classHandle, (uint8_t *)&g_CurrentUsbRecvNode->buffer[0], 
                                  g_CurrentUsbRecvNode->dataLength, USB_HostCdcDataInCallback, &g_cdc); 
                if (!g_UartSendBusy) 
                g_UartSendNode = getNodeFromQueue(&g_UartSendQueue); 
                if (g_UartSendNode) 
                 g_txfer.buffer = g_UartSendNode->buffer; 
                 g_txfer.size = g_UartSendNode->dataLength; 
                 g_UartSendBusy = 1; 
                 USB_UartSendNonBlocking((USB_UartType *)BOARD_DEBUG_UART_BASEADDR, &g_UartHandle, &g_txfer); 
                if (g_UartActive > USB_HOST_UART_RECV_TIMEOUT_THRSHOLD) 
                    g_UartActive = 0; 
                    if ((g_CurrentUartRecvNode) && (g_CurrentUartRecvNode->dataLength)) 
                        insertNodeToQueue(&g_UsbSendQueue, g_CurrentUartRecvNode); 
                        g_CurrentUartRecvNode = getNodeFromQueue(&g_EmptyQueue); 
         if (NoReceivCounter > 90000 ) 
            NoReceivCounter = 0; 
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:
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
if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success) 
#ifdef HOST_ECHO 
        usb_echo("error to get transfer DataRecv\r\n"); 
        return kStatus_USB_Error; 
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
/*! @brief buffer number used to data transfer */ 
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.



: Edited by User


Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]

Bild automatisch verkleinern, falls nötig