Баги микроконтроллеров STM32

Обсуждение вопросов применения микроконтроллеров и ПЛИС

Куратор темы: pwn

Баги микроконтроллеров STM32

Сообщение pwn » 04 фев 2014, 13:43

В этой теме предлагаю отчитываться о найденных граблях в сабже. Оффтоп буду нещадно удалять!

Проц STM32F051R8T6 пытаемся при помощи таймера TIM15 сформировать управление для пушпула частота 50кгц D=0.5 дедтайм 500нс. Используем фирменные либы, инициализируем таким кодом:

Код: Выделить всё
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
//
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_1);
//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, ENABLE);
//
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 959;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM15, &TIM_TimeBaseStructure);
//
TIM_OCInitStructure.TIM_OCMode       = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState  = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_OCIdleState  = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
//
TIM_OCInitStructure.TIM_Pulse        = 480;
TIM_OCInitStructure.TIM_OCPolarity   = TIM_OCPolarity_High;
TIM_OC1Init(TIM15, &TIM_OCInitStructure);
//
TIM_OCInitStructure.TIM_Pulse        = 504;
TIM_OCInitStructure.TIM_OCPolarity   = TIM_OCPolarity_Low;
TIM_OC2Init(TIM15, &TIM_OCInitStructure);
//
TIM_BDTRInitStructure.TIM_OSSRState  = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState  = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel  = TIM_LOCKLevel_1;
TIM_BDTRInitStructure.TIM_DeadTime   = 24;
TIM_BDTRInitStructure.TIM_Break      = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity   = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM15, &TIM_BDTRInitStructure);
//
TIM_Cmd(TIM15, ENABLE);
//
TIM_CtrlPWMOutputs(TIM15, ENABLE);


компилим в IAR-е, заливаем через ST-Link, становимся отладчиком. Смотрим скопом - сигналы на PB14 и PB15 неправильные, полярность первого канала инвертирована и дедтайма нет, т.е. равносильно открытию сразу обеих каналов пушпула с соответствующим :bach: Слезаем с отладчика - результат тот же. Жмем ресет - результат тот же. Вырубаем питание и включаем снова и... о чудо! Все так как и должно быть, полярность сигналов на месте, дедтаймы как и задумано 500 нс. Снова прошиваем через ST-Link тот же код и становимся на отладку - опять те же грабли, один в один. Мораль? TIM15 в данном проце глючный, для формирования PWM сигналов его использовать нельзя. Иначе любая попытка на ходу отладить девайс будет приводить к :bach: если логикой драйвера не учтен такой момент и она не запрещает одномоментного включения каналов. Хотя радости с того все равно мало, транс пуша быстро съедет в насыщение из за перекоса, с последующим опять же визитом :bach:
Аватара пользователя
pwn
 
Сообщения: 3375
Зарегистрирован: 26 янв 2011, 03:04

Re: Баги микроконтроллеров STM32

Сообщение pwn » 04 фев 2014, 14:57

Попробовал тот же режим только с таймером TIM1 - ситуация ровно та же. Если производились манипуляции с процом через ST-Link, то полярность сигнала на CH1 все равно остается в Low, хотя и в коде прописано как High и из этого состояния проц не получается вывести в том числе подачей сигнала сброс. Только питанием и никак иначе :(
Аватара пользователя
pwn
 
Сообщения: 3375
Зарегистрирован: 26 янв 2011, 03:04

Re: Баги микроконтроллеров STM32

Сообщение pwn » 04 фев 2014, 17:07

Разобрался, глюк к счастью оказался не самого проца :) Скорее криворукость того кто писал либы и моя надежда на его адекватность. Я не использую комплементарный выход канала (он мне тут ни к чему), соответственно в инициализационной структуре не указываю для него полярность. Да и нафига, какая разница? Оказалось разница есть и она весьма существенна. В коде для корректной работы нужно было так

Код: Выделить всё
TIM_OCInitStructure.TIM_Pulse        = 480;
TIM_OCInitStructure.TIM_OCPolarity   = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity  = TIM_OCNPolarity_Low;      // !!!! Иначе корректно работать будет от случая к случаю !!!
TIM_OC1Init(TIM1, &TIM_OCInitStructure);


без этого в TIM_OCInitStructure.TIM_OCNPolarity оказывается мусор, который в либе stm32f0xx_tim.c на строке номер 775 код
Код: Выделить всё
/* Set the Output N Polarity */
    tmpccer |= TIM_OCInitStruct->TIM_OCNPolarity;

