|
SAM7S256 Системные прерывания перестают работать через 2-4часа, Помогите. |
|
|
|
Apr 1 2015, 07:49
|
Знающий
   
Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247

|
Основной процесс работает. Проверял так: Код *PIO_SODR = (1<<18); *PIO_CODR = (1<<18); иосцилографом. Используются прерывания от Real-time Timer и PITS Код __irq void SYS_int (void) { //Прерывание от System Controller. Время выполнения 1мкс на частоте 48МГц if (*PIT_SR & 1) { //Проверка бита PITS(0) из PIT_SR - регистр статуса интервального таймера *PIO_SODR = (1<<18); *PIO_CODR = (1<<18);
if (!(*PIO_PDSR&(1<<28))) {KnobCNT++;}//Если кнопка нажата - считаем время нажатия else if (KnobCNT) {Knob = KnobCNT; KnobCNT=0; Beep = 1;}//Если отжата и счетчик ненулевой - перезаписываем if (Beep) { //Прерывание по Periodic Interval Timer (PIT) стр77. P2.0 Beep--; // *PWM_ENA = 2;} //Разрешить работу канала PWM1 (CHID2) P2.0 else {*PWM_DIS = 2;} //Запретить работу канала PWM1 (CHID2) *AIC_EOICR = *PIT_PIVR; } //Чтение PIT_PIVR сбрасывает бит PITS в PIT_SR if (*RTT_SR & 2) { //Время выполнения 450нс на частоте 48МГц Strob = 1; //Прерывание по Real-time Timer (RTT) (для подсчёта секунд) стр71. *AIC_EOICR = 1;} // } //__irq void SYS_int (void) Инициализация системного прерывания: Код [/code] *AIC_SMR1 = (1 << 5) | 1; //Positive edge triggered (5), 1-й уровень пиоритета *AIC_SVR1 = (unsigned long) SYS_int; //Адрес обработчика прерывания *AIC_IECR = (1 << 1); //Разрешить системное прерывание SYS(1)
Инициализация RTT: [code] *RTT_MR=0x00008000 | (1<<17); //Секундный интервал и прерывания RTTINCIEN(17) = 1 Инициализация PIT: Код *PIT_MR = (1 << 25)| //Разрешить прерывание от PIT (1 << 24)| //Разрешить работу PIT 0xAFFFF; //Потолок счета PIT. Максимальное значение 1 048 575(FFFFFh)(20 бит) Через произвольное время 2-4 часа колом встает системное прерывание - оно не вызывается. Не могу понять куда копать, какие регистры вывести чтобы проверить. Помогите советом, добрые люди.
Сообщение отредактировал Димон Безпарольный - Apr 1 2015, 07:51
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 25)
|
Apr 1 2015, 08:36
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата The status register flags reset is taken into account only 2 slow clock cycles after the read of the RTT_SR (Status Register) Пример зависания: 1. сработал RTT 2. вошли в прерывание, прочитали RTT_SR 3. после выхода из прерывания линия остается активной еще 2 цикла slow clock 4. в этот момент пришло прерывание PIT 5. фронта нет и больше не будет, линия активна - висим
|
|
|
|
|
Apr 1 2015, 10:11
|

Знающий
   
Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663

|
В первом посте меня смущает наличие *AIC_EOICR = 1 в обработчике прерывания от SYSC (PIT и RTT - составные части системного контроллера, как впрочем и AIC). Если мы посмотрим на "потроха" SYSC, то мы увидим:
прерывания от составных частей являются "вложенными" для прерывания от AIC. Мне "к-а-а-атца", что *AIC_EOICR = 1 должно быть в обработчике прерывания от AIC и в единственном эеземпляре
--------------------
Пролетарий умственного труда.
|
|
|
|
|
Apr 1 2015, 11:15
|
Знающий
   
Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247

|
Чего то я совсем запутался. Я думал что для запрещения прерываний от RTT достаточно не программировать это: Код *RTT_MR=0x00008000 | (1<<17); Но прерывания от RTT все равно идут! Я не могу убрать ветку: Код if (*RTT_SR & 2) { //Время выполнения 450нс на частоте 48МГц *AIC_EOICR = 1;} // поскольку тогда прерывания вообще не работают. Прерывания от RTT все равно вызываются! Проверено. Как отключить прерывания от RTT?
Сообщение отредактировал Димон Безпарольный - Apr 1 2015, 11:39
|
|
|
|
|
Apr 1 2015, 11:43
|
Знающий
   
Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247

|
Цитата(aaarrr @ Apr 1 2015, 14:29)  Вынесите запись из блока if(){}. Правильно заметили, что она должна быть единственная и выполняться без всяких условий: попали в прерывание - на выходе всегда запись EOICR.
AIC, случайно, не в protect mode? Как вообще оформлен вектор на "нижнем уровне"? Как проверить protect mode прерывания? Я бы вынес запись EOICR, но как быть с PIT_PIVR? Читать его в какую - нибудь переменную? Код *AIC_EOICR = *PIT_PIVR; Чтение PIT_PIVR сбрасывает бит PITS в PIT_SR. К тому же я так и не смог отключить RTT и всех запутал. Пост 13.
Сообщение отредактировал Димон Безпарольный - Apr 1 2015, 11:43
|
|
|
|
|
Apr 1 2015, 11:53
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Димон Безпарольный @ Apr 1 2015, 14:43)  Как проверить protect mode прерывания? В AIC_DEBUG он включается. Лучше приведите код инициализации AIC и стартап (или где находится вектор IRQ), чтобы не приходилось гадать. Цитата(Димон Безпарольный @ Apr 1 2015, 14:43)  Я бы вынес запись EOICR, но как быть с PIT_PIVR? Читать его в какую - нибудь переменную? Оставьте просто *PIT_PIVR; Цитата(Димон Безпарольный @ Apr 1 2015, 14:43)  К тому же я так и не смог отключить RTT и всех запутал. Пост 13. Не понял, в чем состоит проблема. Просто не включайте ALMIEN и RTTINCIEN в RTT_MR.
|
|
|
|
|
Apr 1 2015, 12:00
|
Знающий
   
Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247

