cancel
Showing results for 
Search instead for 
Did you mean: 

usb bootloader in cortex-m3

nicolacodogno
Associate II
Posted on October 16, 2014 at 12:50

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,

Nicola
12 REPLIES 12
Posted on October 16, 2014 at 18:33

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
nicolacodogno
Associate II
Posted on October 17, 2014 at 10:52

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 execute

It 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.

nicolacodogno
Associate II
Posted on October 21, 2014 at 15:00

suggestions?

anyone?
chen
Associate II
Posted on October 21, 2014 at 15:39

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)

Posted on October 21, 2014 at 18:29

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.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
nicolacodogno
Associate II
Posted on October 22, 2014 at 09:59

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?

bye

chen
Associate II
Posted on October 22, 2014 at 11:18

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?

nicolacodogno
Associate II
Posted on October 22, 2014 at 12:36

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.

chen
Associate II
Posted on October 22, 2014 at 12:55

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.