Hi everyone,
I'm working on a project to connect a Hauwai E3531i-2 Surf Stick to the frdmk64 bord via USB and I ran into some difficulties with the CDC-Host Stack. My goal is to send AT-Commands like a Terminal Tool over the USB-Port.
I'm working with KDS 3.2 and SDK 2.2 and got the USB-Host BM examples CDC and MSD up and running and modified them for my purpose. I rewrote the enumeration process so I can differ between different Classes automaticly 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). 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 error:
1. The Interrupt Pipe fails to be established
2. Line State is "ok", but all Values are zero.
3. data transfer error with code 10
4. when I try to send Data I just get successes but I don't see any Data coming in.(But I am not sure where I would see them)
I try to send Data by creating a Node fill it's buffer with the AT Command and send it to the queue.
Now my questions:
1. Has anyone an Idea on how to do this?
2. Is this the right procedure for sending data?
3. Am I even right with using CDC-Stack?
4. Are there any examples with better Documentation? I'm not that familiar with this Topic and my experience with Controllers is just around half a year quite intense working with this board on other projects.
The ModeSwitch just has to happen after a power down of the Stick so, so it would be possible to load different Projects to the board without the Stick changing its operation mode. So if someone could lead me to a project that does this Serial Connection as a host it would really help as a prove of concept.
Also I would like to not use PE, I don't like it I also try to do all project without additional RTOS.
This is my first post so if I missed some important Information I'm happy to provide them.
Cheers
Bastian
Update:
I opened an additional thread USB host K64F weird "receive" behaviour .
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 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)
{
if(g_UsbSendQueue)
{
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);
}
}
else
{
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);
}
}
else
{
NoReceivCounter++;
}
}
}
if (!g_UartSendBusy)
{
if(g_UartSendQueue)
{
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);
}
}
}
g_UartActive++;
if (g_UartActive > USB_HOST_UART_RECV_TIMEOUT_THRSHOLD)
{
g_UartActive = 0;
USB_BmEnterCritical(&usbOsaCurrentSr);
if ((g_CurrentUartRecvNode) && (g_CurrentUartRecvNode->dataLength))
{
insertNodeToQueue(&g_UsbSendQueue, g_CurrentUartRecvNode);
g_CurrentUartRecvNode = getNodeFromQueue(&g_EmptyQueue);
}
USB_BmExitCritical(usbOsaCurrentSr);
}
}
}
if (NoReceivCounter > 90000 )
{
USB_HostCdcInitBuffer();
NoReceivCounter = 0;
}
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:
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");
#endif
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 */
#define USB_HOST_CDC_BUFFER_NUM 10U
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?
And most important could someone give me a comment, who didn't had these kind of Problems? 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.