I keep getting a failure with the 'Configuration Descriptor'. (bare-metal code)

, Jan 05, 2025|
0
59
13

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)

https://github.com/OpenNuvoton/NUC126BSP/blob/master/SampleCode/StdDriver/USBD_VCOM_SinglePort/descriptors.c#L41


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();
}

https://github.com/mymy49/yss/blob/87e0a1227602c656b15bb7dfae6fcc2761949dfa/src/UsbClass/UsbClass.cpp#L151


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;
}

https://github.com/mymy49/yss/blob/87e0a1227602c656b15bb7dfae6fcc2761949dfa/src/targets/nuvoton/driver/drv_usbd_nuvoton.cpp#L212


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;
			}
		}

https://github.com/mymy49/yss/blob/87e0a1227602c656b15bb7dfae6fcc2761949dfa/src/targets/nuvoton/driver/drv_usbd_nuvoton.cpp#L310


Please help me.

Reply