|
|
  |
STM32F10x, не перестаёт удивлять |
|
|
|
Feb 7 2011, 17:15
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(pr0m @ Feb 7 2011, 21:57)  Нет, одна группа - 0-я, и в ней 15 ПОДприоритетов, к-е друг друга не вытесняют. Всё же нет, 16 групп, в каждой по одному уровню приоритета. Цитата(pr0m @ Feb 7 2011, 21:57)  Кстати, не совсем понял один момент: после сброса поле групп = 000, если верить описанию регистра SCB_AIRCR: Такого сочетания этих конфигурационных бит нет. И какая схема приоритетов имеет место после ресета? 0b011. Ибо все значения, меньше либо равные этому (вплоть до нуля) дают одинаковый результат при имеющихся битах приоритета.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 7 2011, 17:17
|
Частый гость
 
Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233

|
Цитата(sonycman @ Feb 7 2011, 20:11)  Хм, я тогда приведу другую картинку: Ваша картинка красивее  у меня про сочетание b000 умалчивается. Черпал знания из "STM32F10xxx Cortex-M3 programming manual.pdf" с сайта ST.
--------------------
Правильно поставленный вопрос - половина ответа...
|
|
|
|
|
Feb 7 2011, 17:31
|
Частый гость
 
Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233

|
Цитата(AHTOXA @ Feb 7 2011, 20:15)  Всё же нет, 16 групп, в каждой по одному уровню приоритета.
0b011. Ибо все значения, меньше либо равные этому (вплоть до нуля) дают одинаковый результат при имеющихся битах приоритета. А моя практика подсказывает, что нифига. Почему? Пока не конфигурил группы, имел место, как я теперь уже понял, пропуск прерываний от таймера, т.к. он хоть и имел 0-й приоритет, но не мог когда нужно вытеснить программное прерывание, к-е копировало порядка 1200байт, один раз в 200 отсчётов (раз в 2мс). После явного конфигуривания групп всё стало на свои места. Каким документом по поводу работы NVIC руководствуетесь? Вот состояния NVIC на реальном железе STM32F107 сразу после сброса, и после конфигурирования приоритетов. К сожалению, у кейла нет для 107-го в периферии регистров NVIC.
--------------------
Правильно поставленный вопрос - половина ответа...
|
|
|
|
|
Feb 7 2011, 17:32
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(pr0m @ Feb 7 2011, 22:22)  А моя практика подсказывает, что нифига. Почему? Пока не конфигурил группы, имел место, как я теперь уже понял, пропуск прерываний от таймера Так если не конфигурили, то у всех прерываний был одинаковый приоритет, потому и не вытесняло. Цитата(pr0m @ Feb 7 2011, 22:22)  Каким документом по поводу работы NVIC руководствуетесь? Главный документ касательно ядра Cortex-M3 -- Cortex-M3 Technical Reference Manual.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 7 2011, 17:53
|
Частый гость
 
Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233

|
Разобрался. sonycman прав. 15 подгрупп после ресета. У меня в коде инициализации, т.к. делал не с нуля проект, а взял шаблон, было вот это: Код /* 0 bit for pre-emption priority, 4 bits for subpriority */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
В хидере: #define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */ #define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */ #define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */ #define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */ #define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */ Т.е. переключался на 0 групп. Сейчас вот так: Код /* 2 bit for pre-emption priority, 2 bits for subpriority */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); Цитата(AHTOXA @ Feb 7 2011, 20:32)  Так если не конфигурили, то у всех прерываний был одинаковый приоритет, потому и не вытесняло. Ненене (с)  ПОДприоритеты назначал разные. Группа была одна. Из шаблона проекта унаследовал - там переключался NVIC на 0 групп. Цитата(AHTOXA @ Feb 7 2011, 20:32)  Главный документ касательно ядра Cortex-M3 -- Cortex-M3 Technical Reference Manual. Угумс, первоисточник-с. И что ж это получается, господа - NVIC у STM32 - кастрированный???  В армовской спецификации у него вон скока бит для приоритетов!
--------------------
Правильно поставленный вопрос - половина ответа...
|
|
|
|
|
Feb 7 2011, 17:58
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(pr0m @ Feb 7 2011, 18:31)  А моя практика подсказывает, что нифига. Почему? Пока не конфигурил группы, имел место, как я теперь уже понял, пропуск прерываний от таймера, И моя практика такое же подсказала, когда я ту же шишку набил на заре использования Cortex. После этого любой мой проект начинается с вызова NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); в процессе инициализации системы. Тогда при инициализации тех или иных прерываний вытесняющий приоритет в диапазоне [0..15] можно задать в поле "NVIC_IRQChannelPreemptionPriority" записи "NVIC_InitTypeDef", то есть (пример для UART1): Код ... NVIC_InitTypeDef NVIC_InitStructure = { USART1_IRQn, USART_IT_Priority, // preemptive 0, // subpriority ENABLE }; ... NVIC_Init(&NVIC_InitStructure); Пока 16-ти вытесняющих приоритетов хватало. На 51-х процессорах и двух было достаточно
|
|
|
|
|
Feb 7 2011, 18:05
|
Частый гость
 
Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233

|
Цитата(KnightIgor @ Feb 7 2011, 20:58)  После этого любой мой проект начинается с вызова NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); На 51-х процессорах и двух было достаточно  Воистину, теперь и у меня эту будет самый главный после main(), вызов Да уж, на 8-,16-разрядных, с коими достаточно имел дело, понятие приоритета однозначно подразумевало вытеснение. Придётся ломать сознание.
--------------------
Правильно поставленный вопрос - половина ответа...
|
|
|
|
|
Feb 7 2011, 18:11
|
Частый гость
 
Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233

