|
|
  |
Вложенные прерывания Cortex M3 (LPC1768), не выполняются |
|
|
|
Dec 28 2012, 07:34
|
Частый гость
 
Группа: Свой
Сообщений: 131
Регистрация: 14-10-08
Из: г. Королев
Пользователь №: 40 940

|
Здравствуйте, уважаемые! Пишу реализацию ПИД-регулятора. МК LPC1768 Период перерасчета должен быть соблюден крайне точно, поэтому использую прерывания по таймеру и устанавливаю этому прерыванию наивысший приоритет. CODE void init_tmr1() { T1TCR_bit.CR = 1; // Сбрасываем T1TCR_bit.CR = 0; /* Fp = 25 МГц Частота периферии. T = 20 мс Желаемый период таймера. N = Fp/T Формула рачета кол-ва тактов за период. N = 250000 Кол-во тактов за желаемый период таймера. */ T1MR0 = 250000; // Загружаем регистр сравнения T1MCR_bit.MR0I = 1; // Разрешаем прерывание по совпадению MR0 T1MCR_bit.MR0R = 1; // Разрешаем сброс таймера по совпадению MR0 T1TCR_bit.CE = 1; // Разрешаем счет IP0_bit.PRI_2 = 0; // Приоритет прерывания: наивысший (0) SETENA0_bit.SETENA2 = 1; // Разрешаем прерывания в NVIC } Далее в обработчике прерываний от этого таймера есть получение данных с абсолютного датчика положения. Опрос датчика производится из прерывания таймера 1 раз за прерывания, поэтому на осциллографе я наблюдаю пакеты опроса датчика строго с частотой таймера. Ок. Теперь инициализирую UART для приема управляющего воздействия (DMX512) CODE PCONP_bit.PCUART3 = 1; FIO3DIR_bit.P3_26 = 1; FIO3CLR = 1 << 26; PINSEL0_bit.P0_0 = 2; PINSEL0_bit.P0_1 = 2; // Скорость /* F = Fp/(16*(DLM*256+DLL)*(1+DIV/MUL)) F = 250 kBod Fp = 100 MHz DLM = 0 DLL = 25 DIV = 0 MUL = 1 */ U3LCR_bit.DLAB = 1; U3DLL = 25; U3DLM = 0; U3LCR_bit.DLAB = 0; // FIFO U3FCR_bit.FCRFE = 1; // Включаем FIFO U3FCR_bit.RFR = 1; // Сбрасываем RxFIFO U3FCR_bit.TFR = 1; // Сбрасываем TxFIFO U3FCR_bit.RTLS = 2; // Порог срабатывания 8 символов // Формат U3LCR_bit.WLS = 3; // 8 бит U3LCR_bit.SBS = 1; // 2 стоп-бита // Преывания U3IER_bit.RDAIE = 1; // Разрешаем прерывание по входящим данным U3IER_bit.RXLSIE = 1; // Разрешаем прерывание по статусу линии IP2_bit.PRI_8 = 2; // Приоритет прерывания: средний (2) SETENA0_bit.SETENA8 = 1; // Разрешаем в NVIC } И в обработчике прерываний уже непосредственно получение данных из FIFO. Итак: приоритет таймера - 0, приоритет UART - 2. Но когда по UART приходят данные период таймера нарушается и становится вообще не понятно каким. То есть вложенные прерывания не выполняются? Как это исправить? А если в процессе приема данных по UART отключить источник сигнала, то программа из прерывания UART вообще не выходит и прерывания таймера не выполняются вообще! Вот обработчик UART CODE void UART3_IRQHandler() { char uiir, ulsr, urbr; do { uiir = U3IIR; ulsr = U3LSR; if((uiir & INTID) == RLS) { if(ulsr & (OE | PE)) bDMX = 0; if(ulsr & BI) { nDMX = 0; bDMX = 1; } U3RBR; } if((uiir & INTID) == RDA) { urbr = U3RBR; if(nDMX && bDMX && (nDMX < 513)) DMX[(nDMX++)-1] = urbr; else if(!(nDMX++) && urbr) bDMX = 0; } } while(!(uiir & INTPEND)); CLRPEND0_bit.CLRPEND8 = 1; }
Сообщение отредактировал IgorKossak - Dec 28 2012, 08:15
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!, форматирование
|
|
|
|
|
Dec 28 2012, 09:36
|
Частый гость
 
Группа: Свой
Сообщений: 131
Регистрация: 14-10-08
Из: г. Королев
Пользователь №: 40 940

|
Цитата(SSerge @ Dec 28 2012, 13:05)  А что с регистром AIRCR и полем PRIGROUP в нём? Там у кортексов настраиваются группы приоритетов. Не пойму, о каких регистрах идет речь? В мануале описаны следующие регистры, относящиеся к NVIC: ISER0 - ISER3 RW Set-Enabe Разрешение прерывания ICER0 - ICER3 RW Clear-Enable Запрет прерывания ISPR0 - ISPR3 RW Set-Pending Установка ожидания (обработки) ICPR0 - ICPR3 RWClear-Pending Снятие ожидания (обработки) IABR0 - IABR3 RO Active Bit Состояние текущих прерываний (только чтение) IPR0 - IPR27 RW Priority Установка приоритетов STIR WO Software Trigger Программные прерывания У меня в конце каждой функции инициализации периферии стоит установка приоритета и разрешение прерывания. А в конце каждого обработчика снятие ожидания. Повторюсь: у таймера приоритет - 0, у UART'а - 2. Только почему-то из обработчика UART при возникновении прерывания по таймеру с высшим приоритетом перехода к его обработчику не происходит никогда.
|
|
|
|
|
Dec 28 2012, 10:12
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(theBMV @ Dec 28 2012, 10:36)  У меня в конце каждой функции инициализации периферии стоит установка приоритета и разрешение прерывания. А в конце каждого обработчика снятие ожидания. Повторюсь: у таймера приоритет - 0, у UART'а - 2. Только почему-то из обработчика UART при возникновении прерывания по таймеру с высшим приоритетом перехода к его обработчику не происходит никогда. По умолчанию контроллер прерываний не настроен на вложенные прерывания. Для большинства случаев (до 16-ти уровней приоритетов и 16 подгрупп) подойдет вызов NVIC_SetPriorityGrouping(0x03) при инициализации приложения. Функция объявлена и реализована в core_cm3.h (но включать этот заголовок явно не надо, т.к. он включается через аппаратно-зависимый заголовок процессора).
|
|
|
|
|
Jan 16 2013, 10:28
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Цитата(KnightIgor @ Dec 28 2012, 14:12)  По умолчанию контроллер прерываний не настроен на вложенные прерывания. Что-то я не понимаю... По умолчанию в AIRCR поле "Interrupt priority grouping field" равно нулю. По моим соображениям, это означает, что приоритеты прерываний - это именно priority, а не subpriority. Т.е. количество вложенных прерываний может быть максимальным. Ссылку на infocenter.arm.com дать не могу - никак не найду, где её там взять :-) На железе, правда, все свои соображения проверить поленился: у меня критичное к времени старта прерывание ровно одно, оно же - самое длительное. Остальные прерывания быстрые, и особо не влияют. Пока, во всяком случае...
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Jan 16 2013, 13:27
|

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

|
Цитата(esaulenka @ Jan 16 2013, 16:28)  По умолчанию в AIRCR поле "Interrupt priority grouping field" равно нулю. По моим соображениям, это означает, что приоритеты прерываний - это именно priority, а не subpriority. Т.е. количество вложенных прерываний может быть максимальным. Да, именно так. Я, помнится, тоже когда читал этот тред, удивился. Но раз заработало, то и ладно
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jan 16 2013, 14:17
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Может, нам theBMV расскажет, что у него за компилятор? И даже стартапы все покажет? :-)
Кейл по умолчанию делает только инициализацию стеков, включает питание на периферию и настраивает PLL. Тут, кажется, IAR, и там, может, есть настройки NVIC ?
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Jan 16 2013, 17:10
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(esaulenka @ Jan 16 2013, 17:28)  По умолчанию в AIRCR поле "Interrupt priority grouping field" равно нулю. По моим соображениям, это означает, что приоритеты прерываний - это именно priority, а не subpriority. Т.е. количество вложенных прерываний может быть максимальным. Так-то оно так, но если используется не 8, а только 4 бита под приоритеты непонятно как интерпретировать значения 0, 1 и 2 в этом поле. Нигде определённо этого не сказано. Могли для экономии вентилей сделать "как получится".
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
Jan 22 2013, 06:31
|
Частый гость
 
Группа: Свой
Сообщений: 131
Регистрация: 14-10-08
Из: г. Королев
Пользователь №: 40 940