|
Цитата(aaarrr @ Apr 1 2015, 14:53)  Лучше приведите код инициализации AIC и стартап (или где находится вектор IRQ), чтобы не приходилось гадать. Код инициализации AIC Код *AIC_SMR1 = (1 << 5) | 1; //Positive edge triggered (5), 1-й уровень пиоритета *AIC_SVR1 = (unsigned long) SYS_int; //Адрес обработчика прерывания *AIC_IECR = (1 << 1); //Разрешить системное прерывание SYS(1) Стартап большой. Вот что касается IRQ: Код Mode_USR EQU 0x10 Mode_FIQ EQU 0x11 Mode_IRQ EQU 0x12 Mode_SVC EQU 0x13 Mode_ABT EQU 0x17 Mode_UND EQU 0x1B Mode_SYS EQU 0x1F
I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled
IRQ_Stack_Size EQU 0x00000080
; LDR PC,IRQ_Addr LDR PC,[PC,#-0xF20] ; Vector From AIC_IVR
IRQ_Addr DCD IRQ_Handler FIQ_Addr DCD FIQ_Handler
IRQ_Handler B IRQ_Handler FIQ_Handler B FIQ_Handler
; Enter IRQ Mode and set its Stack Pointer MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit MOV SP, R0 SUB R0, R0, #IRQ_Stack_Size
|
|
|
|
|
Apr 1 2015, 12:16
|
Знающий
   
Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247

|
Разобрался почему я не могу отключить RTT. Отключил PIT и RTT. Тогда прерывания остановились полностью. Включаю PIT и что я вижу? Выполнение кода из условия if (*RTT_SR & 2): Код if (*RTT_SR & 2) { //Время выполнения 450нс на частоте 48МГц Strob = 1; //Прерывание по Real-time Timer (RTT) (для подсчёта секунд) стр71. *AIC_EOICR = 1;} // Но RTT остановлен! Проверено. Дело в некорректной диагностики прерывания от RTT? Как тогда будет правильно?
Сообщение отредактировал Димон Безпарольный - Apr 1 2015, 12:19
|
|
|
|
|
Apr 1 2015, 12:19
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Димон Безпарольный @ Apr 1 2015, 15:16)  Разобрался почему я не могу отключить RTT. Отключил PIT и RTT. Тогда прерывания остановились полностью. Включаю PIT и что я вижу? Выполнение кода из условия: Код if (*RTT_SR & 2) Но RTT остановлен. Проверено. Дело в некорректной диагностики? Как тогда будет правильно? Все правильно, в статусном регистре биты в любом случае устанавливаются.
|
|
|
|
|
Apr 2 2015, 05:37
|
Знающий
   
Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247

|
Правильно написал aaarrr (пост6) что медленный таймер RTT при завершении прерывания блокирует линию SYS_INT еще на 2 цикла: Цитата The status register flags reset is taken into account only 2 slow clock cycles after the read of the RTT_SR (Status Register) В этом причина. Если прерывания случаются в этот период они уже не обрабатываются никогда. Страшно подумать какой геморрой будет если вместе с RTT включить остальные системные прерывания. Таймер RTT я больше не использую. Процессор проработал 12 часов без глюков. Проблема решена. Всем спасибо. Вот конечный код: Код __irq void SYS_int (void) { //Прерывание от System Controller. Время выполнения 1мкс на частоте 48МГц if (*PIT_SR & 1) { //Проверка бита PITS(0) из PIT_SR - регистр статуса интервального таймера Strob = 1; //Прерывание по Real-time Timer (RTT) (для подсчёта секунд) стр71. if (!(*PIO_PDSR&(1<<28))) {KnobCNT++;}//Если кнопка нажата - считаем время нажатия else if (KnobCNT) {Knob = KnobCNT; KnobCNT=0; Beep = 1;}//Если отжата и счетчик ненулевой - перезаписываем if (Beep) { //Прерывание по Periodic Interval Timer (PIT) стр77. P2.0 Beep--; // *PWM_ENA = 2;} //Разрешить работу канала PWM1 (CHID2) P2.0 else {*PWM_DIS = 2;} //Запретить работу канала PWM1 (CHID2) *PIT_PIVR; } //Чтение PIT_PIVR сбрасывает бит PITS в PIT_SR *AIC_EOICR = 1; } //__irq void SYS_int (void)
Сообщение отредактировал Димон Безпарольный - Apr 2 2015, 05:38
|
|
|
|
|
Apr 15 2015, 06:07
|
Знающий
   
Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247

|
Вышел из положения. Величину секундного таймера проверяю в прерывании RTT. Если величина отличается от ранее запомненой, выставляется секундный строб: Код if (!(RTT_Value==*RTT_VR)) {Strob1s=1; RTT_Value=*RTT_VR;}
|
|
|
|
|
Apr 15 2015, 11:59
|
Знающий
   
Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247

|
Цитата(aaarrr @ Apr 15 2015, 13:05)  Наверное, в прерывании PIT?
Мне все же интересно, зачем в системе иметь секундные прерывания от таймера, тактирующегося от RC-генератора? Ведь от Real Time там одно название на SAM7. В прерывании от PIT конечно. Да просто спортивный интерес. Секундные прерывания нужны для обновления дисплея. Точность не нужна. Можно было бы и прерывания от PIT через счетчик пересчитать. Собственно, оно так и было. Просто может кому пригодится..
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|