Hello,
As shown in the image attached below, I have successfully completed 'Get Device Descriptor', 'Set Address', and 'Get Configuration Descriptor (9 Bytes)'.
However, the 67-byte 'Get Configuration Descriptor' does not send an ACK from the Host side.
I compared the data I sent with the data defined by Nuvoton to check if there was any problem. Below is the data I sent and the Nuvoton Code Link I referenced.
(First 64 Bytes)
(Second 3 Bytes)
I don't know if the timing of my preparation to receive the ACK is wrong, or if the data sent to the host is wrong.
The link below is the code to send the Descriptor.
void UsbClass::process(void) { request_t *request = (request_t*)mSetupData; uint8_t buf[256]; bool ableFlag = false; bool addrFlag = false; switch(request->wRequest) { case 0x0680 : // Get Descriptor switch(request->wValue) { case 0x0100 : // Device Descriptor ableFlag = getDeviceDescriptor((devDesc_t*)buf); break; case 0x0200 : // Configuration Descriptor ableFlag = getConfigDescriptor((confignDesc_t*)buf, request->wLength); break; case 0x0600 : // Device Qualifier Descriptor ableFlag = getDeviceQualifierDescriptor((devQualifier_t*)buf); break; default : ableFlag = false; break; } break; case 0x0500 : // Set Address ableFlag = true; addrFlag = true; *buf = 0; break; default : ableFlag = false; break; } mUsbd->lock(); if(ableFlag) mUsbd->send(0, buf, *buf); // Send else mUsbd->stall(0); if(addrFlag) mUsbd->setAddress(request->wValue); mUsbd->unlock(); }
The link below is the code that sets up receiving an ACK.
error_t Usbd::send(uint8_t ep, void *src, uint16_t size) { if(ep >= USBD_MAX_EP) return error_t::UNSUPPORTED_EP; ep = mInEpAllocTable[ep]; if(ep >= USBD_MAX_EP_BUF) return error_t::UNSUPPORTED_EP_BUF; if(size >= mMaxPayload[ep]) { mInSendingSize = size - mMaxPayload[ep]; size = mMaxPayload[ep]; mInSendingBuffer = (uint8_t*)src; mInSendingBuffer += mMaxPayload[ep]; } else { mInSendingSize = 0; } mInSendingCompleteFlag = false; mDev->EP[ep].CFG |= USBD_CFG_DSQSYNC_Msk; copyBuffer((uint8_t*)mSetupRxBuffer + mDev->EP[ep].BUFSEG, (uint8_t*)src, size); mDev->EP[ep].MXPLD = size; if(ep == 0) // ACK Ready { mDev->EP[1].CFG |= USBD_CFG_DSQSYNC_Msk; mDev->EP[1].MXPLD = mMaxPayload[1]; } while(!mInSendingCompleteFlag) thread::yield(); return error_t::ERROR_NONE; }
The link below is a code to split and send additional data if it exceeds 64 bytes.
if(intsts & USBD_INTSTS_EPEVT0_Msk) // Control In { mDev->INTSTS = USBD_INTSTS_EPEVT0_Msk; switch(mDev->EPSTS0 & 0xF) { case 0 : // IN ACK if(mInSendingSize > 0) { if(mInSendingSize > mMaxPayload[0]) { buf = mMaxPayload[0]; mInSendingSize -= mMaxPayload[0]; } else { buf = mInSendingSize; mInSendingSize = 0; } mDev->EP[0].CFG |= USBD_CFG_DSQSYNC_Msk; copyBuffer((uint8_t*)mSetupRxBuffer + mDev->EP[0].BUFSEG, mInSendingBuffer, buf); mInSendingBuffer[0] += buf; mDev->EP[0].MXPLD = buf; } else { mInSendingCompleteFlag = true; } break; case 1 : // IN NAK break; case 2 : // OutPacket Data0 ACK break; case 3 : // OutPacket Data0 ACK break; } }
Please help me.
Reply
For USB Full-Speed devices, the maximum data payload size for a control transfer packet is limited to 64 bytes as per the USB 2.0 specification.
chhuang16
I didn't know that the maximum packet size for USB 2.0 was 64 bytes, so I just set it to 64 bytes and used it. Thank you.
Currently, the maximum size is 64 bytes, so it is divided into 64-byte units and transmitted. I also checked that the code provided by Nuvoton is divided and transmitted if it exceeds 64 bytes.
https://github.com/OpenNuvoton/NUC126BSP/blob/master/Library/StdDriver/src/usbd.c#L570
mymy49
How about the packets in USB capture if you use the sample code directly.
NUC126BSP/SampleCode/StdDriver/USBD_VCOM_SinglePort at master · OpenNuvoton/NUC126BSP
chhuang16
I'll try building the Virtual COM Dual version of M433 in Crossworks for ARM and leave a comment with the results.
Thank you.
mymy49
Here is the sample code of VCOM for M433:
https://github.com/OpenNuvoton/M433BSP/tree/master/SampleCode/StdDriver/USBD_VCOM_SerialEmulator
chhuang16
Oh! Thank you.
The company I'm currently working for is preparing a project using M433. The PWM pin of the manufactured board is connected to the EPWM pin, so it seems that an EPWM driver needs to be written in the OS first.
Once the EPWM driver is written, let's make sure the 'USBD_VCOM_SerialEmulator' project compiles normally in Crossworks for ARM.
mymy49
It worked fine on Crossworks for ARM.
The problematic section also worked normally, as shown in the image below.
I found a problem with modifying data of FMC->CYCCTL register in Nuvoton library without unlocking. I modified it as in the link below and it worked fine.
Now that I have some working code, I'll have to take a closer look at it with the debugger. ^^
mymy49
I found out what was wrong. ^^;
Currently it works fine as shown in the image below.
Thank you~!!
mymy49
That's good news.
chhuang16
As mentioned above, I found something strange with the Nuvoton Driver.
I found a problem with modifying data of FMC->CYCCTL register in Nuvoton library without unlocking. I modified it as in the link below and it worked fine.
Please note.
mymy49
Ah ha~
I used the code provided by Crossworks for ARM as the link below. ^^;
https://github.com/mymy49/CrossworksForARM_Nuvoton_M43x/blob/main/targets/M43x/Source/M43x_Startup.s
Okay, thank you.
mymy49
Finally done~!
There are still some Setup requests that haven't been written yet...
But it works well ^^; If I find any problems, I will analyze what they are and add them.
I have created an example of Dual COM Port operating as echo, as shown in the link below.
https://github.com/mymy49/Nuvoton_M43x/blob/NuMaker-M433SE_V1.0/BSP/app/src/main.cpp#L66
mymy49