|
Цитата(sonycman @ Feb 7 2011, 21:05)  В этом нет необходимости, это является значением по умолчанию  .....если в моей программе будет использоваться более одного прерывания
--------------------
Правильно поставленный вопрос - половина ответа...
|
|
|
|
|
Feb 7 2011, 19:06
|
Участник

Группа: Участник
Сообщений: 72
Регистрация: 7-01-11
Пользователь №: 62 073

|
Цитата 1) Для детерминированности времени исполнения код должен исполняться из ОЗУ, что и сделал. Хотя исполняется медленнее, чем из флэш - что подтверждает высказывания по поводу отсутствия преимуществ исполнения кода из ОЗУ в сравнении с флэш для STM32F10... 2) Проверка флага UEV как признака окончания внутреннего цикла (while(!(TIMx->CR1 & UEV))увеличивает общее время исполнения блока на 2 такта, в сравнении c флагом в ОЗУ (bStopDSS), что в принципе понятно - чтение регистра+наложение маски бита UEV-сравнение, вместо чтение-сравнение). Поэтому bStopDSS. Странные выводы. Вызов прерывания + установка флага займет куда больше 2х тактов + вход в прерывание можеть занимать разное время. На счет кода в озу тоже есть большие сомнения. Имхо, вы рискуете нарваться на новые грабли. Приоритеты - это все хорошо, теперь таймер будет выключаться в прерывании стабильно (хотя он это и сам умеет делать, достаточно лишт включить OPM). Но в этом ли была проблема изначально? Ведь получается, что код не успевает обрабатывать данные на заданной скорости, во всяком случае при возникновении того самого прерывания, которое " быстро выполняет другие дела".
|
|
|
|
|
Feb 7 2011, 19:31
|
Частый гость
 
Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233

|
Цитата(akimych @ Feb 7 2011, 22:06)  Странные выводы. Вызов прерывания + установка флага займет куда больше 2х тактов + вход в прерывание можеть занимать разное время. На счет кода в озу тоже есть большие сомнения. Имхо, вы рискуете нарваться на новые грабли. Я видимо путано высказался. 2 варианта проверки окончания внутреннего цикла: 1) проверять флаг UEV. Прерывания от таймера в этом случае конечно отключены. Polling классический, та-скать. 2) проверять переменную в ОЗУ bStopDSS, к-я устанавливается в обработчике прерывания таймера. Так вот, практика показала, что мой внутренний цикл DDS, в который ессно входит проверка: Код while(один из 2-х вариантов окончания){зело критичный по времени код DDS} выполняется на 2 такта быстрее во 2-м случае. Время установки флага кем-то извне (в моём случае в обработчике таймера bStopDSS или сам битик UEV анализируем) значения не имеет. Какие именно сомнения по поводу кода в ОЗУ? Располагаю конкретными цифрами кол-ва тактов для 1)флэш-кода и 2)ОЗУ-кода. 2-й - медленнее, но абсолютно детерминированное кол-во тактов. 1-й быстрее, но с этим конвейером, IBUS-DBUS-ами может исполняться то 14 тактов, то 18, на одной прошивке ессно. После 8-,16-разрядников для меня это был шок. Недавно поднимал вопрос в какой-то ветке пониже. Цитата(akimych @ Feb 7 2011, 22:06)  Приоритеты - это все хорошо, теперь таймер будет выключаться в прерывании стабильно (хотя он это и сам умеет делать, достаточно лишт включить OPM). Но в этом ли была проблема изначально? Ведь получается, что код не успевает обрабатывать данные на заданной скорости, во всяком случае при возникновении того самого прерывания, которое "быстро выполняет другие дела". В этой ветке переплелись мои вопросы по двум разным проектам. В этом сообщении Вы их тоже переплели  Там где речь зашла о приоритетах - другая проблема. Была. Решена. Кстати, включил OPM. Понравилось - изящнее. То что нужно для 1-го проекта. Ещё кстати, "того самого прерывания, которое " быстро выполняет другие дела"" - эти дела заключаются в приёме конфигурации по I2C от внешнего контроллера, код DDS-цикла конечно останавливается (более того, я его явно останавливаю при начале обмена по I2C, установив флаг окончания цикла), чтобы затем войти в цикл вновь, обновившись из принятой конфигурации.
Сообщение отредактировал pr0m - Feb 7 2011, 19:57
--------------------
Правильно поставленный вопрос - половина ответа...
|
|
|
|
|
Feb 7 2011, 21:24
|
Участник

