Кто-то любит пирожки, а кто-то - нет.
NVIC, векторный контроллер прерываний, есть во всех контроллерах на базе ядер Cortex-M, так как он входит в состав ядра. В старых ядрах контроллер прерываний был отдельно и не отличался хорошими характеристиками в плане скорости.
Описывается он подробно в Cortex-M4 Programming Manual.

читать дальше

<< Предыдущее Следующее >>

@темы: arm, программизмы, электроника, ассемблер, stm32f4discovery, stm32

Комментарии
19.11.2012 в 22:43

Спасибо! почитаю с удовольствием:)
19.11.2012 в 23:19

Позвольте поинтересоваться, а где был взят файл stm32f4xx.ini, если не ошибаюсь все константы для данного контроллера написаны на c в заловочном файле *.h.
Переписали сами?
19.11.2012 в 23:31

Кто-то любит пирожки, а кто-то - нет.
Гость, ага, переписал нужные из stm32f4xx.h, сохраняя названия в целях совместимости и взаимопонимания =)

Хотя по уму, их надо либо целиком перевести автоматически с Си на асм, написав или найдя соответствующую утилиту, либо сгенерировать инклюд из SVD-файлов... Хотя, по-моему, там только описание регистров... Но вручную переводить всё слишком уж муторно ^^"
19.11.2012 в 23:37

Аж зарегился)
Я переписал весь h файл но там нет offset, могу поделиться. ток подскажи смещения для ADC)
19.11.2012 в 23:58

Кто-то любит пирожки, а кто-то - нет.
HellEvil, смещения бери из референс мануала на семейство :) В конце каждой главы про периферию есть описание регистров. Их размер и смещение относительно базы :) В принципе, можно аналогично расписать структуры. В си смещения учитываются косвенно через структуры :)

База указана в карте памяти там же и в файле stm32f4xx.h
20.11.2012 в 07:35

А когда внешнее прерывание, bx lr не поможет выйти из обработчика, в этом случае сработает endp?:) запрещайте прерывания на время нахождения в нём с помощью CPSIE/CPSID Об этом надо бы подробнее:)
20.11.2012 в 08:03

Кто-то любит пирожки, а кто-то - нет.
HellEvil, ENDP - это не команда, а просто указание на логическое завершение блока (для ассемблера). Всё закончится на BX LR. Нет, если флаг не снять, то он просто зайдёт в него снова) И так будет, пока флаг не исчезнет.

Про них у меня мимоходом было сказано: Есть такая полезная инструкция CPS (Change Processor State). Раньше флаг глобального разрешения прерываний хранился в регистре CPSR и требовалось его считать, установить и записать (Команды MSR, MRS). Теперь всё делается за одну команду.

20.11.2012 в 18:03

BL ADC_RegularChannelConfig также действует с сишными функциями при подключении стартапа?
Вообще изначальная идея была использовать asm вставки в код но чтот они отказались пахать.
LDR R0, =ADC1 ; Это адрес же? да адрес:)
SHL R2, #2 ; Вроде ж так можно? незнаю, не пользовался командой shl.


_waitloop
; Читаем содержимое регистра
LDR R2, [R0, #ADC_SR_OFFSET]
; Накладываем маску и ставим флаги результата
ANDS R2, R1
BNE _waitloop ; Если не равно нулю, пробуем ещё раз

Занимательно. Я использовал немножко другой подход:) Для IDR
Proverka PROC
mov32 r0, GPIO_IDR_IDR_7
ldr r1, =GPIOC_BASE
str r0,[r1]
pov tst r0, #GPIO_IDR_IDR_7
BNE pov
bx lr
ENDP

Тут еще и ограничение U-mail это печально..
20.11.2012 в 18:33

Кто-то любит пирожки, а кто-то - нет.
HellEvil, не понял этого момента:


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

Не замечал, я u-mail почти не пользуюсь)
20.11.2012 в 18:55

Ах да чтот я сглупил я пробовал адаптировать это с f103. Если писали под такую штучку там есть такая вещь как GPIOA_IDR тоесть весь порт IDR. и выглядело как-то так:

