3
votes

Update: Maybe the better question to ask is how should I go about debugging this problem? I'm using VS Code with OpenOCD debugger. I always clean build. The best I can do once I JumpToApplication() is see what addresses the debugger stops at when I pause/step into.

I am able to flash a program into Partition A (@address 0x8060000) and verify it with a CRC check. The program runs anything in while loop fine (LED3 toggling, UART); however, the LED2 toggling based off of a timer interrupt does not work. When I flash the program normally (ie not with my bootloader) it works 100%, including LED2 toggling.

Here are some of the resources I have addressed (1, 2, 3, AN2606). How do I get the interrupts working for my second application? The resources recommend I clear pending interrupts, but I don't know the best way to approach that. In my bootloader app I use the ETH, UART and GPIO peripherals so I will go through the manual and read registers to clear the interrupt flags but what about the other interrupts like NMI, HardFault, do I have to figure out how to clear those as well? Through my Google searching I have not found any convenient functions to clear all pending interrupts, does it exist?

Below I include the jump function/linker file for the bootloader application at 0x8000000 and the main.c/linker file for the application at 0x8060000:

JUMP FUNCTION IN BOOTLOADER PROGRAM AT 0x8000000

void ApplicationManager::RunActivePartition()
{     
    JumpToApplication = (void (*)(void)) (*((uint32_t *) (active_partition.address + 4)));

    /* Set vector table offset register */
    SetVectorTable(MemoryInfo::BTLR_ADDRESS, MemoryInfo::PARTITION_A_OFFSET_FROM_BTLR);

    /* STM32 needs the stack pointer to start at the beginning of
    ** the application in flash. This must happen last */ 
    __set_MSP(*(__IO uint32_t*) active_partition.address);

    JumpToApplication();


    /*************** Other things I have tried ***************/
    /* Reset RCC clock configuration */
    // HAL_RCC_DeInit();

    /* Disable peripheral clocks */
    // __HAL_RCC_GPIOA_CLK_DISABLE();
    // __HAL_RCC_GPIOB_CLK_DISABLE();
    // __HAL_RCC_GPIOC_CLK_DISABLE();
    // __HAL_RCC_GPIOD_CLK_DISABLE();
    // __HAL_RCC_GPIOG_CLK_DISABLE();
    // __HAL_RCC_GPIOH_CLK_DISABLE();
    // __HAL_RCC_PWR_CLK_DISABLE();

    /* Disable Peripherals */
    // HAL_CRC_MspDeInit(&hcrc);
    // HAL_UART_DeInit(&huart3);

    /* Disable and reset systick timer */
    // SysTick->CTRL= 0;
    // SysTick->LOAD = 0;
    // SysTick->VAL = 0;

    /* Disable all interrupts */
    // __disable_irq();

    /* Clear pending interrupts */

    /* Remap system memory */
    // SYSCFG->MEMRMP = SYSCFG_MEMRMP_MEM_MODE_0; // 

    /*************** What I want to add when more basic implementation works ***************/
    // /* Relocate vector interrupt table to RAM */
    // CopyVectorInterruptTable();

    // /* TODO: Patch VIT with bootloader interrupt handlers (ex: hard fault handler) */
    // PatchVectorInterruptTable();

    // if (!CopyandPatchOkay())
    // {
    //     LOG_DEBUG("Vector interrupt table not probably copied and/or patched \n");
    // }
    // else
    // {
    //     LOG_DEBUG("Device ready to jump into application \n");
    // }
}

LINKER FILE FOR APPLICATION (BOOTLOADER) 0x8000000

/* Highest address of the user mode stack */
_estack = 0x20010000;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 192K
CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 2048K
}

APPLICATION TO JUMP TO AT 0x8060000

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim10)
{
 HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  SCB->VTOR = 0x8060000; //---- @berendi's suggestion
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART3_UART_Init();
  MX_TIM10_Init();
  /* USER CODE BEGIN 2 */
  uint32_t count = 0;
  HAL_TIM_Base_Start_IT(&htim10);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    for (uint32_t i=0; i < 100000; i++);
    HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
    _printf("Hi %d \n", count);
    count++;
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

LINKER FILE FOR APPLICATION (INTERRUPT-BLINKY) 0x8060000

/* Highest address of the user mode stack */
_estack = 0x20010000;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 192K
CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8060000, LENGTH = 1024K
}
1
Your "bootloader" code seems to disable all interrupts. Do your main "application" code enable interrupts again?Some programmer dude
I added __enable_irq() as the first line in main in my blinky program. Now both LED's do not toggle.mbards
FYI: arm KEIL: ARM: How to Write a Bootloader: keil.com/support/docs/3913.htmGabriel Staples

1 Answers

4
votes

In projects generated by STM32CubeMX, the SystemInit() function in system_stm32f4xx.c, called by the startup code before main(), resets the vector table address register to the start of the FLASH.

/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET  0x00 /*!< Vector Table base offset field.
                                   This value must be a multiple of 0x200. */

/* -- snip -- */

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif

You can edit this file directly (and not run STM32CubeMX on the project again, because it appears to overwrite this file), or simply set the right value again in main(), before enabling interrupts.