Группа: Участник
Сообщений: 72
Регистрация: 7-01-11
Пользователь №: 62 073

|
Цитата В этой ветке переплелись мои вопросы по двум разным проектам. Ах вот оно что, тогда понятно  На счет проверки бита. Вообще-то там не должно быть "чтение-наложение маски-сравнение", наложение маски + сравнение делается хитрее, команд столько же, надо смотреть, что генерит компилятор. Разница в том, что для TIM3->SR может генериться немного другая инструкция чтения, которая длиннее. Можно предварительно положить &TIM3-SR в регистр (присвоить указателю). Сомнения больше на счет детерминированного времени выполнения команд, если оно действительно нужно, то стоило ли выбирать стм32... А что там такого хитрого в цикле, если не секрет?
|
|
|
|
|
Feb 8 2011, 07:03
|
Частый гость
 
Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233

|
Цитата(akimych @ Feb 8 2011, 00:24)  На счет проверки бита. Вообще-то там не должно быть "чтение-наложение маски-сравнение", наложение маски + сравнение делается хитрее, команд столько же, надо смотреть, что генерит компилятор. Разница в том, что для TIM3->SR может генериться немного другая инструкция чтения, которая длиннее. Можно предварительно положить &TIM3-SR в регистр (присвоить указателю). Сомнения больше на счет детерминированного времени выполнения команд, если оно действительно нужно, то стоило ли выбирать стм32... А что там такого хитрого в цикле, если не секрет? Вы наверное имеете ввиду доступ к bit-banding региону, вместо чтения регистра целиком+маска нужного бита? За пару недель тяжело стать гуру в армах, и ассемблер ихний тяжеловат, ещё и компилятор просто так не позволяет __asm вставки делать для thumb-кода. Я в процессе  В цикле - подобие вот этого: DDS на AVR. Там должно стать понятным, почему этот код внутри должен исполняться за детерминированное кол-во тактов - им определяется частота дискретизации, и как следствие, частота самого генерируемого сигнала. Основное отличие моего проекта - вместа резистивного делителя для формирования аналогового сигнала используются бортовые ЦАП-ы, причём оба, и формируют прямой и инверсный формы сигнала, чтобы затем завести их на входы компаратора и получить целевые прямоугольные импульсы с малым джиттером (и у программной, и у аппаратной реализаций DDS на предельных частотах проблема явственная - сильно дрожат фронта, если формировать напрямую прямоугольник). По сути, программная замена DDS от Analog devices, AD9854 можно глянуть для примера. Выбран был скажем так, не STM32, а в целом АРМ - по критерию скорости, потому что в моём проекте максимальная генерируемая частота (синус) требуется выше, чем в ссылке (до 450...500кГц). Код DDS получился 20 тактов, при 72МГц тактвовой ядра Fd=72/20=3.6МГц - 5-6 отсчётов за период 500кГц - приемлемо, без усложнения аналогового фильтра на выходе ЦАП-ов. Я всё ещё не определился окончательно с MCU, потому что к задаче подходят и довольно шустрые C8051F12x, к тому же имеющие нужные 2 ЦАП-а на борту.
--------------------
Правильно поставленный вопрос - половина ответа...
|
|
|
|
|
Feb 8 2011, 22:00
|
Участник

Группа: Участник
Сообщений: 72
Регистрация: 7-01-11
Пользователь №: 62 073

|
Цитата Вы наверное имеете ввиду доступ к bit-banding региону Нет, bit-banding тут не при чем. Просто если посмотреть код, генерируемый компилятором, то видно, что маску он не делает. Делается либо сдвиг + проверка <0, либо используется команда TST, которая как раз и делает AND. А что надо получить в конечном итоге, прямоугольник заданной частоты? Может быть как-то на таймерах это сделать, неужели синус + компаратор лучше (не спорю, просто не сталкивался). На счет цапов я бы предложил попробовать реализовать используя возможности стм32, а именно дма + синхр. по таймеру.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|