Перейти к содержанию
    

Начинаю осваивать ARM STM32F4DISCOVERY

Все привет! Изучаю программирование ARM-контроллеров, в частности STM32.

Решил пойти следующим путем: STM32F4-DISCOVERY + ARM-NONE-EABI-GCC + собственный Makefile

Выбор пал на GNU дабы использовать не коммерческие САПРы

Собственный Makefile позволяет контроллировать этапы сборки.

Собрал простой проект: инициализация системы (HAL_init и тактирование), ну и помыргать светодиодами.

Проект собирается без ошибок, загорается светодиод, но такое впечатление, что когда доходит до цикла моргания светодиодами - виснет.

И я заступорился - куда копать...

Привожу проект полностью

Подозрения падают на инициализацию тактирования, а также не неверный старт-ап или скрипт сборки...

Может, местные Гуру подскажут что-нить дельное?)

 

Так же отдельно приведу код main.c чтобы не качать полностью архив из-за одного файла:

 

#include "stm32f4xx.h"
#include "stm32f4xx_hal.h"

static void GPIO_init(void);
static void SystemClock_Config(void);
static void Error_Handler(void);

int main(void)
{   

////////////////////////////////////////////////////////////////////////////
//Libraries initialization - Инициализация библиотек
HAL_Init();
//GPIO initialization - Инициализация портов ввода/вывода
GPIO_init();
//Clock initialiaztion - Инициализация системы тактирования
SystemClock_Config();

long cnt = 0;


while(1)
{

if (cnt == 100) {cnt = 0;}
else {cnt = cnt + 1;}

if (cnt <= 50) HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
else HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);

/*
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
HAL_Delay(1000);
*/
}

}

static void GPIO_init(void)
{
 ///////////////////////////////////////////////////////////////////////////
 GPIO_InitTypeDef  GPIO_InitStruct; 
 /* Enable the GPIO_LED Clock */
 __GPIOD_CLK_ENABLE();
 /* Configure the GPIO_LED pin */
 GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15|GPIO_PIN_12;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_PULLUP;
 GPIO_InitStruct.Speed = GPIO_SPEED_FAST;

 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);										
 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
 //HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET);
 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
 //HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
}

static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;	 

__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

////////////////////////////////////////////////////////////////////////////
//Set External High-speed oscillator type - Установка типа генератора - у нас имеется внешний кварц 8МГц
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;

//SysClk = 8(HSE) / PLLM / RCC_PLLP_DIV2 * PLLN = 168 MHz
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

RCC_OscInitStruct.PLL.PLLQ = 7;

if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
 Error_Handler();
}

////////////////////////////////////////////////////////////////////////////
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | 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_DIV4;  
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
 Error_Handler();
 }

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

}

static void Error_Handler(void)
{
 /* Turn LED5 on */
 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
 while(1)
 {
 }
}

void _exit(int i)
{
while (1);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
}
 

MyTestARM5.rar

Изменено пользователем haker_fox
Уточнил название темы, добавил теги, переместил в нужный раздел.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Предлагаю

1) разобраться, какой же светодиод загорается

2) временно закомментировать инициализацию клоков (оно и так работать будет, только небыстро)

3) временно закомментировать инициализацию HAL'а (а лучше его вообще не использовать. Если там что-то не заработает, на раскопки уйдёт куда больше времени, чем на написание своего велосипеда с нужным для конкретной задачи диаметром колёс).

4) прикрутить отладчик (гуглить "openocd gdb stm32")

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Предлагаю

1) разобраться, какой же светодиод загорается

2) временно закомментировать инициализацию клоков (оно и так работать будет, только небыстро)

3) временно закомментировать инициализацию HAL'а (а лучше его вообще не использовать. Если там что-то не заработает, на раскопки уйдёт куда больше времени, чем на написание своего велосипеда с нужным для конкретной задачи диаметром колёс).

4) прикрутить отладчик (гуглить "openocd gdb stm32")

 

2) и 3)

Закомментировал сначала //SystemClock_Config(); - эффекта не дало...

Закомментировал следом //HAL_Init(); - нужный светодиод (PD15) начал мигать...

Вернул в код SystemClock_Config(); - снова все сломалось

Согласно логике можно сделать вывод, что инициализация библиотек и схемы тактирования в моем проекте производится неверно...

Придется либо разбираться в библиотеках HAL от STM, что геморрой, но и как Вы предложили - геморрой еще тот.

Я больше на данном этапе своего ARM-развития, вероятно, предпочту первый вариант...

 

4)

Насколько я знаю прикрутить openocd это тоже довольно сложно (работаю в виндовс), ну что ж буду копать дальше и информировать о сдвигах в положительную сторону. Спасибо!

 

 

Демошка, без HAL.

 

Судя по тому, что уровень моего знания STM довольно низок, писать код не используя HAL довольно сложно - потребуется много времени на штудирование документации

а использование HAL от производителя как раз и направлено на, так называемый, быстрый старт...

Я по основной специализации - FPGA-шник и сам сторонник, чтобы писать код самостоятельно с нуля, не используя схематик и ip-блоки, чтобы знать досконально что творится в камне, поэтому целиком и полностью понимаю Вас...

 