Проверка нажатия кнопки. Сравниваются состояния PIN0 есть на нем 1 или нет, точно работало (stm32asm.ru/periph_pll_init.html).

Дак всеже можно вызывать функции си из asm при помощи BL?)
20.11.2012 в 18:57

Кто-то любит пирожки, а кто-то - нет.
HellEvil, ну да, я на то внимание и обращаю: надо каждый раз загружать состояние регистра IDR, чтоб его проверить)

Что ж нельзя-то?) Можно, если соблюдать соглашения о вызове. Я где-то в самом начале stm32f4 об этом писал и приводил примерны =)
25.02.2013 в 18:14

Здравствуйте, подскажите пожалуйста как вы заставили Keil понимать русский в вашем проекте?
25.02.2013 в 19:53

Кто-то любит пирожки, а кто-то - нет.
Ahtyng, в новых версиях в настройках среды есть чыбор кодировки редактора. У меня выбран UTF-8.

В принципе, можно использовать ANSI, — в сети есть патч, который добавляет русские символы в неё (на рутрекере в частности). Единственный минус — не понимает «ё». Ну и есть только под некоторый диапазон более-менее новых версий.
01.03.2013 в 18:11

Здравствуйте еще раз. Ковыряюсь в stmf4discovery пытаюсь настроить прерывание с кнопки PA0 добился того что при нажатие на кнопку выставляются биты в регистрах EXTI_PR и NVIC_ISPR0 я так понимаю, что с этого момента контроллер должен перейти по вектору прерывания и ждать пока я сброшу бит в EXTI_PR, но вместо этого продолжает крутиться в mainloop, подскажите пожилуйста, что я еще не настроил. Вот какие регистры я настраивал:
регистр - адрес со сдвигом/маска
RCC_APB2ENR - 0x40023844/0x00004000
SYSCFG_EXTICR1 - 0x40013808/0x0000000
EXTY_IMR - 0x40013C00/0x00000001
EXTI_RTSR - 0x40013C08/0x00000001
EXTI_FTSR - 0x40013C0C/0x00000001
NVIC_ISER0 - 0xE000E100/0x00000020

В качестве основы взят проект с морганием светодиодами и в него уже дописывалась вся инициализация. может как то неправильно описал процедуру обработчик? Хотя сделал все как у вас вроде: в startup_stm32f4xx.s ничего не менял, а код обработчика вот

01.03.2013 в 19:21

Вы уверены что он крутиться в mainloop? По сути прерывания после выполения возвращаются к месту на котором был остановлен ко регистр R14(если не ошибаюсь) за это в ответе. Вижу что вы пытаетесь зажечь и потушить светодиод, но в данном случае, слишком маленький размер кода чтоб увидеть включение. роставте после зажжения nop раз 5-6 и проверьте работает ли прерывание.
п.с. в кейле можно пользоваться и отладчиком. только для отладки камешек f103 попробуй:)
п.с.с лутше бы весь проект в студию, т.к возможно причины могут быть в другом
01.03.2013 в 23:00

Кто-то любит пирожки, а кто-то - нет.
Ahtyng, неправильный канал выбран в NVIC.

EXTI0 — 6 канал, а значит маска 0x40, а не 0x20. Потому функции удобнее. Сейчас у вас выбрано прерывание от RCC.
02.03.2013 в 18:58

teplofizik, спасибо проблема действительно была в неправильной маске, хотя я знал что мне нужно 6-е прерывание, видимо глаз замылился пока искал косяк.
HellEvil
Вы уверены что он крутиться в mainloop?
я пользуюсь st-link дебагером так что видел и состояние регистров, и какая команда выполняется.
05.03.2013 в 13:56

Кто-то любит пирожки, а кто-то - нет.
Ahtyng, маски дело такое, в си я их даже не использую сами по себе, только как (1 << 5) или типа того. Тут уж сразу видно какой бит выбран =)
А в асме предпочту использовать именованные константы, там, где их много, (перечислены все) видно, кого не хватает и где что потеряно. По-моему, Кейл и в асме так делать умеет.
07.07.2013 в 18:18

