Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 13:34:14

Доброго времени суток!

Может быть кто знает, в чем может быть затыка.

Камешек STM32F103C8T6. Собираю проект с нуля в Keil5. Структуры проекта собрана. Подключены файлы CMSIS библиотеки. Добавлен Startup для данной модели.
Пути к инклудам прописаны. Настройки компилятора, линкера в "Options for Target..." и прочего- аналогичны тем, что в проектах, созданных Кубом. Оптимизация отключена.
Тактирование, проты ввода-вывода, прерывания-все как положено...
Все собирается без ошибок и заливается в МК. Код, написанный в Main-е работает (светодиодом управляю, кнопки читаю и т.п.). Во только не работают обработчики прерываний! Пробовал писать их и в main.c, и в отдельном файле.

Если запускаю кубовский проект в отладку, точка выполнения встает в начало функции Main(), что логично.
А вот в новом- точка выполнения застревает где-то в ассемблеровском startup-е, на строке "LDR R0, =SystemInit".
Затем наблюдаются необъяснимые чудеса. Если в запущенном режиме Debug запустить выполнение кода (F5)- обработчики начинают жить (я для простоты сделал моргание светодиодом на борту платы по прерыванию таймера1).
Отключаю режим отладки, жму Reset- все затыкается и не работает.
Платы пробовал разные- bluepill, STM323 Smart.

Причем есть пара проектов собранных ранее с нуля- там прерывания чудесным образом работают (хотя раньше не работали и не понятно, по какому тычку они завелись).
Все библиотеки в них- одни и те же, стартап тот же. :dont_know:

Очень хотелось бы найти эту загадочную настройку, из за которой то работает то нет, ведь с Кубовскими проектами таких чудес не возникает.

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 13:40:56

Вопросов к вам собственно два:
1. Что является ИСТОЧНИКОМ прерываний?
2. Вы ничего не сказали о РАЗРЕШЕНИЯХ конкретных векторов в NVIC.
Приведите код который формирует условия генерации прерываний и собственно сами обработчики. Весь код приводить не надо.

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 13:56:49

Источник прерываний: таймер1 (прерывание TIM1_UP_IRQn):
Код:
void TimerConfig (void)
{
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;         // Тактиррование таймера от APB2
TIM1->SMCR &=~TIM_SMCR_SMS;               // Внутреннее тактирование таймера 1
TIM1->CR1=TIM_CR1_CEN;                  // Режим работы таймера
TIM1->PSC=500;                        // Прескалер. Частота импульсов 0,1мс  (10 кГц)
TIM1->ARR=9999;                        // Регистр перезагрузки. Будет раз в секунду.      
TIM1->DIER |= TIM_DIER_UIE;               // Разрешили прерывания по перезагрузке
}   


Разрешение в main():
Код:
NVIC_EnableIRQ(TIM1_UP_IRQn);            // Разрешили прерывания в контроллере


Обработчик в Interrupt_handler.c:
Код:
void TIM1_UP_IRQHandler      ()
{
   TIM1->SR &= ~TIM_SR_UIF;   // Сняли флаг сработки
   
   if ((GPIOC->IDR & GPIO_IDR_IDR13)==0)   // Моргаем светодиодом
   GPIOC->ODR |=1<<13;   
   else
   GPIOC->ODR &=~(1<<13);   
}

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 14:04:26

Причем есть пара проектов собранных ранее с нуля- там прерывания чудесным образом работают (хотя раньше не работали и не понятно, по какому тычку они завелись).
Все библиотеки в них- одни и те же, стартап тот же. :dont_know:

Берешь и сравниваешь текстовые файлы с конфигами из рабочего и нерабочего проекта, сам так пару раз делал...

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 14:08:09

Неплохо привести код мэйна связанный с вызовом инициализации таймера.
Ну и в инициализации куртуазно запускать таймер ПОСЛЕ того, как он инициализирован.
Это я к тому, что
TIM1->CR1=TIM_CR1_CEN; // Режим работы таймера
никакой не режим, а тупо его запуск.
ЗЫ. Ну и отладчик на этот случай есть. Останавливаете его и смотрите что с таймером и флагами.

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 14:16:54