Изменено пользователем dde29

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4) Насколько я знаю, прикрутить openocd - это тоже довольно сложно (работаю в виндовс)
Вы знаете неправильно. Вот тут есть готовые сборки. Эта ссылка есть на официальном сайте openocd в разделе "где взять openocd".

 

а использование HAL от производителя как раз и направлено на, так называемый, быстрый старт...
А его изучать не нужно будет? Ну вот HAL_init() у вас уже быстро стартанул :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

чтобы писать код самостоятельно с нуля, не используя схематик и ip-блоки, чтобы знать досконально что творится в камне, поэтому целиком и полностью понимаю Вас...

 

Ну мой случай не тот...

Приходится писать под разные "камни" - а HAL для всех не напишут. Потому получилась своя "библиотека всего" - набор функций и настроенных сред компиляции для разных целевых устройств.

Написать всё смому не получится, но язык С позволяет относительно легко использовать чужие наработки (если, разумеется, нет завязки на какой-то другой framework).

 

С FPGA altera как раз предпочёл схематик - с простыми элементами понятно, их без разницы - сгенерил автомат или сам написал А + Б.

А используя тяжелые блоки вроде CIC и FIR уже привязали накрепко... В случае FPGA, мне кажется, использование средств колирования уровня повыше (схематик) не столь катастрофически гробит производительность процессора, как в случае программ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А его изучать не нужно будет? Ну вот HAL_init() у вас уже быстро стартанул :)

 

Этот "быстрый" HAL_init() стартанул так, что ничего не работает)))) так что в нем еще поразбираться надо...

 

 

С FPGA altera как раз предпочёл схематик - с простыми элементами понятно, их без разницы - сгенерил автомат или сам написал А + Б.

А используя тяжелые блоки вроде CIC и FIR уже привязали накрепко... В случае FPGA, мне кажется, использование средств колирования уровня повыше (схематик) не столь катастрофически гробит производительность процессора, как в случае программ.

 

По специфике моей профессии - нету готовых блоков IP для Альтеры, поэтому привык писать с нуля конфигурации - в этом случае и SignalTap-ом пользоваться удобнее - заранее знаешь к чем прицепиться - но это уже оффтоп)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Этот "быстрый" HAL_init() стартанул так, что ничего не работает)))) так что в нем еще поразбираться надо...
Так и я о том же - или прочитать про 5 регистров инциализации порта и написать инициализацию каждого порта записью в 5 регистров, или разбираться в структурах HAL и писать по пол-экрана записи в структуры для инциализации каждой ноги. "Думайте сами, решайте сами...."

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А пройти по шагам отладчиком и посмотреть все 10-20 действий которые делает HAL/SPL или еще что-то используемое ?

Пофиг что использовать для моргания лампочкой.

Возьмите CubeMX, Keil/DS-5/AS6/Atollic/... и минут за 5 будет понятно.

Потом можете точить память на регистрах или что там понравится.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вобщем, я понял почему при использовании инициализации HAL_Init() программа полностью висла (не так уж и плохо использовать HAL:) ).

Пройдя вглубь функции HAL_Init(), через несколько вызовов в файле stm32f4xx_hal_cortex.c натыкаемся на функцию SysTick_Config(uint32_t ticks), в которой описана настройка регистров системного таймера:

 

if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   /* Reload value impossible */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  return (0UL);

 

Внимание обратил на флаг SysTick_CTRL_TICKINT_Msk, установка которого заставляет вызывать прерывание по сбросу системного таймера...

Стало понятно, что у меня нигде не описана обработка этого прерывания. Получается проц переходит по адресу прерывания и остается там...

 

Добавив в main.c функцию обработки прерывания по сбросу системного таймера, код стал работоспособен:

 

void SysTick_Handler(void)
{
  HAL_IncTick();
}

Изменено пользователем dde29

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

(не так уж и плохо использовать HAL:)

Да, шикарная штука этот HAL. Всего три дня, и вы уже моргаете светодиодом! :yeah:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, шикарная штука этот HAL. Всего три дня, и вы уже моргаете светодиодом! :yeah:

 

Для человека, который до этого из микроконтроллеров только АВР-ки программил - думаю неплохо)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И бонусом контроллер тратит время на совершенно ненужное вам прерывание, но выпилить это вы уже не можете.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И бонусом контроллер тратит время на совершенно ненужное вам прерывание, но выпилить это вы уже не можете.

 

Уверен, что когда будет писаться код под какой-то реальный проект, думаю ресурсы будут задействованы только те которые надо, а пока и так сойдет))))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для человека, который до этого из микроконтроллеров только АВР-ки программил - думаю неплохо)

Похвастаюсь, у меня первый "взлёт" на AT91SAM7S32 вместе с изготовлением J-TAG адаптера WIGGLER занял 12 часов!

До этого в умениях только 8086, x86 и ATMega. Ну да, 8080/z80, 6502 издали... куда без всего этого.

 

Ну серьёзно, не туда копаете.

Гляньте на мой исходник, там добавить пяток строк - и тоже появятся прерывания по systick без залезания в дебри CMSIS:

1) Расширить таблицу векторов прерываний (Добавить 14 элементов, нужен последний на смещении -1

2) добавить тело обработчика прерываний с нужным действием (4 строки)

3) Разрешить это прерывание

4) разрешить прерывания вообше.

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...