Программирование STM8
Re: Программирование STM8
Кода довольно много из разных файлов
Есть универсальный класс шаблон который хранит статичный указатель на функцию и имеет методы sethandler и callhandler
Этот же шаблон применен для двух таймеров где все работает
Для универсальности ссылка описана как void (*handler_ptr)(void) и в таймерах это описание соотвествует реальным функциям
А в ADC реальная функция имеет аргумент типа uint16_t
Чтобы тем не менее использовать универсальный класс я делаю одно явное преобразование типа указателя при присвоении адреса статичной переменной и одно когда вызываю функцию из хандлера
Не может быть именно в этом какого то сюрприза?
добавка
все таки действительно что то не так с временем
после того как поменял предделитель ADC с 4 на максимальное 18 зацикливание прекратилось
но это не снимает вопроса - почему так?
есть старая программа на Си на том же железе и с теми же настройками железа - там работает с предделителем при том что кода внутри вектора больше, но нет выхова функций
в обоих случаях CLK_CKDIVR = 0
в программе на си ADC_CR1_SPSEL = 2, в программе на С++ так не работает, работает с ADC_CR1_SPSEL = 7
что еще может быть причиной? не может же один вызов функции быть таким времязатрантным?
Есть универсальный класс шаблон который хранит статичный указатель на функцию и имеет методы sethandler и callhandler
Этот же шаблон применен для двух таймеров где все работает
Для универсальности ссылка описана как void (*handler_ptr)(void) и в таймерах это описание соотвествует реальным функциям
А в ADC реальная функция имеет аргумент типа uint16_t
Чтобы тем не менее использовать универсальный класс я делаю одно явное преобразование типа указателя при присвоении адреса статичной переменной и одно когда вызываю функцию из хандлера
Не может быть именно в этом какого то сюрприза?
добавка
все таки действительно что то не так с временем
после того как поменял предделитель ADC с 4 на максимальное 18 зацикливание прекратилось
но это не снимает вопроса - почему так?
есть старая программа на Си на том же железе и с теми же настройками железа - там работает с предделителем при том что кода внутри вектора больше, но нет выхова функций
в обоих случаях CLK_CKDIVR = 0
в программе на си ADC_CR1_SPSEL = 2, в программе на С++ так не работает, работает с ADC_CR1_SPSEL = 7
что еще может быть причиной? не может же один вызов функции быть таким времязатрантным?
- Реклама
Re: Программирование STM8
переписал проект на с++ получил +250 байт read write memory от линковщика
это RAM?
как понять на что ушло?
что еще странно - пишу новый проект, совершенно пустой проект на С++ - 524 байта read write memory
это вообще как?
это RAM?
как понять на что ушло?
что еще странно - пишу новый проект, совершенно пустой проект на С++ - 524 байта read write memory
это вообще как?
Re: Программирование STM8
а что за компилятор? sdcc, к примеру, кроме собственно результирующего бинарника выдает на гора еще ворох файлов, весьма во всех отношениях познавательных - ассемблерные листинги каждого компилируемого файла с комментариями из исходника; выхлоп диагностики линковщика, куда чего он какие символы положил, откуда их взял и сколько каждый занимает места; сводка использования областей памяти - вот такое, штук около десятка. В вашем такое поведение не присутствует или не включается флагами?
Re: Программирование STM8
я IAR использую, да, надо будет погружаться в схему распределения памяти у линковщика для С++
она явно отличается от Си
другой вопрос
происходит прерывание по GPIO и по усолчанию прерывания от таймеров не могут прозойти пока я не завершил прерывание по GPIO
можно как то внутри обработчика прерывания GPIO узнать, что тот или иной таймер переполнился? т.е. что должно будет следом произойти прерывание таймера
она явно отличается от Си
другой вопрос
происходит прерывание по GPIO и по усолчанию прерывания от таймеров не могут прозойти пока я не завершил прерывание по GPIO
можно как то внутри обработчика прерывания GPIO узнать, что тот или иной таймер переполнился? т.е. что должно будет следом произойти прерывание таймера
- Реклама
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Программирование STM8
Ну у таймеров же флаги есть.axillent писал(а):можно как то внутри обработчика прерывания GPIO узнать, что тот или иной таймер переполнился?
Приоритет можно сменить.axillent писал(а):и по усолчанию прерывания от таймеров не могут прозойти пока я не завершил прерывание по GPIO
Re: Программирование STM8
спасибо
приоритет не хотелось бы менять. вложенные прерывания могут создать еще проблем как мне кажется
а какой это флаг? TIF?
почему то для TIM4 он отмечен как "In TIM4 this bit is reserved."
приоритет не хотелось бы менять. вложенные прерывания могут создать еще проблем как мне кажется
а какой это флаг? TIF?
почему то для TIM4 он отмечен как "In TIM4 this bit is reserved."
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Программирование STM8
У меня вроде не было пролем со вложенностью прерываний. Контент на стек МК сам скидывает.
Добавлено after 3 minutes 47 seconds:
Коли STM8 мучаете. Если не в лом, можете проверить вот это http://radiokot.ru/forum/viewtopic.php? ... 1#p3090161 . А то я так время и не нашел (под этой фразой прячется слово лень).
Нет, UIF. Он называется не по переполнению, а по обновлению. Точку же обновления сам назначаешь. Ну можно считать что переполнение, если регистр TIMx_ARR=0xFF.axillent писал(а):а какой это флаг? TIF?
Добавлено after 3 minutes 47 seconds:
Коли STM8 мучаете. Если не в лом, можете проверить вот это http://radiokot.ru/forum/viewtopic.php? ... 1#p3090161 . А то я так время и не нашел (под этой фразой прячется слово лень).
Re: Программирование STM8
сейчас как раз отлаживаю устройство в котором активно конкурентно работают прерывания по двум таймерам и прерывания по одному пину
теоретически они должны друг на друна попадать, но как это сделать абсолютно точно - не знаю
у меня прерывания по пинам не теряются
теоретически они должны друг на друна попадать, но как это сделать абсолютно точно - не знаю
у меня прерывания по пинам не теряются
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Программирование STM8
Чтобы это проверить, я хотел запретить прерывания, дать один два импульса на порт, и разрешить прерывания когда уже внешних импульсов нет.
Собственно запрета прерывания глобального как такого нет в контроллере, есть повышение текущего уровня основной программы который прерывания не перебивают.
Собственно запрета прерывания глобального как такого нет в контроллере, есть повышение текущего уровня основной программы который прерывания не перебивают.
Re: Программирование STM8
вопрос
как избавиться от таких варнингов кроме как описывать промежуточную переменную?
видел решение использовать #pragma для скрытия варнингов, но мне нужен стандартный код, не только для IAR
как избавиться от таких варнингов кроме как описывать промежуточную переменную?
речь о коде где вместе используется более одной volatile переменной и где для меня порядок обращения к ним не важенWarning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement
видел решение использовать #pragma для скрытия варнингов, но мне нужен стандартный код, не только для IAR
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Программирование STM8
Разбейте одно математическое выражение на несколько, в каждом котором только одна переменная volatile. Тогда точно будет знать про порядок.
Re: Программирование STM8
в том то и дело что часто порядок не важен
и получается, что ради избавления от предупреждения надо создавать лишние переменные
и получается, что ради избавления от предупреждения надо создавать лишние переменные
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Программирование STM8
Не переживайте за лишние переменные, объявляйте их как локальные и в узкой области видимости, они долго жить не будут, может даже только в регистрах ядра (маловато конечно регистров в stm, зато система команд неплохая). Оптимизацию только не выключайте.
Добавлено after 8 minutes 24 seconds:
Например.
и
Скорее всего компиллятор сделает одинаковый код, все равно же куда то класть надо результат суммы для передачи его в функцию.
З.Ы. По моему скромному мнению конечно.
Добавлено after 8 minutes 24 seconds:
Например.
Код: Выделить всё
func (x+y);Код: Выделить всё
type buf=x;
buf+=y;
func(buf);З.Ы. По моему скромному мнению конечно.
Re: Программирование STM8
а если так?
где а и b volatile и такой код дает warning:
Код: Выделить всё
return a + *(int*)&b;
Код: Выделить всё
return a + b;;
Re: Программирование STM8
буду признателен за строчку кода для повышения приориетат прерывания по update TIM4
так, чтобы прерывание срабатывало внутри external interrupt
так, чтобы прерывание срабатывало внутри external interrupt
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Программирование STM8
Вот приоритеты прерываний