Собственно Main.c:
Спойлер
Код:
#include "main.h"

void GPIO_Config(void);   
void SystemClockConfig (void);
void TimerConfig (void);

int main(void)
{
   SystemClockConfig();
   GPIO_Config();
   TimerConfig();
   while(1)
   {   }
}   

void GPIO_Config()
{
   RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;      // включили тактирование портов A-D
   RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;      
   RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
   RCC->APB2ENR |= RCC_APB2ENR_IOPDEN;   
   
   GPIOC->CRH &= ~(GPIO_CRH_CNF13 | GPIO_CRH_MODE13);       // CNF 0b00 MODE 0b10
   GPIOC->CRH |= (0b10 << GPIO_CRH_MODE13_Pos);                // PC13- активный выход
}


void SystemClockConfig (void)
{
RCC->CR |= (1<<RCC_CR_HSEON_Pos);                           // Запуск внешнего генератора
while (!(RCC->CR & (1<<RCC_CR_HSERDY_Pos))){}         // Ждем запуска генератора...

RCC->CFGR |= (0x07<<RCC_CFGR_PLLMULL_Pos)|(0x01<<RCC_CFGR_PLLSRC_Pos); // Тактирование PLL от HSE, множитель =9

RCC->CR |= (1<<RCC_CR_PLLON_Pos);                           // Запуск PLL
while (!(RCC->CR & (1<<RCC_CR_PLLRDY_Pos))){}         // Ждем запуска PLL...

FLASH->ACR |= (0x02<<FLASH_ACR_LATENCY_Pos);         // 2 цкла ожидания для FLASH

//Делители:
RCC->CFGR |= (0x00<<RCC_CFGR_PPRE2_Pos)|(0x04<<RCC_CFGR_PPRE1_Pos)|(0x00<<RCC_CFGR_HPRE_Pos);

RCC->CFGR |= (0x02<<RCC_CFGR_SW_Pos);                     // Переключаемся на работу от PLL
// Ждем окончания переключения:
while ((RCC->CFGR & RCC_CFGR_SWS_Msk)!=(0x02<<RCC_CFGR_SWS_Pos)){}
RCC->CR &= ~(1<<RCC_CR_HSION_Pos);                        // Отключаем HSI
}

void TimerConfig (void)
{
   RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;         // Тактиррование таймера от APB2
   TIM1->SMCR &=~TIM_SMCR_SMS;               // Внутреннее тактирование таймера 1

   TIM1->PSC=500;                        // Прескалер. Частота импульсов 0,1мс  (10 кГц)
   TIM1->ARR=9999;                        // Регистр перезагрузки. Будет раз в секунду.      
   TIM1->DIER |= TIM_DIER_UIE;               // Разрешили прерывания по перезагрузке
   NVIC_EnableIRQ(TIM1_UP_IRQn);            // Разрешили прерывания в контроллере
   TIM1->CR1=TIM_CR1_CEN;                  // Режим работы таймера
}   

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 14:25:59

А с отладчиком чего видно?

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 14:37:10

При переходе в отладчик:
Изображение

И вот если в отладке жамкнуть F5- прерывания работать будут (светодиод замигает).
Отключить отладчика и нажать Reset- не будут :dont_know:

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 15:52:41

Шозабред?
В брейкпойнт в прерывании заходит?
И почему main файл именован для плюсов? У вас проект на Си или на плюсах?

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 15:59:00

Кстати, да. На словах в проекте Main.c, а на картинке main.cpp, для плюсов нужно обработчикам прерываний extern "C" добавлять, за исключением случаев когда стартап тоже на плюсах.

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 16:04:19

Я имею ввиду что если запустить программу кнопкой Run, находясь в отладчике, то в прерывания заходить будет.
Этот проект с плюсами (экспериментировал), но пробовал и с простым Си, то же самое.
В плане Си или плюсов- я экспериментировал с Кубовскими проектами- менял main.c на main.cpp, stm32f1xx_it.c на stm32f1xx_it.cpp, и все работало как часы. Прямо из обработчика прерывания по таймеру вызывался метод класса без проблем.

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 17:52:28

