cancel
Showing results for 
Search instead for 
Did you mean: 

Bare metal USB HID

Nickelgrass
Senior

Hello,

I am trying to implement a USB HID keyboard on an STM32F042 without HAL or LL, just simple register defs. I took an example code generated in CubeIDE with HAL and a few other examples. I extended the example with HAL to also implement the LEDs which all works fine. 

I understand how it basically works. I define the descriptors and configure the Endpoints etc. Then I need to transfer the descriptors when the host requires them. But what I can not figure out is how exactly the descriptors are actually transferred. The HAL is so overloaded that it seems impossible to find the exact lines of code where the descriptors are transferred to the host and how that is done exactly. Also where do I put the report descriptor to send some key presses? Can anyone give me some info on how that is done?

1 ACCEPTED SOLUTION

Accepted Solutions
gbm
Principal

Looks like you have some error in the code setting the endpoint buffer pointers. In F0, PMA content may be displayed incorrectly. It must be read and written as 8-bit or 16-bit but unlike in F1 both halfwords in every word are meaningful. You may try to compare your code with mine - link in the signature.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

View solution in original post

9 REPLIES 9
Nickelgrass
Senior

Maybe someone from ST can point me to some additional documentation for the USB peripheral and the PMA?

STOne-32
ST Employee

Dear @Nickelgrass ,

 

Full description of USB and PMA SRAMs is here :https://www.st.com/resource/en/reference_manual/rm0444-stm32g0x1-advanced-armbased-32bit-mcus-stmicroelectronics.pdf#page1262

 

IMG_8430.jpeg

Not  an easy task to handle , all the processing should be interrupt based .Let us know

Hope it helps you .

Ciao

STOne-32

Thanks for the reply. I read the RM (of F042). But I somewhat hoped there was a more detailed explanation to the PMA. Something like a concrete map of what goes where.

Is it correct that the PMA is 16 bit registers but 32 bit aligned?

So from the logic of how it works is that I get an interrupt. The host requests a specific descriptor. I load the descriptor in the PMA and then send it of. Is that basically how it works?

STOne-32
ST Employee

Hi @Nickelgrass,

Here is a legacy STM32F1 series library documentation which was the first software implementation before F0 series , there are some similarities.

https://www.st.com/resource/en/user_manual/um0424-stm32-usbfsdevice-development-kit-stmicroelectronics.pdf

PMA is a kind optimized dual port SRAM where the Core and USB are able to write and read , endpoints should be well programmed with the right size .

Hope it helps ,

STOne-32

Thanks! I had not found that yet.

Nickelgrass
Senior

Hello again,

its been over a year since I posted first. After a few things got in the way today finally I got round to actually start implementing it. So far all is setup and I am debugging receiving packets. 

It seems I am misunderstanding one detail. With BTABLE=0 I have set my control endpoint 0 ADDR_TX to 32 and COUNT_TX to 0. Then ADDR_RX to 96 and COUNT_RX to 64 which translates to 0x8800 with the NUM_BLOCK value 2<<10 and bit 15 set. I checked in the debugger that the values in the USB RAM are actually correct which seems to be the case. Note that the USB RAM is 16 bit wide, so the upper 16 bits of each 32 bit word are just a mirror garbage. 

Nickelgrass_0-1757184588848.png

Now if I start the program I do receive the first two bytes of the first request. But the bytes are written to address 0 and not 96. If I change the COUNT_TX to some value, the data is stored at the address that COUNT_TX points to. I also tried simply using values that the Cube HID example uses. But it still results in rubbish. The request data is simply not stored. My endpoint 0 register is set to 0x3210 just like in Cube. Note that the value at address 0 are actually the first two bytes from the request 0x80 0x06. The 0xDDDDDDDD seems to be some strange garbage. 

Nickelgrass_1-1757184955713.png

Does anyone have an idea what I am doing wrong?

Thanks

kind regards

 

gbm
Principal

Looks like you have some error in the code setting the endpoint buffer pointers. In F0, PMA content may be displayed incorrectly. It must be read and written as 8-bit or 16-bit but unlike in F1 both halfwords in every word are meaningful. You may try to compare your code with mine - link in the signature.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

As you've found out yourself, the device-only USB module bears significant 16-bit legacy, i.e. it has been originally built for 16-bit mcus. This is reflected not only in the access to its registers, but also to the memory buffer, which does not allow other than 16-bit access. Thus, what Cube displays when reading it as 32-bit words, may be and most probably also is incorrect.

I have no insight on why the addressing failed, I don't use that USB actively. However, generally, I strongly recommend reading out and checking content of the registers when debugging, not just relying on the code which wrote into them.

JW

Nickelgrass
Senior

Thanks to gbm and JW! It works now. I had some screw ups in my addressing. My biggest mistake was using 32bit pointers and taking in account the wrong addressing like in F1 series.