Обратите внимание что приоритеты левела 0 и левала 3 для основного цикла программы устанавливаются командами RIM и SIM. Т.е. установив левел3 для основного цикла, ни одно прерывание не сможет его перебить (таким хитрым образом запрещаются прерывания глобально).
Приоритеты же для соответствующего вектора прерывания настраиваются в регистре ITC_SPRx. По умолчанию уровень 0b11 или левел 3. Т.е. чтобы повысить уровень одного вектора, надо опустить другие включенные, что по-моему неудобно, а что делать...
-----
UPD: Зато можно часть прерываний отключать пачкой, изменяя биты I1 I0 в регистре CCR (типа регистр статуса), ну то есть пывысить уровень основного цикла до левел 1 например и только прерывания левела 2 и 3 будут актиывны, все с левелом 1 будут как бы отключены, только я так не пробовал.
Обратите внимание что приоритеты левела 0 и левала 3 для основного цикла программы устанавливаются командами RIM и SIM. Т.е. установив левел3 для основного цикла, ни одно прерывание не сможет его перебить (таким хитрым образом запрещаются прерывания глобально).
Приоритеты же для соответствующего вектора прерывания настраиваются в регистре ITC_SPRx. По умолчанию уровень 0b11 или левел 3. Т.е. чтобы повысить уровень одного вектора, надо опустить другие включенные, что по-моему неудобно, а что делать...
-----
UPD: Зато можно часть прерываний отключать пачкой, изменяя биты I1 I0 в регистре CCR (типа регистр статуса), ну то есть пывысить уровень основного цикла до левел 1 например и только прерывания левела 2 и 3 будут актиывны, все с левелом 1 будут как бы отключены, только я так не пробовал.
- Вложения
-
- стм8 приор.png
- (11.94 КБ) 1368 скачиваний
Re: Программирование STM8
я правильно понял, что чтобы из EXTIx срабатывал TIMx_OVR_UIF надо у EXTIx приоритет понизить до 2-го?
а это какие биты в каком конкретно регистре? по RM0016 я не понял как векторы связаны с этими регистрами, там почему то нотация другая, иными словами не вижу там EXTIx
а это какие биты в каком конкретно регистре? по RM0016 я не понял как векторы связаны с этими регистрами, там почему то нотация другая, иными словами не вижу там EXTIx
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Программирование STM8
Ну или до первого понизить.axillent писал(а):что чтобы из EXTIx срабатывал TIMx_OVR_UIF надо у EXTIx приоритет понизить до 2-го?
Смотрите на каком векторе сидит EXTIx и находите его в регистре ITC_SPRx и в каких битах этого регистра.axillent писал(а):а это какие биты в каком конкретно регистре? по RM0016 я не понял как векторы связаны с этими регистрами,
Добавлено after 2 minutes 22 seconds:
А таблицу векторов в ДШ смотрите.
Re: Программирование STM8
[uquote="axillent",url="/forum/viewtopic.php?p=3191511#p3191511"]а это какие биты в каком конкретно регистре? по RM0016 я не понял как векторы связаны с этими регистрами, там почему то нотация другая, иными словами не вижу там EXTIx[/uquote]
Для примера... настраиваю TIM2 с пониженным приоритетом следующим образом:
В RM0016 на стр.68 есть табличка с 8-мю регистрами ITC_SPR1 - ITC_SPR8, в которых каждые парные 2 бита отвечают за приоритет соответствующего прерывания.
Но в этой таблице (на стр.68), первые два железных прерывания пропущены (RESET и TRAmP или как там его...)))), поэтому VECT0SPR[1:0] это биты не 0-го прерывания а 2-го... соответственно VECT1SPR[1:0] это биты 3-го и т.д.
Так что от фактического номера железного прерывания нужно отнимать 2 чтобы получить номер в таблице на стр.68

