я имею некоторый опыт работы с AVR и теперь пытаюсь освоить ARM. У меня AT91SAM3X8E и IAR EWARM 7.3.
Благодаря вашей помощи мне удалось продвинуться до рабочего проекта, переключающего состояние линии ввода-вывода, при последовательном опросе события сравнения "RC compare" таймера TC0.
Теперь мне нужно заменить последовательный опрос прерыванием, но я пока не понимаю, как это сделать.
На основании изучения немногочисленных примеров и документации у меня сложились такие представления:
1) нужно сказать TC0->TC_CHANNEL->TC_IER|=0x00000010; // Разрешено прерывание RC compare.
2) Нужно установить глобальный флаг маскируемых перрываний, используя, например, intrinsic функцию (-и) "__enable_interrupt();" и/или "__enable_fiq();" (не понимаю пока, какую или обе ) или ассемблерную вставку (типа asm("sei") в AVR)
3) Нужно написать функцию обработчик, причем пока совершенно не понимаю, как она оформляется. Найденные мной примеры инкапсулируют функционал и предлагают подключать некие библиотеки и действовать через функции в этих библиотеках, чего мне совсем не хотелось бы делать на этапе освоения железа.
4) Правильно ли я понимаю, что за всем блоком TC0 закреплено одно и только одно прерывание, а понять, какое конкретное событие (например, сравнение RC или переполнение), возбудило это прерывание можно только анализируя флаги в регистре статуса внутри обработчика этого прерывания? Если это так, то для всех ли ARM Cortex-Mxx это характерно?
Привожу свой рабочий код, который нужно модифицировать:
Код
#define __SAM3X8E__
#include <iosam3xa.h>
#define BITON(X, N) (X)|=(1<<(N))
#define BITOFF(X, N) (X)&=~(1<<(N))
#define GETBIT(X, N) ((X&(1<<(N)))&&1)
void main(){
WDT->WDT_MR=0x00008FFF; //Выключить сторожевой таймер
// Переключаемся на внешний кварц (12МГц)
PMC->CKGR_MOR=0x0137FF01; // Включить внешний кварц 3-20 MHz (у нас 12 MHz) и выключить внутренний RC-генератор
while (!(0x00000001&PMC->PMC_SR)); // Дождаться стабилизации кварца
// Настройка ФАПЧ
PMC->CKGR_PLLAR = 0x200A3F03; // MUL=10, DIV=3 PLLACLK= 12 MHz*(MUL+1)/DIV = 44 MHz (но потом делится пополам в PMC_MCKR - PLLADIV2=1)
while (!(0x00000002&PMC->PMC_SR)); // Дождаться захвата ФАПЧ
// Выбираем вход Master Clock - PLLA без деления. Установка в 2 этапа - сначала смена делителей, потом смена источника такта
PMC->PMC_MCKR=0x00001001; // Выход Master Clock = Main Clock c делителем PLL на 2 (бит PLLADIV2=1)
while (!(0x00000008&PMC->PMC_SR)); // Дождаться установки Master Clock
PMC->PMC_MCKR=0x00001002; // Выход Master Clock = PLLA c делителем PLL на 2 (бит PLLADIV2=1)
while (!(0x00000008&PMC->PMC_SR)); // Дождаться установки Master Clock
PMC->PMC_PCER0=1<<13; // Тактировать PIOC
PMC->PMC_PCER0=1<<27; // Тактировать TC0
PIOC->PIO_OER=1<<12; // PC12 as output pin
PIOC->PIO_ODR=1<<13; // PC13 as input pin
PIOC->PIO_PER=3<<12; // PC12, PC13 as PIO pins
TC0->TC_CHANNEL->TC_RC=1000; // Загружаем регистр сравнения RC (11MHz/1000 =11000 раз в сек событие сравнения RC)
TC0->TC_CHANNEL->TC_CMR=0x0000C4000; // Timer_Clock1 selected (MCK/2=11MHz), Waveform Enabled, Up mode with autotrigger (autoreset) on RC
while (GETBIT(PIOC->PIO_PDSR, 13)); // Ждем, пока не замкнута на GND тактовая кнопка на PC13
TC0->TC_CHANNEL->TC_CCR=0x00000005; //CLKEN=1, SWTRG=1 - RESET+Start
while(1){
if (TC0->TC_CHANNEL->TC_SR&0x00000010){ // Если было сравнение с RC (флаг автоматически сбрасывается после чтения регистра)
if (GETBIT(PIOC->PIO_ODSR, 12)) // переключаем состояние ноги PC12
PIOC->PIO_CODR=1<<12;
else
PIOC->PIO_SODR=1<<12;
}
}
}
#include <iosam3xa.h>
#define BITON(X, N) (X)|=(1<<(N))
#define BITOFF(X, N) (X)&=~(1<<(N))
#define GETBIT(X, N) ((X&(1<<(N)))&&1)
void main(){
WDT->WDT_MR=0x00008FFF; //Выключить сторожевой таймер
// Переключаемся на внешний кварц (12МГц)
PMC->CKGR_MOR=0x0137FF01; // Включить внешний кварц 3-20 MHz (у нас 12 MHz) и выключить внутренний RC-генератор
while (!(0x00000001&PMC->PMC_SR)); // Дождаться стабилизации кварца
// Настройка ФАПЧ
PMC->CKGR_PLLAR = 0x200A3F03; // MUL=10, DIV=3 PLLACLK= 12 MHz*(MUL+1)/DIV = 44 MHz (но потом делится пополам в PMC_MCKR - PLLADIV2=1)
while (!(0x00000002&PMC->PMC_SR)); // Дождаться захвата ФАПЧ
// Выбираем вход Master Clock - PLLA без деления. Установка в 2 этапа - сначала смена делителей, потом смена источника такта
PMC->PMC_MCKR=0x00001001; // Выход Master Clock = Main Clock c делителем PLL на 2 (бит PLLADIV2=1)
while (!(0x00000008&PMC->PMC_SR)); // Дождаться установки Master Clock
PMC->PMC_MCKR=0x00001002; // Выход Master Clock = PLLA c делителем PLL на 2 (бит PLLADIV2=1)
while (!(0x00000008&PMC->PMC_SR)); // Дождаться установки Master Clock
PMC->PMC_PCER0=1<<13; // Тактировать PIOC
PMC->PMC_PCER0=1<<27; // Тактировать TC0
PIOC->PIO_OER=1<<12; // PC12 as output pin
PIOC->PIO_ODR=1<<13; // PC13 as input pin
PIOC->PIO_PER=3<<12; // PC12, PC13 as PIO pins
TC0->TC_CHANNEL->TC_RC=1000; // Загружаем регистр сравнения RC (11MHz/1000 =11000 раз в сек событие сравнения RC)
TC0->TC_CHANNEL->TC_CMR=0x0000C4000; // Timer_Clock1 selected (MCK/2=11MHz), Waveform Enabled, Up mode with autotrigger (autoreset) on RC
while (GETBIT(PIOC->PIO_PDSR, 13)); // Ждем, пока не замкнута на GND тактовая кнопка на PC13
TC0->TC_CHANNEL->TC_CCR=0x00000005; //CLKEN=1, SWTRG=1 - RESET+Start
while(1){
if (TC0->TC_CHANNEL->TC_SR&0x00000010){ // Если было сравнение с RC (флаг автоматически сбрасывается после чтения регистра)
if (GETBIT(PIOC->PIO_ODSR, 12)) // переключаем состояние ноги PC12
PIOC->PIO_CODR=1<<12;
else
PIOC->PIO_SODR=1<<12;
}
}
}