Уже не первый день долблюсь с этими прерываниями.
Вначале совсем забыл "при включении всё выключено", к прерываниям тоже относится.
Потом не сразу въехал в NVIC и EXTI. EXTI описывается в референсе на F100xx, а NVIC - нет. Можно было бы написать, мол "Про NVIC почитайте в референсе F10xxx"
И потом всё рассчитано под код на сцях, примерами весь инет завален, а вот с асмом беда.

В общем IRQ для TIM6 ровно 54 (на F100 камни)
По вышеописанным формулам получаем номер регистра: 1 = ( 54 >> 5 ) и номер бита: 16 = ( 54 & 0x1F )
Базовый адрес NVIC_ISER равен 0xE000E100, а первый регистр равен 0xE000E104 (NVIC_ISER1)
Значит по адресу NVIC_ISER1 нужно накатить значение 0x8000 ( без чтения и модификации, предположим там нули ) что будет равно 0b1000000000000000
Тем самым разрешим прерывания от TIM6
Не работает блин :(
Берём nvic.s от уважаемого teplofizik и включаем его в проект.
NVIC_EnableIRQ по адресу NVIC_ISER1 записывает значение 0x400000 о_О
В общем и этот вариант тоже не пашет.
Открываем Сишные либы от ST, роемся, находим: NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); ( сдвиг в лево это маска? )
В этих же либах можно найти: #define NVIC_ISER_SETENA_16 ((uint32_t)0x00010000) /*!< bit 16 */
Ничерта не понятно....

Перепробовал все варианты, ни один не работает.
Я прикреплю код, если будет не лень посмотреть, указать на ошибку.
Кстати ещё вопрос, в векторной таблице обязательно должно быть значение +1 на всех обработчиках прерывания?

pastebin.com/urQ4iKic - основной
pastebin.com/Q6DXaj5D - таблица векторов
pastebin.com/DWRB90h9 - линкер

Плата: STM32 VL Discovery
Компилятор: arm-none-linux-gnueabi
07.07.2013 в 19:46

Кто-то любит пирожки, а кто-то - нет.
Можно было бы написать, мол "Про NVIC почитайте в референсе F10xxx"
Про NVIC надо читать в Cortex-M3 Programming Manual, раздел 4.3 =) В доках по контроллерам максимум упомянут кратко регистры и порядок следования векторов. Ну и ссылка на этот документ)

16 = ( 54 & 0x1F )
Позволю заметить, что 0x36 & 0x1F = 0x16 (22 бит). То есть 0x400000 — это правильно.

А что конкретно не пашет? Не попадает в прерывание или светодиодом не моргает?) Так я для светодиода не вижу настройки (на выход)... Да и битбенд, он всё куда надо пишет?=)

в векторной таблице обязательно должно быть значение +1 на всех обработчиках прерывания
Думаю, да. Тут суть в том, что изначально армы, которые имели два набора инструкции ARM и Thumb переключали наборы переходя с помощью команды BX, а набор команд выбирался последним битом: 0 означал 32битный арм, а 1 — 16битный Thumb. В кортексах набор всего один, Thumb2, но единичка в конце адреса сохранилась. В Кейле такого нет, но, думаю, он добавляет единички к адресам процедур во время сборки.

Плохо, что у меня нет платки, на которой проверить можно было бы =) У меня только F0 и F4...
08.07.2013 в 03:06

Про NVIC надо читать в Cortex-M3 Programming Manual
Уже полистал, увидел у вас в сносках, спасибо.

А что конкретно не пашет?
Да вот хрен его знает :)
Вернее сказать не срабатывает обработчик прерывания. Обработчик должен потушить диод, что будет являться показателем его срабатывания.
Вроде с векторной таблицей всё правильно, проверил всё много раз.
И с включением прерываний как бы не должно быть ошибки, я даже в NVIC_ISER1 записал 0xFFFFFFFF чтобы уж точно :) Не завелось.
Вариантов думаю всего два: ошибка в таблице векторов или ошибка с включением прерывания для TIM6 через NVIC.
Таймер считает, флаг UIF выставляется таймером, UIE выставлен, а вот прерывание не срабатывает.

