theBMV 0 28 декабря, 2012 Опубликовано 28 декабря, 2012 (изменено) · Жалоба Здравствуйте, уважаемые! Пишу реализацию ПИД-регулятора. МК LPC1768 Период перерасчета должен быть соблюден крайне точно, поэтому использую прерывания по таймеру и устанавливаю этому прерыванию наивысший приоритет. 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) 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 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; } Изменено 28 декабря, 2012 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!!, форматирование Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SSerge 6 28 декабря, 2012 Опубликовано 28 декабря, 2012 · Жалоба А что с регистром AIRCR и полем PRIGROUP в нём? Там у кортексов настраиваются группы приоритетов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
theBMV 0 28 декабря, 2012 Опубликовано 28 декабря, 2012 · Жалоба А что с регистром 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 при возникновении прерывания по таймеру с высшим приоритетом перехода к его обработчику не происходит никогда. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 28 декабря, 2012 Опубликовано 28 декабря, 2012 · Жалоба У меня в конце каждой функции инициализации периферии стоит установка приоритета и разрешение прерывания. А в конце каждого обработчика снятие ожидания. Повторюсь: у таймера приоритет - 0, у UART'а - 2. Только почему-то из обработчика UART при возникновении прерывания по таймеру с высшим приоритетом перехода к его обработчику не происходит никогда. По умолчанию контроллер прерываний не настроен на вложенные прерывания. Для большинства случаев (до 16-ти уровней приоритетов и 16 подгрупп) подойдет вызов NVIC_SetPriorityGrouping(0x03) при инициализации приложения. Функция объявлена и реализована в core_cm3.h (но включать этот заголовок явно не надо, т.к. он включается через аппаратно-зависимый заголовок процессора). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
theBMV 0 28 декабря, 2012 Опубликовано 28 декабря, 2012 · Жалоба Ого! Только что нашел: Appendix: Cortex-M3 user guide в мануале на LPC1768! Там как раз всё расписано! Всем спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 16 января, 2013 Опубликовано 16 января, 2013 · Жалоба По умолчанию контроллер прерываний не настроен на вложенные прерывания. Что-то я не понимаю... По умолчанию в AIRCR поле "Interrupt priority grouping field" равно нулю. По моим соображениям, это означает, что приоритеты прерываний - это именно priority, а не subpriority. Т.е. количество вложенных прерываний может быть максимальным. Ссылку на infocenter.arm.com дать не могу - никак не найду, где её там взять :-) На железе, правда, все свои соображения проверить поленился: у меня критичное к времени старта прерывание ровно одно, оно же - самое длительное. Остальные прерывания быстрые, и особо не влияют. Пока, во всяком случае... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 16 января, 2013 Опубликовано 16 января, 2013 · Жалоба По умолчанию в AIRCR поле "Interrupt priority grouping field" равно нулю. По моим соображениям, это означает, что приоритеты прерываний - это именно priority, а не subpriority. Т.е. количество вложенных прерываний может быть максимальным. Да, именно так. Я, помнится, тоже когда читал этот тред, удивился. Но раз заработало, то и ладно:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 16 января, 2013 Опубликовано 16 января, 2013 · Жалоба Может, нам theBMV расскажет, что у него за компилятор? И даже стартапы все покажет? :-) Кейл по умолчанию делает только инициализацию стеков, включает питание на периферию и настраивает PLL. Тут, кажется, IAR, и там, может, есть настройки NVIC ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SSerge 6 16 января, 2013 Опубликовано 16 января, 2013 · Жалоба По умолчанию в AIRCR поле "Interrupt priority grouping field" равно нулю. По моим соображениям, это означает, что приоритеты прерываний - это именно priority, а не subpriority. Т.е. количество вложенных прерываний может быть максимальным. Так-то оно так, но если используется не 8, а только 4 бита под приоритеты непонятно как интерпретировать значения 0, 1 и 2 в этом поле. Нигде определённо этого не сказано. Могли для экономии вентилей сделать "как получится". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 16 января, 2013 Опубликовано 16 января, 2013 · Жалоба Так-то оно так, но если используется не 8, а только 4 бита под приоритеты непонятно как интерпретировать значения 0, 1 и 2 в этом поле. Они все эквивалентны значению 0. (Потому что различия между этими вариантами приходятся на не-имплементированные биты приоритета). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
theBMV 0 22 января, 2013 Опубликовано 22 января, 2013 (изменено) · Жалоба Что-то я не понимаю... По умолчанию в AIRCR поле "Interrupt priority grouping field" равно нулю. По моим соображениям, это означает, что приоритеты прерываний - это именно priority, а не subpriority. Т.е. количество вложенных прерываний может быть максимальным. Я тоже так думал, пока у меня одно прерывание не зациклилось (с наинизшим приоритетом, между прочим) и не давало прерываниям с наивысшими приоритетами отработать. Поэтому (PRIGROUP == 0) - это отключенная вложенность, и приоритетность прерываний ни коим образом не работает. Проверено. А "приоритеты прерываний - это именно priority, а не subpriority" достигается, когда (PRIGROUP == 2). Table 660. Priority grouping в мануале на LPC1768. Может, нам theBMV расскажет, что у него за компилятор? И даже стартапы все покажет? :-) Кейл по умолчанию делает только инициализацию стеков, включает питание на периферию и настраивает PLL. Тут, кажется, IAR, и там, может, есть настройки NVIC ? Компилятор IAR. В стартапе указатлель на вершину стека, вектор сброса и вектора прерываний периферии с именами функций. Взят из примеров к IAR'у /************************************************** * * 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 Изменено 22 января, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 22 января, 2013 Опубликовано 22 января, 2013 · Жалоба Поэтому (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 Table 660. Priority grouping в мануале на LPC1768. Думаете, NXP смогли переделать ядро? Сильно сомневаюсь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 25 февраля, 2013 Опубликовано 25 февраля, 2013 · Жалоба Прошёл всего лишь месяц, и у меня дошли руки проверить. LPC1778 (уж что было под рукой, с припаяным лог.анализатором). Один таймер с NVIC_SetPriority(4), другой таймер с NVIC_SetPriority(0). В первом - длительная задержка (в половину его периода) и дрыганье ножкой на входе и выходе. Во втором - также дрыганье ножкой. Кроме EnableIRQ и SetPriority, в проекте больше нет никаких обращений к NVIC'у. Компилятор - кейл. В итоге - дрыг ножкой второго таймера от первого никак не зависит, находится ли тот в прерывании, или нет. Собственно, что и требовалось доказать - NXP люди вменяемые и делают контроллеры, которые работают согласно документации :-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться