Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: FreeRTOS + localtime() == Hard Fault
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
lawless
Здравствуйте.

Все произошло во время того, когда я пытался поднять сервер mongoose на плате stm32-e407 с контроллером stm32f407zgt6. До этого хардфолты возникали довольно часто, но как-то удавалось от них уходить не разбираясь до конца, в чем же все-таки дело, но видимо время пришло:
Делаю проект с помощью CubeMX на eclipse (генерирую для truestudio), в проекте включен FreeRTOS версии 8.2.1 с heap.4, включены кварцы, программа падает в функции localtime в StartDefaultTask, НО, если расскоментировать такие же три строчки перед osKernelStart, то и в таске оно не упадет. Хотелось бы разобраться в чем проблема или хотя бы куда копать, ниже код и содержимое регистров после ХФ:
CODE
#include "stm32f4xx_hal.h"
#include "cmsis_os.h"

/* USER CODE BEGIN Includes */
/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/
osThreadId defaultTaskHandle;

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
void StartDefaultTask(void const * argument);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
extern void initialise_monitor_handles(void);

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */
/* USER CODE END 0 */

int main(void)
{

/* USER CODE BEGIN 1 */
#ifdef DEBUG
initialise_monitor_handles();
printf("initializing\n");
#endif
/* USER CODE END 1 */

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

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

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

/* Initialize all configured peripherals */
MX_GPIO_Init();

/* USER CODE BEGIN 2 */
/* USER CODE END 2 */

/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */

/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */

/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */

/* Create the thread(s) */
/* definition and creation of defaultTask */
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 1024);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */

/* definition and creation of httpTask */
/* USER CODE END RTOS_THREADS */

/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */


/* Start scheduler */
// ЕСЛИ РАСКОММЕНТИРОВАТЬ 3 СТРОЧКИ НИЖЕ ВСЕ ОК
// long a = 10241024;
// time_t timet = a;
// struct tm* mytime = localtime(&timet);
osKernelStart();

/* We should never get here as control is now taken by the scheduler */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}
/* USER CODE END 3 */

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;

__HAL_RCC_PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 6;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

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;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0);
}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
PG11 ------> ETH_TX_EN
PG13 ------> ETH_TXD0
PG14 ------> ETH_TXD1
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();

/*Configure GPIO pins : PG11 PG13 PG14 */
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_13|GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/* StartDefaultTask function */
void StartDefaultTask(void const * argument)
{

/* USER CODE BEGIN 5 */
long a = 10241024;
time_t timet = a;
struct tm* mytime = localtime(&timet);
/* Infinite loop */
for(;;)
{
vTaskDelay(1000);
}
/* USER CODE END 5 */
}


Код
EXEC_RETURN (LR):
lr             0xfffffffd    -3
xPSR            0xffffffff
ReturnAddress   0x8008fc9
LR (R14)        0x8008fc9
R12             0x8008ec2
R3              0x0
R2              0x0
R1              0x0
R0              0x1
Return instruction:
   0x8008fc9:    movs    r0, r4
LR instruction:
   0x8008fc9:    movs    r0, r4

CFSR            0x00008200
HFSR            0x40000000
BFAR            0x2800cb48


Добавлю, попробовал обновить FreeRTOS до V9.0.0rc2, ничего не поменялось
lawless
Обнаружил, что падает на исполнении вот этой инструкции
Код
ldr.w r3, [r5, r3, lsl #2]
в фнкции localtime_r. В случае, если код вставлен до инициализации ядра, то до исполнения этой инструкции дело не доходит
Сергей Борщ
QUOTE (lawless @ Jul 8 2016, 10:02) *
Обнаружил, что падает на исполнении вот этой инструкции
Как вы и сами понимаете, криминала в этой инструкции нет. Проблема в содержимом регистров R3 и/или R5. А его телепатически тут никто определить не может. Если хотите получить хоть сколько-то полезный ответ, выложите архив со всем проектом или хотя бы листинг проблемной функции целиком (только используйте теги codebox для больших исходников).
lawless
В том то и дело, что проект пустой.
Вот функция в которой падает
Непомнящий Евгений
Так а вы не пробовали под отладчиком посмотреть, что там в этих регистрах?
jcxz
Цитата(Сергей Борщ @ Jul 8 2016, 13:33) *
Как вы и сами понимаете, криминала в этой инструкции нет. Проблема в содержимом регистров R3 и/или R5. А его телепатически тут никто определить не может. Если хотите получить хоть сколько-то полезный ответ, выложите архив со всем проектом или хотя бы листинг проблемной функции целиком (только используйте теги codebox для больших исходников).

Достаточно поставить бряк на этой инструкции (или чуть раньше) и посмотреть содержимое регистров. Далее - ознакомиться с картой памяти МК. И думать "как же я дошёл до адресов таких?" smile3046.gif
lawless
Цитата(jcxz @ Jul 8 2016, 12:10) *
Достаточно поставить бряк на этой инструкции (или чуть раньше) и посмотреть содержимое регистров. Далее - ознакомиться с картой памяти МК. И думать "как же я дошёл до адресов таких?" smile3046.gif

Код
r5             0x8008c14
r3             0x8000fc9

Вроде все нормально, и то и другое ссылается на флеш, меня смущает две вещи:
1. Тут вроде как сказано, что в thumb нельзя использовать Rm (ldr.w r3, [r5, r3, lsl #2]), т.е. r3, который в скобках
2. Я не понял, что есть lsl, гдб говорит, что регистра такого нет.
Заранее говорю, что асм вижу в глаза вообще первый раз)
В целом смущает, что функция вроде стандартная и падать, казалось бы, не должна. Еще больше смущает, что без FreeRTOS она и не падает.
AHTOXA
localtime() возвращает указатель на глобальную структуру, что в многопоточной среде не очень хорошо.
Поэтому не используйте localtime(), а используйте localtime_r():
Код
        time_t t = rtc_ReadTime();
        struct tm stm;
        localtime_r(&t, &stm);


Во-вторых, я заметил, что в свежих версиях arm-embedded что-то начудили с функциями времени, и они теперь подтягивают вызовы gettzinfo(), которые, в свою очередь, вызывают malloc(). Поэтому проверьте, как у вас настроена куча.
Непомнящий Евгений
Кстати говоря, в мануале на cortex-m3 описано, как расшифровать регистры CFSR, HFSR, DFSR, AFSR, MMFAR и BFAR

Оттуда можно почерпнуть, что именно вызвало падение

А вот тут описано, как получить регистры, которые были в момент падения
jcxz
Цитата(lawless @ Jul 8 2016, 17:00) *
Код
r5             0x8008c14
r3             0x8000fc9

Вроде все нормально, и то и другое ссылается на флеш, меня смущает две вещи:

Вы уверены, что на флешь???
Посмотрите внимательнее на свою команду: ldr.w r3, [r5, r3, lsl #2]
исполнительный адрес вычисляется: R5 + R3 * 4 - возьмите калькулятор, подставьте свои значения и посчитайте.

Цитата(lawless @ Jul 8 2016, 17:00) *
1. Тут вроде как сказано, что в thumb нельзя использовать Rm (ldr.w r3, [r5, r3, lsl #2]), т.е. r3, который в скобках
2. Я не понял, что есть lsl, гдб говорит, что регистра такого нет.

Там вообще про другое ядро разговор. У Вас - Cortex-M.
Найдите на том же ресурсе мануал на Ваше ядро.
lawless
Цитата(AHTOXA @ Jul 8 2016, 14:01) *
localtime() возвращает указатель на глобальную структуру, что в многопоточной среде не очень хорошо.
Поэтому не используйте localtime(), а используйте localtime_r():
Код
        time_t t = rtc_ReadTime();
        struct tm stm;
        localtime_r(&t, &stm);


Во-вторых, я заметил, что в свежих версиях arm-embedded что-то начудили с функциями времени, и они теперь подтягивают вызовы gettzinfo(), которые, в свою очередь, вызывают malloc(). Поэтому проверьте, как у вас настроена куча.

Спасибо за подсказку, с localtime_r все сработало, помимо gettzinfo() сам localtime() вызывает malloc(), что, в принципе, понятно.

Цитата
Вы уверены, что на флешь???

Теперь не уверен, ссылается какраз таки куда-то на 0x2800cb38, где должен быть sram, но уже давно кончился, из-за этого, по-видимому и падает, тем более что в регистре BFAR какраз оно и содержится.
lawless
Я так понял, основная проблема была с тем, что malloc() возвращал 0x0 при вызове из поток и решилась заменой функции _sbrk(), вот тут нашел ответ. Спасибо всем кто принимал участие)
jcxz
Цитата(lawless @ Jul 8 2016, 20:50) *
Я так понял, основная проблема была с тем, что malloc() возвращал 0x0 при вызове из поток и решилась заменой функции _sbrk(), вот тут нашел ответ. Спасибо всем кто принимал участие)

А как тогда у Вас кривой адрес возникал?
lawless
Цитата(jcxz @ Jul 8 2016, 19:24) *
А как тогда у Вас кривой адрес возникал?

Хороший вопрос) Был бы рад, если бы мне кто-то на него ответил. Особенно учитывая, что программа теперь стала хардфолтится в функции svnprintf() и я подозреваю, что причина как-то связана с тем, что было в localtime()
jcxz
Цитата(lawless @ Jul 9 2016, 01:46) *
Хороший вопрос) Был бы рад, если бы мне кто-то на него ответил. Особенно учитывая, что программа теперь стала хардфолтится в функции svnprintf() и я подозреваю, что причина как-то связана с тем, что было в localtime()

Очевидно, что Вы не нашли причину фаулта. На Вашем месте я бы вернулся к исходном коду и выяснил откуда берётся неправильный адрес. Ответить можете только Вы сами, никто здесь за Вас отладить ваше устройство не сможет.
demiurg_spb
Цитата(AHTOXA @ Jul 8 2016, 14:01) *
Во-вторых, я заметил, что в свежих версиях arm-embedded что-то начудили с функциями времени, и они теперь подтягивают вызовы gettzinfo(), которые, в свою очередь, вызывают malloc().
Вышел очередной релиз (судя по описанию исправлены серьёзные косяки):
https://launchpad.net/gcc-arm-embedded/+download
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.