2024-03-01 07:14 AM
I need to debug an application code which is not on the default flash address (0x8000000) but it is at 0x8008000. I just changed the flash origin address to that value. When the execution reaches the CAN initialization part, the program counter goes outside of program code (0x8000f44). Note that the code work as expected if I move the origin flash address to the default value in the linker script.
Here is a minimum reproducible example:
#include "main.h"
CAN_HandleTypeDef hcan1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN1_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_CAN1_Init();
/* USER CODE BEGIN 2 */
// Setup can
const uint32_t filter_mask = 0x00000000;
const uint32_t filter_id = 0x00000000;
CAN_FilterTypeDef canfilterconfig = (CAN_FilterTypeDef) {
.FilterBank = 0,
.FilterActivation = CAN_FILTER_ENABLE,
.FilterFIFOAssignment = CAN_FILTER_FIFO0,
.FilterMaskIdHigh = (filter_mask >> 13) & 0xFFFF,
.FilterMaskIdLow = (filter_mask << 3) & 0xFFF8,
.FilterIdHigh = (filter_id >> 13) & 0xFFFF,
.FilterIdLow = (filter_id << 3) & 0xFFF8,
.FilterMode = CAN_FILTERMODE_IDMASK,
.FilterScale = CAN_FILTERSCALE_32BIT,
.SlaveStartFilterBank = 27,
};
HAL_CAN_ConfigFilter(&hcan1, &canfilterconfig);
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
/* USER CODE END 2 */
while (1)
{
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 180;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
if (HAL_PWREx_EnableOverDrive() != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
static void MX_CAN1_Init(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 15;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_5TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_6TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = DISABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */
Here is the linker part I changed:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
FLASH (rx) : ORIGIN = 0x8008000, LENGTH = 480K
}
Attached you can find the whole project
Solved! Go to Solution.
2024-03-01 07:20 AM
Hello,
Did you set the vector table to this new flash address:
SCB->VTOR = 0x8008000;
in system_stm32f4xx.c ?
2024-03-01 07:20 AM
Hello,
Did you set the vector table to this new flash address:
SCB->VTOR = 0x8008000;
in system_stm32f4xx.c ?
2024-03-02 08:29 PM
Yeah, even the answers here guide you to the issue - it is not the solution.
Remember this:
Yes, you can move the Vector Table to a different address, e.g. 0x08008000. But a "chicken and egg" problem:
Your MCU starts always at 0x08000000, and just now you can move the Vector Table (via a Reset_Handler entry address found at 0x0800004 and doing all this stuff).
You have to have code at 0x08000000! At least a little bit of code "binding" now to your new address location for all other stuff at 0x08008000, e.g. with a new vector table (relocate the Vector Table base address via code, but done in the "master/main" Reset_Handler, referenced via its entry address at 0x08000004 (and SP value in 0x08000000).
Without any "correct" code on 0x08000000 and 0x08000004 - it cannot work. These locations must be programmed with "code" which forwards now to your code at 0x08008000.