|
Цитата(esaulenka @ Jan 16 2013, 14:28)  Что-то я не понимаю... По умолчанию в AIRCR поле "Interrupt priority grouping field" равно нулю. По моим соображениям, это означает, что приоритеты прерываний - это именно priority, а не subpriority. Т.е. количество вложенных прерываний может быть максимальным. Я тоже так думал, пока у меня одно прерывание не зациклилось (с наинизшим приоритетом, между прочим) и не давало прерываниям с наивысшими приоритетами отработать. Поэтому (PRIGROUP == 0) - это отключенная вложенность, и приоритетность прерываний ни коим образом не работает. Проверено. А "приоритеты прерываний - это именно priority, а не subpriority" достигается, когда (PRIGROUP == 2). Table 660. Priority grouping в мануале на LPC1768. Цитата(esaulenka @ Jan 16 2013, 18:17)  Может, нам theBMV расскажет, что у него за компилятор? И даже стартапы все покажет? :-)
Кейл по умолчанию делает только инициализацию стеков, включает питание на периферию и настраивает PLL. Тут, кажется, IAR, и там, может, есть настройки NVIC ? Компилятор IAR. В стартапе указатлель на вершину стека, вектор сброса и вектора прерываний периферии с именами функций. Взят из примеров к IAR'у CODE /************************************************** * * Part one of the system initialization code, contains low-level * initialization, plain thumb variant. * * Copyright 2009 IAR Systems. All rights reserved. * * $Revision: 33389 $ * **************************************************/
; ; The modules in this file are included in the libraries, and may be replaced ; by any user-defined modules that define the PUBLIC symbol _program_start or ; a user defined start symbol. ; To override the cstartup defined in the library, simply add your modified ; version to the workbench project. ; ; The vector table is normally located at address 0. ; When debugging in RAM, it can be located in RAM, aligned to at least 2^6. ; The name "__vector_table" has special meaning for C-SPY: ; it is where the SP start value is found, and the NVIC vector ; table register (VTOR) is initialized to this address if != 0. ; ; Cortex-M version ;
MODULE ?cstartup
;; Forward declaration of sections. SECTION CSTACK:DATA:NOROOT(3)
SECTION .intvec:CODE:NOROOT(2)
EXTERN __iar_program_start PUBLIC __vector_table PUBLIC __vector_table_0x1c
DATA __vector_table DCD sfe(CSTACK) ; Top of Stack DCD __iar_program_start ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler __vector_table_0x1c DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler DCD WDT_IRQHandler ; Watchdog Handler DCD TMR0_IRQHandler ; TIMER0 Handler DCD TMR1_IRQHandler ; TIMER1 Handler DCD TMR2_IRQHandler ; TIMER2 Handler DCD TMR3_IRQHandler ; TIMER3 Handler DCD UART0_IRQHandler ; UART0 Handler DCD UART1_IRQHandler ; UART1 Handler DCD UART2_IRQHandler ; UART2 Handler DCD UART3_IRQHandler ; UART3 Handler DCD PWM1_IRQHandler ; PWM1 Handler DCD I2C0_IRQHandler ; I2C0 Handler DCD I2C1_IRQHandler ; I2C1 Handler DCD I2C2_IRQHandler ; I2C2 Handler DCD SPI_IRQHandler ; SPI Handler DCD SSP0_IRQHandler ; SSP0 Handler DCD SSP1_IRQHandler ; SSP1 Handler DCD PLL0_IRQHandler ; PLL0 Handler DCD RTC_IRQHandler ; RTC Handler DCD EINT0_IRQHandler ; EXT Interupt 0 Handler DCD EINT1_IRQHandler ; EXT Interupt 1 Handler DCD EINT2_IRQHandler ; EXT Interupt 2 Handler DCD EINT3_IRQHandler ; EXT Interupt 3 Handler DCD ADC_IRQHandler ; ADC Handler DCD BOD_IRQHandler ; BOD Handler DCD USB_IRQHandler ; USB Handler DCD CAN_IRQHandler ; CAN Handler DCD GPDMA_IRQHandler ; General Purpose DMA Handler DCD I2S_IRQHandler ; I2S Handler DCD Ethernet_IRQHandler ; Ethernet Handler DCD RIT_IRQHandler ; Repetitive Interrupt Timer Handler DCD MotorControlPWM_IRQHandler; Motor Control PWM Handler DCD QE_IRQHandler ; Quadrature Encoder Handler DCD PLL1_IRQHandler ; PLL1 Handler
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Default interrupt handlers. ;;
PUBWEAK NMI_Handler PUBWEAK HardFault_Handler PUBWEAK MemManage_Handler PUBWEAK BusFault_Handler PUBWEAK UsageFault_Handler PUBWEAK SVC_Handler PUBWEAK DebugMon_Handler PUBWEAK PendSV_Handler PUBWEAK SysTick_Handler PUBWEAK WDT_IRQHandler PUBWEAK TMR0_IRQHandler PUBWEAK TMR1_IRQHandler PUBWEAK TMR2_IRQHandler PUBWEAK TMR3_IRQHandler PUBWEAK UART0_IRQHandler PUBWEAK UART1_IRQHandler PUBWEAK UART2_IRQHandler PUBWEAK UART3_IRQHandler PUBWEAK PWM1_IRQHandler PUBWEAK I2C0_IRQHandler PUBWEAK I2C1_IRQHandler PUBWEAK I2C2_IRQHandler PUBWEAK SPI_IRQHandler PUBWEAK SSP0_IRQHandler PUBWEAK SSP1_IRQHandler PUBWEAK PLL0_IRQHandler PUBWEAK RTC_IRQHandler PUBWEAK EINT0_IRQHandler PUBWEAK EINT1_IRQHandler PUBWEAK EINT2_IRQHandler PUBWEAK EINT3_IRQHandler PUBWEAK ADC_IRQHandler PUBWEAK BOD_IRQHandler PUBWEAK USB_IRQHandler PUBWEAK CAN_IRQHandler PUBWEAK GPDMA_IRQHandler PUBWEAK I2S_IRQHandler PUBWEAK Ethernet_IRQHandler PUBWEAK RIT_IRQHandler PUBWEAK MotorControlPWM_IRQHandler PUBWEAK QE_IRQHandler PUBWEAK PLL1_IRQHandler
SECTION .text:CODE:REORDER(1) THUMB NMI_Handler HardFault_Handler MemManage_Handler BusFault_Handler UsageFault_Handler SVC_Handler DebugMon_Handler PendSV_Handler SysTick_Handler WDT_IRQHandler TMR0_IRQHandler TMR1_IRQHandler TMR2_IRQHandler TMR3_IRQHandler UART0_IRQHandler UART1_IRQHandler UART2_IRQHandler UART3_IRQHandler PWM1_IRQHandler I2C0_IRQHandler I2C1_IRQHandler I2C2_IRQHandler SPI_IRQHandler SSP0_IRQHandler SSP1_IRQHandler PLL0_IRQHandler RTC_IRQHandler EINT0_IRQHandler EINT1_IRQHandler EINT2_IRQHandler EINT3_IRQHandler ADC_IRQHandler BOD_IRQHandler USB_IRQHandler CAN_IRQHandler GPDMA_IRQHandler I2S_IRQHandler Ethernet_IRQHandler RIT_IRQHandler MotorControlPWM_IRQHandler QE_IRQHandler PLL1_IRQHandler Default_Handler B Default_Handler END
Сообщение отредактировал IgorKossak - Jan 22 2013, 08:27
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Jan 22 2013, 08:37
|

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

