2014-10-16 03:50 AM
Hi everybody,
this is my first post on STe2e, so be patient with me. I've read a good amount of threads related to bootloaders/interrupt/VTOR but I cannot find a final word to my problem so I decided to start a new thread. I'm working on stm32f103 and my application is using USB for communication. I wrote a simple bootloader based on AN2557 for application update through USB. For various reasons I must start the application code without resetting the MCU and after using USB. Once jumped to application code, the USB_IRQHandler is never executed, leading to usb fault. NOTE: before jumping I successfully shut down USB interface and disable all interrupts and the vector table is remapped at beginning of user application. After trying different approaches I disabled USB interrupts in bootloader and manage USB by polling. So USB_IRQHandler is correctly executed in user application now.. but I don't like this solution so much. Is there a way to use the same interrupt in booltloader AND in application? Thank you for your kind help, Nicola2014-10-16 09:33 AM
Is there a way to use the same interrupt in bootloader AND in application?
Of course, if you're coding both ends and can hand over control, you can do it seamlessly. You will need to pass information between the two about the configuration and state. You'll likely need to carve out a common area of SRAM to share between the two processes, and use an agreed data/control structure to permit a clean hand-off.2014-10-17 01:52 AM
Hi clive1, thank you for your reply.
I understand what you say, but the scenario is simpler than that.
I don't need to jump back and forth between bootloader and application and don't need to share control and data. I want the bootloader to: 1. initialize USB peripheral 2. talk to USB host (on PC) 3. execute the application code or flash a new code and executeIt is ok to turn USB off and reinitialize it and it is what I cannot achieve. In particular I cannot make interrupts related to USB to trigger the ISR even if the USB_CNTR is correctly set and I can see interrupts sources updating USB_ISTR.So, if I use USB interrupts in bootloader they will not work in the application code.
If I set bootloader to use USB ''in polling'' the I can use interrupts in the application.In attachment my code for USB reset and jump to application code:
#define APPLICATIONADDRESS 0x8003000
__asm void _jump(uint32_t address)
{ LDR SP, [R0] // SP-> address LDR PC, [R0, #4] // PC-> address+4 }[..]
case CMD_RUN: FLASH_Lock(); // ######### USB reset ######### // USB_CNTR = 0x01 disable all interrupts and force USB reset *((uint32_t*)0x40005C44) = 1; // USB_CNTR = 0x00 clear interrupt status register *((uint32_t*)0x40005C40) = 0; // disconnect cable USB_Cable_Config(DISABLE); // USB_CNTR = 0x03 switch-off device *((uint32_t*)0x40005C44) = 3;// ######### INT reset #########
// disable ALL interrupts ICER[0:2] *((uint32_t *)0xE000E080) = 0xFFFFFFFF; *((uint32_t *)0xE000E084) = 0xFFFFFFFF; *((uint32_t *)0xE000E088) = 0xFFFFFFFF; // clear ALL pending INT ICPR[0:2] *((uint32_t *)0xE000E280) = 0xFFFFFFFF; *((uint32_t *)0xE000E284) = 0xFFFFFFFF; *((uint32_t *)0xE000E288) = 0xFFFFFFFF;EXTI_DeInit();
// jump to application code _jump(APPLICATIONADDRESS); break; [..]Is there a way to use the same interrupt in bootloader AND in application?
Of course, if you're coding both ends and can hand over control, you can do it seamlessly. You will need to pass information between the two about the configuration and state. You'll likely need to carve out a common area of SRAM to share between the two processes, and use an agreed data/control structure to permit a clean hand-off.2014-10-21 06:00 AM
suggestions?
anyone?2014-10-21 06:39 AM
Hi
I have no problems doing this. At the end of the bootloader - do a soft disconnect on the USB : // write directly to register to force a soft disconnect USB_OTG_dev.regs.DREGS->DCTL |= 0x02; In your application - you need to re-initialise the USB stack. (BTW - I did this with the old USB OTG library not the STM32Cube)2014-10-21 09:29 AM
suggestions? anyone?
You seem to be confused about what I stated, I wasn't talking about jumping back-n-forth between the boot loader and application, I was suggesting a clean one way transfer, where adequate information was passed contractually between the two. You'll probably want to rework the application's SystemInit() code so that it doesn't tear down and reconfigure the clocking and PLL, and you'd want it to point the vector table at the one owned by the application.2014-10-22 12:59 AM
hi sung.chen_chung,
and thank you for joining the discussion. My code uses standard peripheral library since Cube is not released yet for stm32F1. Also I use USB FS device library since stm32f103 has not OTG support. My bootloader behaves as you suggested forcing disconnection and peripheral de-initialization, then the application reinitialize everything (unless I didn't make any mistake, of course). What cortex are you working on? bye2014-10-22 02:18 AM
Hi
''What cortex are you working on?'' The commercial project I am working uses a STM32F405 Which means that we have used the STM32 USB OTG library V2.1.0 I have only briefly looked at the STM32 USB FS library but never used it. ''My bootloader behaves as you suggested forcing disconnection and peripheral de-initialization, then the application reinitialize everything (unless I didn't make any mistake, of course).'' I did not find it necessary to de-initialise the USB in the bootloader before handing over to the application. ''then the application reinitialize everything'' Have you tried reseting the USB peripheral in the RCC registers before calling the USB init routines?2014-10-22 03:36 AM
Hi clive1,
you talked about having''a common area of SRAM to share between the two processes''
making me think of a sort of ''ping-pong'' between two processes sharing the same peripheral. I cannot imagine how the use of a shared SRAM area could help solving the interrupt problem. You suggest to pass''information between the two about the configuration and state''
is unclear, what''adequate information''
would you pass considering I'm killing peripherals and cleaning interrupts register before jumping to the application code? Please explain your point.''You'll probably want to rework the application's SystemInit() code so that it doesn't tear down and reconfigure the clocking and PLL, and you'd want it to point the vector table at the one owned by the application.''
The SystemInit() routine on the application side consists of one single line: SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; // and yes, the vector table address is correct :) Please note: everything works fine if I disable USB-triggered ISR on bootloader side. But if I use them in the bootloader they won't be triggered anymore in application. Other non-USB-triggered ISRs on application side work indifferently!! I wonder if my issue could be related to a specific choice or bug in the IC design.2014-10-22 03:55 AM
Hi
In the bootloader I wrote, the USB is not automatically enabled. It is only enabled if needed - ie the bootloader is told to do a firmware upgrade. This is where the shared RAM area comes in - ie how does the application tell the bootloader that it need to to perform a firmware upgrade, in a shared piece of RAM and a special flag, just some string that is very unlikely to appear at random. The application then reboots the processor and the bootloader looks at the RAM locaion for the string. This however, does not explain or fix your problem of the USB not working when used in both Bootloader and application. A simple solution may be to check the RAM location for the string and not start the USB in the bootloader and start the application. If a firmware upgrade is needed, set the flag in RAM and reboot into the bootloader, the bootloader sees the flag, enables USB and does the firmware upgrade, clears the flag and reboots.