LPC1347 - Virtual COM Port questions

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

LPC1347 - Virtual COM Port questions

1,230 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by BPC on Thu May 23 13:36:01 MST 2013
Hello All,

I am using the LPC1347 to read data from a 16 channel ADC and send the data over VCOM to a host PC application (i.e. PUTTY).  The buffer I am sending is 255 chars.  Currently, I simply call:
[COLOR=#3f7f5f][COLOR=#3f7f5f]

pUsbApi->[COLOR=#0000c0][COLOR=#0000c0]hw[/COLOR][/COLOR]->[COLOR=#0000c0][COLOR=#0000c0]WriteEP[/COLOR][/COLOR] (hUsb, USB_CDC_EP_BULK_IN, ([B][COLOR=#7f0055][COLOR=#7f0055]unsigned[/COLOR][/COLOR][/B][COLOR=#7f0055][COLOR=#7f0055][/COLOR][/COLOR] [B][COLOR=#7f0055][COLOR=#7f0055]char[/COLOR][/COLOR][/B][COLOR=#7f0055][COLOR=#7f0055][/COLOR][/COLOR] *)&outBuf[0], [B][COLOR=#642880][COLOR=#642880]strlen[/COLOR][/COLOR][/B][COLOR=#642880][COLOR=#642880][/COLOR][/COLOR](outBuf));
[COLOR=black]Everything works fine, but in reading some posts it seems like pUsbApi->hw->WriteEP should not be called directly.  Is this true?  As an experiment, I implemented the following: [/COLOR]

[B][COLOR=darkred][/COLOR][/B]
[B][COLOR=darkred]void[/COLOR] VCOM_usb_send[/B]([COLOR=#005032][COLOR=#005032]VCOM_DATA_T[/COLOR][/COLOR]* pVcom){
[COLOR=#3f7f5f][COLOR=#3f7f5f]//send txBuf of length [U]txlen[/U] over USB[/COLOR][/COLOR]
[COLOR=#3f7f5f][COLOR=#3f7f5f][/COLOR][/COLOR]pVcom->[COLOR=#0000c0][COLOR=#0000c0]txlen[/COLOR][/COLOR] -= pUsbApi->[COLOR=#0000c0][COLOR=#0000c0]hw[/COLOR][/COLOR]->[COLOR=#0000c0][COLOR=#0000c0]WriteEP[/COLOR][/COLOR] (pVcom->[COLOR=#0000c0][COLOR=#0000c0]hUsb[/COLOR][/COLOR], USB_CDC_EP_BULK_IN, pVcom->[COLOR=#0000c0][COLOR=#0000c0]txBuf[/COLOR][/COLOR], pVcom->[COLOR=#0000c0][COLOR=#0000c0]txlen[/COLOR][/COLOR]);
}

[COLOR=#005032][COLOR=#005032]VCOM_DATA_T[/COLOR][/COLOR]* pVcom = &g_vCOM;


pVcom->[COLOR=#0000c0][COLOR=#0000c0]txlen[/COLOR][/COLOR] = [B][COLOR=#642880][COLOR=#642880]strlen[/COLOR][/COLOR][/B][COLOR=#642880][COLOR=#642880][/COLOR][/COLOR](outBuf);pVcom->[COLOR=#0000c0][COLOR=#0000c0]txBuf[/COLOR][/COLOR] = ([COLOR=#005032][COLOR=#005032]uint8_t[/COLOR][/COLOR]*)outBuf;
pVcom->[COLOR=#0000c0][COLOR=#0000c0]send_fn[/COLOR][/COLOR](pVcom);

[COLOR=black]Both ways work well (as they are calling the same function in the end), but I would just like to know which is more "proper" or reliable.  Any input here would be greatly appreciated. Thank you.[/COLOR]
[/COLOR][/COLOR]
0 项奖励
回复
4 回复数

1,148 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Sat May 25 08:53:39 MST 2013
To send ZLT (Zero-Length Transaction = ZLP),

pUsbApi->hw->WriteEP( EPNum, NULL, 0 );

Tsuneo
0 项奖励
回复

1,148 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by BPC on Fri May 24 21:11:00 MST 2013
Quick update and good news.  I hooked up my Beagle USB protocol analyzer and found that this strange behavior happens if my array was exactly 128 chars.  Since FS USB splits transfers > 64 bytes into multiple 64 byte transactions, if my array length was a multiple of 64 (i.e. 128), the host waits for either a packet of < 64 bytes or a ZLP to terminate the transfer.  I could not find how to implement the ZLP feature, but I was able to force my array to always be >128 and <192.  This has fixed this issue.  It would probably be more elegant to implement the ZLP feature.  Does anyone know if this exists in USB ROM for LPC1347?

Thanks again Tsuneo for your help.
0 项奖励
回复

1,148 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by BPC on Fri May 24 08:12:17 MST 2013
Hi Tsuneo,

Thanks for the reply.  What is the maximum number of characters for a single pUsbApihw->WriteEP call? 

I was starting to see problems at around ~128 chars.  The behavior was strange.  In a PUTTY window, if the array was ~128 chars, everything worked fine, but if the array went over ~128 chars, no data would come through, but when the array went below this threshold, all the data would come through, as if it was stored somewhere.  The driver is usbser.sys.  Perhaps its a driver limitation or USB protocol requirement?

To test this, I changed my FW to send the array in 3 chunks of 64 bytes maximum each.  This resolved the issue, but was wondering if you could enlighten me on why.

Thanks again.
0 项奖励
回复

1,148 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Thu May 23 21:37:56 MST 2013

Quote:
but in reading some posts it seems like pUsbApi->hw->WriteEP should not be called directly.

I believe you may call WriteEP() as you like, on the USB on-chip drivers of LPC1345-7.

The restriction of endpoint read/write is caused by shared resource(s), either on the USB engine or on the stack code.

a) USB engine
On the old USB engine of LPC family, LPC214x, LPC23xx/24xx, LPC17xx and LPC1342-3, endpoint read/write starts with "Select Endpoint" SIE command to specify the target endpoint. And register read/write follows. Lastly, "Validate Buffer" or "Clear Buffer" command finishes the process. In this process, the target endpoint should be kept unchanged.

If USB interrupt would occur and if it would cause any endpoint access, while a main-loop process (or lower priority ISR) is accessing to even other endpoint, the target endpoint on SIE command alters. Therefore, exclusive access to the USB engine is required. For this purpose, a couple of programming technique have been applied.
- USB interrupt is disabled while endpoint access is going on.
OR
- SVC (SWI) of the endpoint process ensures that it runs without any interrupt.

On the other hand, the new USB engine on LPC11Uxx and LPC1345-7 has solved this restriction by independent register interface for each endpoint. On this new SIE, such a technique is not required any more.

b) Stack code
Even if the engine would ensure concurrent access to the endpoints, stack code could break this advantage down by poor coding.

I believe the USB on-chip drivers of LPC1345-7 and LPC11Uxx derive from Keil USB examples. We can examine the original Keil source code on this code bundle. As the USB engine is common among LPC1345-7 and LPC11Uxx, the source code should be common, too.

"Sample Code Bundle for LPC11Uxx Peripherals using Keil's MDK-ARM"
http://www.lpcware.com/content/nxpfile/sample-code-bundle-lpc11uxx-peripherals-using-keils-mdk-arm-0

The implementation of USB_ReadEP() USB_WriteEP() are seen on USBDriver\usbhw.c
These routines are re-entrant for different endpoints. The stack code has no problem on this point. Therefore, I believe hw->ReadEP and hw->WriteEP on the USB on-chip drivers have no problem.


On the other hand, LPCUSBLib (modified LUFA) in LPCOpen is careless on the endpoint coding.
Endpoint_SelectEndpoint() - endpointselected[] static array, which is introduced just for code esthetics, disturbs reentrancy of endpoint access.

I wonder why LPCware doesn't trash LUFA code yet. There are so many problems on the LUFA code, which experienced embedded programmer never does. In the aspect of USB protocol implementation, LUFA is an excellent work. But in the view of embedded coding, LUFA is just a student homework.
- Many local waiting loops which trap MCU execution for milli-seconds order.
- unnecessary "stream" over endpoints makes the code bulky and its speed crawl

"Hey new graduate, MCU isn't a PC"

Tsuneo
0 项奖励
回复