если запустить программу кнопкой Run

А переставьте мигания в основной цикл. Есть смутные подозрения...

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 18:27:17

Вот ведь! Та же история!
Выключил прерывания, убрал обработчик и сделал такую до безобразия простую вещь:
Код:
int main(void)
{
   SystemClockConfig();
   GPIO_Config();
   int Delay_Counter=500000;
   while(1)
   {
      Delay_Counter-=1;
      if (Delay_Counter==0)
      {
            if ((GPIOC->IDR & GPIO_IDR_IDR13)==0)   // Моргаем светодиодом
               GPIOC->ODR |=1<<13;   
            else
               GPIOC->ODR &=~(1<<13);   
            Delay_Counter=500000;
      }
   }
}   

И запускается только в отладке в Run-е. Поделитесь подозрениями, в какую сторону копать :)

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 18:32:17

Ну наверное МК не стартует... :)
Схемку предъявите пожалуйста...

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 18:47:57

А МК есть другой?
Китайцы шлют нередко перемарк и отбраковку.
Бывали уже случаи с непонятными глюками которые пропадали со сменой самого МК.

Re: KEIL. Нулевой проект- на работают прерывания.

Вс окт 24, 2021 19:43:16

Тоже было подозрение, но пробовал на двух платах: самая обычная BluePill китайская за 200р и чуть подороже STM32 Smart. У обеих STM32F103С8T6 на борту. Схема.. так кроме питания 5В и собственно программатора ничего и не подключаю. У таблетки копеечный программатор-свисток, у Smart- ST-Link/V2. И там и там картина одна. И вопрос то остаётся- почему Кубовские проекты встают без всяких косяков, и работают без сбоев. Есть подозрения на сам Кейл, что он в памяти саму программу как-то криво размещает. Вот я и подумал, что может какую-то конфигу не делаю, адресацию где-нибудь не задаю и т.п. Но окно "Options for Target..." излажено вдоль и поперек, и каких-либо отличий не нашел :dont_know:

Re: KEIL. Нулевой проект- на работают прерывания.

Ср янв 12, 2022 09:26:28

Нашел странную закономерность- все вышеуказанные косяки проявляются при отключенной оптимизации (О0). Если включить любой уровень О1, О3 и т.п. - все работает и в отладке и непосредственно на МК. Проверил на разных компах и разных кристаллах :shock:
Глюк Кейла? :dont_know:

Re: KEIL. Нулевой проект- на работают прерывания.

Ср янв 12, 2022 18:07:36

Дайте периферии хоть пару тактов после включения, перед тем как заполнять ее регистры.
Например, вынестите включение всей периферии вперед, а регистры начните заполнять с той, какую включили первой.
... не внимательно посмотрел, кажется дело не в этом.


... где-то в ассемблеровском startup-е, на строке "LDR R0, =SystemInit"..."
это обращение в system_stm32f10x.c - делает примерно тоже ч то вы в СистемКлок

Re: KEIL. Нулевой проект- на работают прерывания.

Ср янв 12, 2022 20:44:07

Николай Relsart писал(а):А вот в новом- точка выполнения застревает где-то в ассемблеровском startup-е, на строке "LDR R0, =SystemInit".

Наверное, затык возникает позже, уже после входа в SystemInit. Поставьте точку останова внутри функции SystemInit и пройдите её по-шагам, чтобы понять, где именно в ней происходит затык (скорее всего это событие HardFault). Кстати, поставьте точку останова внутри HardFaultHandler, чтобы убедиться (или наоборот), что в момент зависания вашей программы МК заходит туда. А там можно и по регистру отказов посмотреть причину.

Re: KEIL. Нулевой проект- на работают прерывания.

Ср янв 12, 2022 21:25:08

у меня отладчик проваливается на СистемИнит в файл system_stm32f10x.c и ждет пинка на первой его процедуре.
А унего в стартапе останавливается. Startupповский файл у меня на _md_vl.s заканчивается
Ответить