cancel
Showing results for 
Search instead for 
Did you mean: 

USBD_LL_PrepareReceive stops filling buffer content

iforce2d
Associate III

I'm making a simple USB MIDI implementation, and using a DAW to send note-on/note-off events from the computer to the device. The maximum packet size is 64 bytes, events are 4 bytes each so up to 16 events should fit in one packet.

When I send one or two events at a time, everything works great - it can run for hours with no problem. But when I send three events (12 bytes) in one packet, something goes wrong.

Selection_132.png

The 12 bytes are received ok, interrupts keep working as normal, and subsequent reported data lengths are correct... but the content of the received buffer never changes any further. It just holds the same old 12 bytes forever, until I reset everything by re-plugging the USB cable.

Is there some reason that more than 8 bytes would be a problem? 

It's interesting the initial 12 bytes are actually received ok, and even more than that is ok too. I can send up to the full 64 bytes allowed in a packet and all the data is received ok, but only once.

Here is the relevant section of code:

__ALIGN_BEGIN uint8_t MIDI_Rx_Buffer[64] __ALIGN_END;

uint8_t USBD_MIDI_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
	USBD_LL_OpenEP(pdev, (midiEndpointIndex_in | IN_EP_DIR), USBD_EP_TYPE_BULK, 64);
	pdev->ep_in[midiEndpointIndex_in].is_used = 1U;

	USBD_LL_OpenEP(pdev, (midiEndpointIndex_out | OUT_EP_DIR), USBD_EP_TYPE_BULK, 64);
	pdev->ep_out[midiEndpointIndex_out].is_used = 1U;

	USBD_LL_PrepareReceive(pdev, (midiEndpointIndex_out | OUT_EP_DIR), (uint8_t*)(MIDI_Rx_Buffer), 64);

	return USBD_OK;
}

uint8_t  USBD_MIDI_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
	return USBD_OK;
}

uint8_t USBD_MIDI_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum)
{
	uint32_t len = USBD_LL_GetRxDataSize(pdev, epnum);
	handleMIDIReceive(MIDI_Rx_Buffer, len); // <-- handle events here
	USBD_LL_PrepareReceive(pdev, (midiEndpointIndex_out | OUT_EP_DIR), (uint8_t*)(MIDI_Rx_Buffer), 64);
	return USBD_OK;
}

 

1 ACCEPTED SOLUTION

Accepted Solutions
iforce2d
Associate III

After much confusion I discovered that of course this was my fault... again. My USB setup is actually non-trivial because it has multiple configurations including composite devices, and the configuration to use is chosen at startup depending on values read from external flash memory.

Anyway, when adding my MIDI configuration I had neglected to update the section where PMA memory is allotted to the endpoints, eg. these type of calls (typically in USBD_LL_Init):

HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);

With no such call made for the MIDI endpoint the address to use remained at zero, which caused MIDI packets to overwrite the first section of PMA where the endpoint table is. It's amazing any communication was able to work at all.

View solution in original post

1 REPLY 1
iforce2d
Associate III

After much confusion I discovered that of course this was my fault... again. My USB setup is actually non-trivial because it has multiple configurations including composite devices, and the configuration to use is chosen at startup depending on values read from external flash memory.

Anyway, when adding my MIDI configuration I had neglected to update the section where PMA memory is allotted to the endpoints, eg. these type of calls (typically in USBD_LL_Init):

HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);

With no such call made for the MIDI endpoint the address to use remained at zero, which caused MIDI packets to overwrite the first section of PMA where the endpoint table is. It's amazing any communication was able to work at all.