Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вложенные прерывания Cortex M3 (LPC1768)
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
theBMV
Здравствуйте, уважаемые!
Пишу реализацию ПИД-регулятора. МК 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;
}
SSerge
А что с регистром AIRCR и полем PRIGROUP в нём?
Там у кортексов настраиваются группы приоритетов.
theBMV
Цитата(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 при возникновении прерывания по таймеру с высшим приоритетом перехода к его обработчику не происходит никогда.
KnightIgor
Цитата(theBMV @ Dec 28 2012, 10:36) *
У меня в конце каждой функции инициализации периферии стоит установка приоритета и разрешение прерывания. А в конце каждого обработчика снятие ожидания.
Повторюсь: у таймера приоритет - 0, у UART'а - 2. Только почему-то из обработчика UART при возникновении прерывания по таймеру с высшим приоритетом перехода к его обработчику не происходит никогда.

По умолчанию контроллер прерываний не настроен на вложенные прерывания. Для большинства случаев (до 16-ти уровней приоритетов и 16 подгрупп) подойдет вызов NVIC_SetPriorityGrouping(0x03) при инициализации приложения. Функция объявлена и реализована в core_cm3.h (но включать этот заголовок явно не надо, т.к. он включается через аппаратно-зависимый заголовок процессора).
theBMV
Ого! Только что нашел: Appendix: Cortex-M3 user guide в мануале на LPC1768!
Там как раз всё расписано!
Всем спасибо!
esaulenka
Цитата(KnightIgor @ Dec 28 2012, 14:12) *
По умолчанию контроллер прерываний не настроен на вложенные прерывания.


Что-то я не понимаю...
По умолчанию в AIRCR поле "Interrupt priority grouping field" равно нулю. По моим соображениям, это означает, что приоритеты прерываний - это именно priority, а не subpriority. Т.е. количество вложенных прерываний может быть максимальным.

Ссылку на infocenter.arm.com дать не могу - никак не найду, где её там взять :-)

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

Да, именно так. Я, помнится, тоже когда читал этот тред, удивился. Но раз заработало, то и ладноsm.gif
esaulenka
Может, нам theBMV расскажет, что у него за компилятор? И даже стартапы все покажет? :-)

Кейл по умолчанию делает только инициализацию стеков, включает питание на периферию и настраивает PLL.
Тут, кажется, IAR, и там, может, есть настройки NVIC ?
SSerge
Цитата(esaulenka @ Jan 16 2013, 17:28) *
По умолчанию в AIRCR поле "Interrupt priority grouping field" равно нулю. По моим соображениям, это означает, что приоритеты прерываний - это именно priority, а не subpriority. Т.е. количество вложенных прерываний может быть максимальным.

Так-то оно так, но если используется не 8, а только 4 бита под приоритеты непонятно как интерпретировать значения 0, 1 и 2 в этом поле.
Нигде определённо этого не сказано.
Могли для экономии вентилей сделать "как получится".
AHTOXA
Цитата(SSerge @ Jan 16 2013, 23:10) *
Так-то оно так, но если используется не 8, а только 4 бита под приоритеты непонятно как интерпретировать значения 0, 1 и 2 в этом поле.

Они все эквивалентны значению 0. (Потому что различия между этими вариантами приходятся на не-имплементированные биты приоритета).
theBMV
Цитата(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
AHTOXA
Цитата(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 смогли переделать ядро? Сильно сомневаюсь.
esaulenka
Прошёл всего лишь месяц, и у меня дошли руки проверить.

LPC1778 (уж что было под рукой, с припаяным лог.анализатором).

Один таймер с NVIC_SetPriority(4), другой таймер с NVIC_SetPriority(0).
В первом - длительная задержка (в половину его периода) и дрыганье ножкой на входе и выходе.
Во втором - также дрыганье ножкой.
Кроме EnableIRQ и SetPriority, в проекте больше нет никаких обращений к NVIC'у. Компилятор - кейл.

В итоге - дрыг ножкой второго таймера от первого никак не зависит, находится ли тот в прерывании, или нет.

Собственно, что и требовалось доказать - NXP люди вменяемые и делают контроллеры, которые работают согласно документации :-)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.