Номера железных прерываний можно подсмотреть в IAR-е в конце файла iostm8s103f3.
Например, нужный мне вектор TIM2_OVR_UIF_vector находится под номером 0x0F, отнимаем от 15-ти двоечку и получаем номер 13 в таблице на стр.68 т.е. VECT13SPR[1:0] а это конкретно регистр ITC_SPR4 и биты [3:2], отсюда и команда ITC_SPR4 &= ~(0x0C);

на стр.67 есть табличка уровней (состояния 2-х битов), от низкого к высокому, по ней и выставляй соответствующую пару...

Возможно это решается как то по другому и покрасивее, но мне когда это было нужно, я ничего другого не сообразил, как только таким способом ... так что другого пока не могу предложить)
Для примера... настраиваю TIM2 с пониженным приоритетом следующим образом:
Код: Выделить всё
//настройка таймера TIM2 для организации регулярных прерываний 400Гц
TIM2_PSCR = 7; //предделитель таймера 0-7 (7 = 128)
TIM2_ARRH = (uint8_t)(154>>8); //считаем до 150, (для генерации частоты 400Гц при 8МГц)
TIM2_ARRL = (uint8_t)(154);
TIM2_IER_bit.UIE = 1; //прерывание по обновлению включено
TIM2_CR1_bit.CEN = 1; //разрешение работы таймера
ITC_SPR4 &= ~(0x0C); //понизить c 3 до 2 программный приоритет у TIM2 update/overflow
В RM0016 на стр.68 есть табличка с 8-мю регистрами ITC_SPR1 - ITC_SPR8, в которых каждые парные 2 бита отвечают за приоритет соответствующего прерывания.
Но в этой таблице (на стр.68), первые два железных прерывания пропущены (RESET и TRAmP или как там его...)))), поэтому VECT0SPR[1:0] это биты не 0-го прерывания а 2-го... соответственно VECT1SPR[1:0] это биты 3-го и т.д.
Так что от фактического номера железного прерывания нужно отнимать 2 чтобы получить номер в таблице на стр.68
Номера железных прерываний можно подсмотреть в IAR-е в конце файла iostm8s103f3.
Например, нужный мне вектор TIM2_OVR_UIF_vector находится под номером 0x0F, отнимаем от 15-ти двоечку и получаем номер 13 в таблице на стр.68 т.е. VECT13SPR[1:0] а это конкретно регистр ITC_SPR4 и биты [3:2], отсюда и команда ITC_SPR4 &= ~(0x0C);
на стр.67 есть табличка уровней (состояния 2-х битов), от низкого к высокому, по ней и выставляй соответствующую пару...
Возможно это решается как то по другому и покрасивее, но мне когда это было нужно, я ничего другого не сообразил, как только таким способом ... так что другого пока не могу предложить)