По поводу векторной таблицы:
читать дальше

Эх, жаль в своё время не было литературы по асму для спектрума, наверное знаний бы тогда в этой области у меня сейчас побольше было бы :)
08.07.2013 в 03:10

Кто-то любит пирожки, а кто-то - нет.
altaw, но я всё не вижу настройки диода в данном коде =) Потому не удивлюсь, если он не может моргать чисто физически=)

А отладка что показывает? Там же можно все регистры прям руками помацать, светодиодом мышкой поморгать (чтоб проверить, что он работает), настроить таймер без кода и проверить, попадает ли он в прерывание и без светодиода, поставив точку останова =)
08.07.2013 в 04:34

но я всё не вижу настройки диода в данном коде =)
Имеете ввиду тактирование и настройка ножек на выход?
Я просто забыл сказать, в платке до сих пор вшита стандартная прошивка с завода, я её даже не менял. Программу гружу в память и оттуда запускаю, соответственно на момент запуска уже всё настроено, порты затактированны, ножка на кнопку настроена на вход, а на диоды - на выход.
В опубликованном коде диод должен переключаться, но сейчас там просто команда на его отключение.
А много ли дебагером можно уловить в такой ситуации? Я конечно смотрел, но там ничего особенного, основная программа доходит до Main и там зацикливается. А команда в обработчике прерывания на гашение диода равносильна точке останова в этом же обработчике. К слову точку ставил, не срабатывает :D
Кстати надо бы гуишный отладчик настроить, а то сижу в gdb. Это в кейле можно мышкой подёргать светодиодом и таймер настроить? Блин, удобно, не поспоришь :) Но мне кейл не понравился, ну... что-то в нём не то, да и под виндой сидеть надо, а я в основном работаю в пингвине :)

Пришла мысль. Попробую код на Си, если будет работать, посмотрю какие значения он пишет в NVIC_ISER
08.07.2013 в 04:48

Кто-то любит пирожки, а кто-то - нет.
altaw, ну для обучения кейл весьма удобен =) В плане отладки. Там сразу и System Viewer есть, где эти регистры все расписаны и могут быть отредактированы.

Да, это правильный подход =)
21.07.2013 в 01:48

А ларчик то просто открывался.
Нужно было просто переназначить таблицу векторов на новое место.
MOV32 R0, 0xE000ED08
MOV32 R1, newaddr
STR R1, [R0]
И сразу всё заработало :)
В Си так и не полез, дебри, лучше пока асм покурю.
21.07.2013 в 14:27

Кто-то любит пирожки, а кто-то - нет.
altaw, а по умолчанию там что было? о.о

Или надо было в оперативку загнать?)
21.07.2013 в 17:01

По умолчанию были нолики :) А-ка флеш.
Не вижу смысла грузить каждый раз в флеш когда можно грузить в оперативку.
21.07.2013 в 17:07

Кто-то любит пирожки, а кто-то - нет.
altaw, ну да, по умолчанию он показывает на старт флеша, куда обычно программа и загружается=)
21.07.2013 в 22:23

ну да, по умолчанию он показывает на старт флеша, куда обычно программа и загружается=)

Да я же этого не знал, совсем недавно начал изучать мк как таковые :)

Вас не затруднит объяснить вот этот момент
Позволю заметить, что 0x36 & 0x1F = 0x16 (22 бит). То есть 0x400000 — это правильно.
Не могу понять как связано 0x16, 22бита и 0x400000. То есть почему в ручном получаем 0х16, а функция выставляет значение 0х400000
21.07.2013 в 23:17

Кто-то любит пирожки, а кто-то - нет.
altaw, Не могу понять как связано 0x16, 22бита и 0x400000. То есть почему в ручном получаем 0х16, а функция выставляет значение 0х400000

0x16 — это 22 в десятичной системе счисления. 0x400000 — это число, где установлен только 22 бит (маска) =)