stm32 HID class USB crash explained
Problem: If you call pyb.USB_HID().recv(...) before the USB device is enumerated by the host, a null pointer is dereferenced and hard fault results immediately.
This happens because the HID interface object is not initialized: usb_device.usbd_cdc_msc_hid_state.hid and in particular usb_device.usbd_cdc_msc_hid_state.hid.usbd are zeros.
The init should happen:
- when the device is enumerated (SetConfig chapter 9 code) in
USBD_SetClassConfig - calls
USBD_CDC_MSC_HID_Initwhich callsusbd_cdc_state_init - I could not find any other paths that might initialize the
usbdfield in particular; the other fields are also wrong, such as defaulting todev_speed == USBD_SPEED_HIGHeven on my board which can't do high speed, becauseUSBD_SPEED_HIGHis zero.
The null de-ref happens inside USBD_HID_ReceivePacket(&hid->base...) when called by usbd_hid_rx() and it only gets that far (thinking that zero bytes have been received already) because it looks at the un-initialized usbd_hid_itf_t *hid and sees zero for hid->report_in_len rather than USBD_HID_REPORT_INVALID which would be more appropriate in this state.
My workaround, on ports/stm32/usbd_hid_interface.c:
--- a/ports/stm32/usbd_hid_interface.c
+++ b/ports/stm32/usbd_hid_interface.c
@@ -49,7 +49,7 @@ int8_t usbd_hid_receive(usbd_hid_state_t *hid_in, size_t len) {
int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout_ms) {
// Wait for an incoming report
uint32_t t0 = mp_hal_ticks_ms();
- while (hid->report_in_len == USBD_HID_REPORT_INVALID) {
+ while (hid->report_in_len == USBD_HID_REPORT_INVALID || !hid->base.usbd) {
if (mp_hal_ticks_ms() - t0 >= timeout_ms || query_irq() == IRQ_STATE_DISABLED) {
return -MP_ETIMEDOUT;
}
@@ -62,6 +62,7 @@ int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout_
// Schedule to receive next incoming report
hid->report_in_len = USBD_HID_REPORT_INVALID;
+ assert(hid->base.usbd);
USBD_HID_ReceivePacket(&hid->base, &hid->report_in_buf[0]);
I can't explain why this bug isn't seen more often, but I think what was covering it for me was that pyb_usb_dev_init() gets called after the end of boot.py and so was defaulting to VCP+HID+MSC but I've recently changed things so that USB doesn't get enabled until sometime much later in main.py (ie. I called pyb.usb_mode(None) in boot.py) and that initialized the composite USB device as "VCP+HID". I suspect something in the code path for the MSC setup initializes the HID interface state before enumeration, but I can't confirm that.
USB HID Receive on Micro Python
How to receive HID data in my stm32F4Discovery board with Micro Python?
please can you provide some Docs link or example with receiving and callback (onReceive)?
pyb.usb_mode("VCP+HID", pid=0x1234, hid=(0, 0, report_len, 50, hid_desc))
when I double pressed tab button I have only one function:
pyb.USB_HID.send
receiving data from host device like PC or tablet not implemented yet on stm32F4Discovery board?
#work good
i=0
while True:
pyb.USB_HID.send(0,"{} Yet another long text".format(i))
pyb.delay(100)
i+=1
I develop https://play.google.com/store/apps/details?id=com.appspot.usbhidterminal
about board and Micro Python version info, how to get it(with sudo screen /dev/ttyACM0 I have no info, only blank screen, after hit enter, I see:
AT
Traceback (most recent call last):
File "<stdin>", line 1
SyntaxError: invalid syntax
>>>
>>> 9+8
17
>>>
PYB: sync filesystems #PRESSED CRTL+D
PYB: soft reboot
Traceback (most recent call last):
File "main.py", line 9, in <module>
KeyboardInterrupt: #PRESSED CRTL+C
Micro Python v1.4.2-55-g2378be4 on 2015-05-03; F4DISC with STM32F407
Type "help()" for more information.
>>>
ihor@ihor-M50Vc:~$ sudo picocom /dev/ttyACM0
picocom v1.7
port is : /dev/ttyACM0
flowcontrol : none
baudrate is : 9600
parity is : none
databits are : 8
escape is : C-a
local echo is : no
noinit is : no
noreset is : no
nolock is : no
send_cmd is : sz -vv
receive_cmd is : rz -vv
imap is :
omap is :
emap is : crcrlf,delbs,
Terminal ready
~x~ # PRESSED Enter
Traceback (most recent call last):
File "<stdin>", line 1
SyntaxError: invalid syntax
>>>
, and then command prompt >>>)?
please add pyb.version(), and help() support with:
(about version, number of version integer value, full info - text)
Micro Python v1.4.2-55-g2378be4 on 2015-05-03; F4DISC with STM32F407
Type "help()" for more information.
and Thank you, Micro Python is awesome, good one =), I did not like Python, but now my view is changing =)