С щедрой подачи ST-ного говнокодера перебивает настройки всех каналов, включая и первого. Ему видимо в голову не пришло сделать примерно так
Код: Выделить всё
/* Set the Output N Polarity */
    tmpccer |= TIM_OCInitStruct->TIM_OCNPolarity & TIM_OCNPolarity_Low;

И мусор от структуры никогда бы в регистр не попал бы. Далее все зависит от воли случая. При включении питания в памяти все по нулям и мусор в структуре содержит нули, что на работе не сказывается никак и все работает корректно. Но при работе под отладчиком это уже не так, и даже аппаратный сброс ОЗУ не зачищает. И возможны уже разные варианты. Типа как в моем случае, возник эффект как если бы отладчик что-то менял в состоянии процессора, что приводило бы к однозначно некорректной работе таймера. За сим все, эпизод исчерпан. Не наступайте на грабли :)
Аватара пользователя
pwn
 
Сообщения: 3375
Зарегистрирован: 26 янв 2011, 03:04

Re: Баги микроконтроллеров STM32

Сообщение pwn » 15 мар 2015, 23:15

Это не баг, а скорее фича документации. Приспичило использовать компараторы, а примера по ним нет. Любую периферию нужно тактировать, иначе она работать не будет. Читаем что по этому сказано в RM0091
14.3.2 Clock
The COMP clock provided by the clock controller is synchronous with the PCLK (APB
clock).
There is no clock enable control bit provided in the RCC controller.
Note: Important: The polarity selection logic and the output redirection to the port works
independently from the PCLK clock. This allows the comparator to work even in Stop mode.

В переводе на русский означает, что компараторы тактируются от тактовой периферии и отдельного бита контроля сего безобразия не предусмотрено. Хорошо думаю, раз не предусмотрено значит ничего включать не нужно. Однако, любые попытки записать что либо в регистр COMP_CSR ничего не дали кроме нулей в нем. То есть, тактирование все же нужно включать, а где - ничего на сей счет не сказано. Методом тыка было выяснено, что все таки нужно включить тактирование SYSCFG иначе ничего работать не будет. Ниже пример рабочего кода, использующие стандартные драйвера для рулежки периферией от ST

Код: Выделить всё
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
COMP_InitStructure.COMP_InvertingInput = COMP_InvertingInput_VREFINT;
COMP_InitStructure.COMP_Output         = COMP_Output_None;
COMP_InitStructure.COMP_OutputPol      = COMP_OutputPol_NonInverted;
COMP_InitStructure.COMP_Hysteresis     = COMP_Hysteresis_Medium;
COMP_InitStructure.COMP_Mode           = COMP_Mode_MediumSpeed;
COMP_Init(COMP_Selection_COMP1, &COMP_InitStructure);
COMP_Cmd(COMP_Selection_COMP1, ENABLE);
Аватара пользователя
pwn
 
Сообщения: 3375
Зарегистрирован: 26 янв 2011, 03:04

Re: Баги микроконтроллеров STM32

Сообщение pwn » 16 мар 2015, 02:34

Продолжаем борьбу с компараторами и налетаем на очередные грабли. Прерывание от компараторов у F0 кортекса идет через EXTI, согласно документации для них предусмотрены 21 и 22 линии EXTI, для которых официально можно либо замаскировать прерывания либо разрешить (то есть биты для 21 и 22 линий предусмотрены только EXTI_IMR регистре. В регистрах детектирования по фронту либо по спаду EXTI_RTSR EXTI_FTSR а также в регистре признаков прерывания от линий согласно документации битов под эти линии нет. ОК. Настраиваю и.... получаю глухой зависон камня в обработчике прерываний от АЦП/Компараторов. Странное дело, явно не сброшен признак прерывания и по выходу из прерывания управление опять попадает в обработчик, как итог проц живет в нем и полезную нагрузку ему выполнять просто некогда. Надо как-то сбросить pending бит, но хде же его взять, если официально он не предусмотрен? Что ж лезем отладчиком и видим такую картину:
1.jpg

Странное дело! У нас pending бит не предусмотрен, IAR честно утверждает что далее 19 бита все никого волновать не должно, но биты то стоят! И прерывание по ним происходят. Ладно, дописываем чуток кода и сбрасываем их
2.jpg

клац
3.jpg

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

...но они стоят. Мораль? Не всему что пишут в документации следует верить. И тот кто писал RM0091 достоин хорошего удара по печени. Чтобы впредь не шутил так.
Аватара пользователя
pwn
 
Сообщения: 3375
Зарегистрирован: 26 янв 2011, 03:04


Вернуться в Микроконтроллеры и ПЛИС

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2