2024-11-01 07:16 PM
Trying to work with the STM32F411 USB OTG peripheral and compiling with Segger Embedded Studio, I'm having trouble clearing out the USB interrupts.
The USB peripheral has IRQ bits that are write-1 to clear. As can be seen in the image below, the breakpoint has triggered under the case that the desired interrupts are cleared out (OTG_HOST_ONLY_IRQs evaluates to 0xF020000A), however, the debugger's register view is showing that they are in fact not cleared. It is suspicious that the value loaded into reg_value happens to be 0x04000020 as this is the stated default value of GINTSTS according to the reference manual (RM0383 rev 3). The CMOD bit is the only bit in this register that is not an interrupt and is correctly showing 1 (host mode) in the debugger's register report, but this bit did not get set when the value of GINTSTS was copied into reg_value. I don't see anything in the reference manual that would indicate GINTSTS needs to be unlocked somehow before doing a read, and the debugger's register report appears to reflect the true value, since if I skip trying to verify the IRQs are cleared and immediately enable the NVIC global interrupt, code branches immediately to the ISR. It is not clear to me why the debug tool correctly reads this register while the compiled code cannot.
2024-11-01 08:40 PM
Thank you for the feedback, although it does not address my issues.
My OP points out that there is a variance in how the GINTSTS register is read between trying to store that value in a local variable vs. what the debugger shows.
I specifically mention that I'm aware that these IRQs are write-1 to clear. As can be seen for just one example, the value I attempt to write to GINTSTS has bit position 1 set which corresponds to the MMIS IRQ, but the debug register view in the lower right is still showing this as set.
2024-11-02 12:55 AM - edited 2024-11-02 12:58 AM
The post you've answered above was an attempt to spam with an AI-generated text.
Are you sure the function appearing to delay for 25ms does indeed that?
Show definition of OTG_FS_GINTSTS.
In cases like these, I look at the disasm.
MMIS bit being set is also a concern. Maybe you already have an interrupt enabled, which may have caused some unexpected operations?
JW
2024-11-04 08:24 AM
Looks like the scam post is gone, I was debating reporting it before.
OTG_FS_GINTSTS is set up as follows :
#define OTG_BASE 0x50000000 // [1]p.38
//
// [1]p.754
#define OTG_FS_GINTSTS (*(volatile uint32_t *)(OTG_BASE+0x014))
The reference page numbers are from RM0383. I haven't been seeing any other issues writing to the USB registers with this setup. Normally I might have used the register definitions provided by Segger but their default header for the STM32F411 doesn't appear to include the USB peripheral for some reason, even though it's there in the XML file used by the debugger.
The timer code was been verified running correctly on an STM32F411 in a different project but I can try to verify it again here. The code that executes before this sets up the main clock to run at 96MHz with 48MHz USB clock, then I reset the USB peripheral via the reset bit via RCC_AHB2RSTR. I also explicitly disable the USB IRQ. I'm not disabling the global IRQ as this is off by default and currently no code executes to turn this on before the USB init code executes.
The code is being compiled as follows:
while (USB_TRUE) {
OTG_FS_GINTSTS |= OTG_HOST_ONLY_IRQs;
2014 movs r0, #20
F2C50000 movt r0, #0x5000
6802 ldr r2, [r0]
210A movs r1, #10
F2CF0120 movt r1, #0xF020
430A orrs r2, r1
6002 str r2, [r0]
--- pfcta_usb_core.c -- 169 --------------------------------
reg_value = OTG_FS_GINTSTS;
6800 ldr r0, [r0]
9002 str r0, [sp, #8]
--- pfcta_usb_core.c -- 170 --------------------------------
if ((reg_value & OTG_HOST_ONLY_IRQs) == 0x00) {
9802 ldr r0, [sp, #8]
4208 tst r0, r1
D100 bne 0x080012B2
--- pfcta_usb_core.c -- 171 --------------------------------
break;
E000 b 0x080012B4
--- pfcta_usb_core.c -- 167 --------------------------------
while (USB_TRUE) {
E7EF b 0x08001294
2024-11-04 10:15 AM
So, we are basically talking about 3 bits here, which were actually cleared just before the test (and read as zero as witnessed by the reg_value variable, but then got set again until they get read by the debugger and displayed (btw., don't you have some sort of "live values" enabled in your IDE, reading out the registers repeatedly as long as they are displayed and/or the program is suspended in breakpoint?)
And we are talking about 3 bits here:
- CIDSCHG - is PA10 set as OTG_FS_ID, and is anything toggling there?
- SOF - this gets set automagically each 1ms if you have the all other things set up as expected for host
- MMIS - this is what is IMO the only intriguing thing here, as it would indicate that there is some access to the device-only registers. I don't know what to think about this one; but also don't see much value in triggering an interrupt upon this flag, except for debugging purposes.
JW
PS. Don't RMW to clear those write-1-to-clear bits; rather, perform a simple write. With the "full mask" you are using this doesn't really matter, but it's a bad style which will bite elsewhere.