|
Цитата(theBMV @ Jan 22 2013, 12:31)  Поэтому (PRIGROUP == 0) - это отключенная вложенность, и приоритетность прерываний ни коим образом не работает. Проверено. А вот ARM утверждает обратное: Цитата PRIGROUP[2:0] : 0 Pre-emption field : [7:1] Subpriority field : [0]. Note. - For a processor configured with less than eight bits of priority, the lower bits of the register are always 0. For example, if four bits of priority are implemented, PRI_N[7:4] sets the priority, and PRI_N[3:0] is 4'b0000
Цитата(theBMV @ Jan 22 2013, 12:31)  Table 660. Priority grouping в мануале на LPC1768. Думаете, NXP смогли переделать ядро? Сильно сомневаюсь.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 25 2013, 13:27
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Прошёл всего лишь месяц, и у меня дошли руки проверить.
LPC1778 (уж что было под рукой, с припаяным лог.анализатором).
Один таймер с NVIC_SetPriority(4), другой таймер с NVIC_SetPriority(0). В первом - длительная задержка (в половину его периода) и дрыганье ножкой на входе и выходе. Во втором - также дрыганье ножкой. Кроме EnableIRQ и SetPriority, в проекте больше нет никаких обращений к NVIC'у. Компилятор - кейл.
В итоге - дрыг ножкой второго таймера от первого никак не зависит, находится ли тот в прерывании, или нет.
Собственно, что и требовалось доказать - NXP люди вменяемые и делают контроллеры, которые работают согласно документации :-)
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|