Proper way to shutdown

Discussions and support about ChibiOS/HAL, the MCU Hardware Abstraction Layer.
User avatar
wurstnase
Posts: 121
Joined: Tue Oct 17, 2017 2:24 pm
Has thanked: 43 times
Been thanked: 30 times
Contact:

Proper way to shutdown

Postby wurstnase » Mon Dec 18, 2017 10:46 pm

Hi,

I working on my first ChibiOS project. First I want to make a very simple bootloader. Writing something over serial and jumping to main.
I'm working with a Nucleo F411RE and F446RE now for over 2 years with bare metal.

So I started with HAL and made a bootloader. Jump to my bare metal firmware. Everything seems to work.

Next step bootloader HAL jumping to HAL. But I had issues.
Looks like the main application start to hang.

So first I thought, that the problem is with the main app. Starting this app without bootloader at 0x8000000 works fine.
Making an app with NIL is also working as standalone. But jumping from bootloader makes always issues. After flashing all of them are working.

So now I start to think it's not the main app, it's the bootloader. And... BINGO.

My bootloader makes always problems, or only, when using a xxxSleepxxx(). So reading some other stuff, also some guidance to shutdown the RT I found my problem with the SysTick. So what kind of pitfalls could I miss also?

So currently my bootloader looks like this:

Code: Select all

#include <stdbool.h>

#include "hal.h"

typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;

#define APP_OFFSET 0x4000
#define NVIC_VectTab_FLASH 0x08000000

#define APP_ADDRESS (NVIC_VectTab_FLASH | APP_OFFSET)

/*
 * Application entry point.
 */
int main(void) {

  static const SerialConfig uart_cfg =
  {
    38400,
    0,
    USART_CR2_STOP1_BITS,
    0
  };

  halInit();

  osalSysEnable();

  sdStart(&SD2, &uart_cfg);
  palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));
  palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));

  palSetPadMode(GPIOC, GPIOC_BUTTON, PAL_MODE_INPUT);
  palSetPadMode(GPIOA, GPIOA_LED_GREEN, PAL_MODE_OUTPUT_PUSHPULL);

  sdWrite(&SD2, (uint8_t *)"\r\nLet's jump!\r\n", 15);

  // while pressing the user button on the nucleo, we could later add
  // some flashing stuff or so.
  while (!palReadPad(GPIOC, GPIOC_BUTTON)) {
    static uint8_t counter = 0;
    counter++;

    palTogglePad(GPIOA, GPIOA_LED_GREEN);
    osalThreadSleepMilliseconds(1000/(counter + 1));

    if (counter > 9) counter = 0;

    sdPut(&SD2, '0'+counter);
    sdWrite(&SD2, (uint8_t *)"\r\n", 2);
  }

  JumpAddress = *(__IO uint32_t *)(APP_ADDRESS + 4);
  Jump_To_Application = (pFunction)JumpAddress;

  sdStop(&SD2);
  osalSysDisable();

  /* Clear pending interrupts just to be on the safe side */
  SCB->ICSR = SCB_ICSR_PENDSVCLR_Msk;

  /* Disable the SysTick */
  SysTick->CTRL  = 0;

  /* Disable all interrupts */
  for(uint8_t i=0; i<8; i++)
    NVIC->ICER[i] = NVIC->IABR[i];

  SCB->VTOR = APP_ADDRESS;

  __set_MSP(*(__IO uint32_t *)APP_ADDRESS);
  Jump_To_Application();

  while (true)
  {
  };
}


Disabling the SysTick is from me. The pendSV handler and disabling other interrupts is copied from another bootloader:
https://github.com/fpoussin/ChibiOS-Boo ... .c#L22-L27

But when comment out the pendSV and disabling all interrupts, my program still works. So when do I need to disable all these things? Do I?
\o/ Nico

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Proper way to shutdown

Postby Giovanni » Tue Dec 19, 2017 6:05 am

Hi,

You need to restore everything like after a reset:

- NVIC
- SysTick
- Any peripheral (note that hosted application HAL would reset everything on start anyway but better do it cleanly)
- Clocks <- HAL does not do this currently, you need to switch to HSI and stop PLLs
- Stack pointer, it is initialized in HW, you need to take the value from the hosted appication vectors table and initialize before jumping

I am thinking to add a bootloader template application at some point but I need to introduce in HAL a clock de-initialization feature first in order to make it more portable.

Giovanni

User avatar
wurstnase
Posts: 121
Joined: Tue Oct 17, 2017 2:24 pm
Has thanked: 43 times
Been thanked: 30 times
Contact:

Re: Proper way to shutdown

Postby wurstnase » Tue Dec 19, 2017 10:23 am

- NVIC

Done with the NVIC-loop?!?

- SysTick

OK, done.

- Any peripheral (note that hosted application HAL would reset everything on start anyway but better do it cleanly)

sdStop should do this? I guess I should also reset the pal also? Probably a halInit() will do this?

- Clocks <- HAL does not do this currently, you need to switch to HSI and stop PLLs

When the main application uses the same clockspeed, it should work anyway?

- Stack pointer, it is initialized in HW, you need to take the value from the hosted appication vectors table and initialize before jumping

Done with __set_MSP() and SCB->VTOR.
\o/ Nico

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Proper way to shutdown

Postby Giovanni » Tue Dec 19, 2017 10:31 am

Hi,

xxStop() does stop the peripheral.

The clock initialization code assumes a post-reset situation, it is not tested to work with PLLs already on etc

Giovanni


Return to “ChibiOS/HAL”

Who is online

Users browsing this forum: No registered users and 13 guests