Перейти к содержанию
    

Настройка прерываний в LPC1778

Данная функция нужна для разрешения исключений с номером 16 и выше, как я понял.

Да, действительно. Исключения (внутренние прерывания) работают не так как внешние прерывания, то есть Enable делать не нужно...

 

Пробовал вставлять такую же функцию для SysTick - cрабатывает прерывание Hard Fault.

...и Clear Pend наверное тоже не нужно. Мне просто казалось, что там все однообразно делается.

 

NVIC_ClearPendingIRQ(UART0_IRQn) - можно и в начало поставить, но насколько это принципиально?

В данном случае не принципиально, но вообще можно придумать такую ситуацию, когда прерывание начнет бесконечно вытеснять самого себя. Не знаю возможно ли такое именно с NVIC, но в других МК я нарывался на подобное поведение. Например в TMS32F28x от TI, заходишь в обработчик прерывания, при этом все прерывания автоматом запрещаются, и чтобы разрешить вытеснение нужно их заново разрешить. Так вот, разрешаешь прерывания и тут же срабатывает это же прерывание, флаг же не сброшен, и так до бесконечности. Конечно, это несколько притянуто за уши, но все же. Кроме того, в рекомендованном Keil'ом варианте реализации вложенных прерываний для старичка ARM7, настоятельно рекомендовалось первым делом сбросить флаг. В общем, перенос этой процедуры в начало хуже не сделает, а вот если она будет в конце, то в некоторых условиях возможны интересные эффекты.

 

Если по делу, то идей почему не работает Sys Tick у меня нету. Включать прерывание, выходит, не надо, да оно по твоим словам уже и так работает, только вот не вытесняет. Хм, пока я смотрел действительно ли не нужно его включать, перед глазами промелькнул код в котором для него задавались приоритеты, а у тебя такого нету, но может я опять чего-то путаю. Во всяком случае поиск выдал кучу статей по настройке этого Sys Tick, можно и подсмотреть.

Изменено пользователем menzoda

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хм, пока я смотрел действительно ли не нужно его включать, перед глазами промелькнул код в котором для него задавались приоритеты, а у тебя такого нету, но может я опять чего-то путаю. Во всяком случае поиск выдал кучу статей по настройке этого Sys Tick, можно и подсмотреть.

Приоритеты прерываний не менял - они по умолчанию уже установлены. Пробовал менять местами обработчики, т.е. зацикливание делал в обработчике системного таймера, а отправка байта в UART0 вызывала соответствующее прерывание, которое по идее должно было бы вытеснить IRQ_SysTick, если бы у него был бы более низкий приоритет. Равенство приоритетов этих двух прерываний слишком маловероятно, поэтому руководствовался документацией, в которой IRQ_SysTick имеет приоритет 15, а UART0 - 21. В LPC17XX.h указан аналогичное соотношение приоритетов

SysTick_IRQn                  = -1,       /*!< 15 Cortex-M3 System Tick Interrupt             

..........
UART0_IRQn                    = 5,        /*!< UART0 Interrupt

 

Может быть нужно перевести главную программу в режим потока установкой бита CONTROL[0]? Сейчас главная программа работает в режиме обработчика, как и должно быть по умолчанию после сброса. Просто в данный момент нет платы под рукой, чтобы проверить.

Изменено пользователем ДЕЙЛ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С уровнями приоритетов разобрался. Ошибка была в том, что я заблуждался относительно предустановки уровней приоритетов. По умолчанию все программируемые прерывания имеют приоритет 0, т.е. самый высокий. Выше только немаскируемые с приоритетами -1 -2 и -3. А у меня получилось, что прерывание от UART0 и от системного таймера имели одинаковый приоритет и поэтому не было вложенности.

 

Добавил две строки в коде при инициализации:

AIRCR = 0x05FA0200;  //приоритет группы - поле [7:3], субприоритеты отключены, т.к. [2:0] не задействованы
IP1   = 0x800;           //уровень приоритета - 1, биты [2-0] не задействованы.

Остался открытым вопрос по настройке приоритета прерывания системного таймера. Он программируемый, судя по описанию ядра CORTEX-M3, но в даташите пока не откопал ничего по этому поводу. Ещё в описании рекомендуют указывать размер стека. Как он указывается?

Изменено пользователем ДЕЙЛ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

в описании ядра сказано, что при многоуровневой вложенности нужно думать о размере стека, вот и интересуюсь. Какая функция задаёт этот размер?

ПЫСЫ Имел ввиду не даташит, а user manual, т.е. руководство пользователя

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Никакая. Точнее так, можно сообщить библиотеке времени исполнения (CRT) границы стека, реализоваав _user_initial_stackheap, но имелось в виду не это. Размеры стека не указываются никакой функцией, под стек выделяется отдельная секция (какая - можно посмотреть в startup), размеры этой секции задаются в настроечном файле компоновщика (scatter-файл, *.sct). Проверить, хватает ли текущего размера стека не совсем тривиальная задача, никаких явных сообщений о переполнении стека не будет, нужно выкручиваться самому.

 

Например, перед началом работы программы заполняем стек одинаковым, по возможности редко встречающимся магическим значением. Запускаем программу и нагружаем ее как можно сильнее. После некоторого времени останавливаем и смотрим на область памяти со стеком: там где магические числа будут затерты - поработала наша программа. Считаем длину оставшейся незатертой части, если осталось совсем мало, или даже совсем не осталось, то лучше увеличить размер стека, иначе можно оставить все как есть.

 

Можно провести более точные измерения, вставив в каждую функцию код, который будет проверять текущее значение указателя на вершину стека и находить его минимальное значение (так как обычно стек "растет сверху-вниз"), но это слишком сложно.

 

Третий вариант - прикинуть эмперически, какова максимальная вложенность вызовов может наблюдаться в твоей программе. Например, в фоне крутиться функция Foo, использующая 12 байт стека, которая вызывает функцию Bar, использующую 15 байт стека. Получается, в фоне максимальная вложенность равна двум функцииям, при этом максимальное потребление стека 12 + 15 = 27 байт стека. Но есть еще прерывания: Tar и Gar, потребляющие 30 и 40 байт стека соответственно. Прерывания могут вытеснять друг-друга, а также прерывать фоновую задачу, в итоге имеем максимальную вложенность Foo + Bar + Tar + Gar и максимальное потребление стека 12 + 15 + 30 + 40 = 97 байт. Размер стека выбираем соответствующий, только нужно не забывать, что прерывания используют стек для сохранения текущих значений регистров ЦПУ, и учитывать это в вычислениях потребляемой памяти.

 

В общем то ARM имел в виду именно это - если у тебя прерывания начинают вытеснять друг-друга, то вложенность вызовов и соответственно потребление стека могут значительно увеличиться.

Изменено пользователем menzoda

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...