Перейти к содержанию
    

OMAP L138. Прерывание по сигналу на GPIO.

Необходимо сгенерировать прерывание по фронту импульса поступающему на одну из ног GPIO и моргнуть светодиодом (ARM ядро OMAP L138).

Выполняю следующий код:

void INTInit(void)
{
unsigned int savePinmux = 0;

/* Enable GPIO */
PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);

/* Read pinmux and clean pins  0[6] */
savePinmux = (HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(1)) & \
					~(SYSCFG_PINMUX1_PINMUX1_7_4));

/* Enable in pinmux pins  0[6] in GPIO 7 */
HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(1)) = \
	(PINMUX1_INT_ENABLE | savePinmux);

/* Set GPIO 7 as input */
GPIODirModeSet(SOC_GPIO_0_REGS, 7, GPIO_DIR_INPUT);

/*
** Configure rising edge and falling edge triggers on pin 7 to generate
** an interrupt
*/
GPIOIntTypeSet(SOC_GPIO_0_REGS, 7, GPIO_INT_TYPE_RISEDGE);

/* Enable interrupts for Bank 0.*/
GPIOBankIntEnable(SOC_GPIO_0_REGS, 0);

/* Configuring the AINTC to handle interrupts.*/
// Setup ARM or DSP interrupt controller
#ifdef _TMS320C6X
	// Initialize the DSP Interrupt Controller
	IntDSPINTCInit();

	// Enable DSP Interrupts Globally
	IntGlobalEnable();
#else
	/* Initialize the ARM Interrupt Controller.*/
	IntAINTCInit();

	 /* Enable IRQ in CPSR.*/
	IntMasterIRQEnable();

	/* Enable the interrupts in GER of AINTC.*/
	IntGlobalEnable();

	/* Enable the interrupts in HIER of AINTC.*/
	IntIRQEnable();
#endif

/* Configure GPIO interrupts */
// Configure GPIO interrupts for ARM or DSP
#ifdef _TMS320C6X
	// Register the ISR in the Interrupt Vector Table
	IntRegister(C674X_MASK_INT0, GPIOIsr);

	// Map the system interrupt to the DSP maskable interrupt
	IntEventMap(C674X_MASK_INT0, SYS_INT_GPIO_B0INT);

	// Enable DSP maskable interrupt
	IntEnable(C674X_MASK_INT0);
#else
	// Register the ISR in the Interrupt Vector Table.
	IntRegister(SYS_INT_GPIOB0, GPIOIsr);

	// Map the channnel number 2 of AINTC to GPIO BANK 0 system interrupt.
	IntChannelSet(SYS_INT_GPIOB0, 2);

	// Enable the System Interrupts for AINTC.
	IntSystemEnable(SYS_INT_GPIOB0);
#endif

}

/*
** \brief   Interrupt Service Routine to be executed on GPIO interrupts.
**		  This disables the bank interrupts, clears the system interrupt
**		  status and pin interrupt status. This also sets flag as 1.
*/
void GPIOIsr(void)
{
/* Disable the interrupts for pins of bank 0 in GPIO.*/
GPIOBankIntDisable(SOC_GPIO_0_REGS, 0);

#ifdef _TMS320C6X
// Clear the system interrupt status in the DSPINTC
IntEventClear(SYS_INT_GPIO_B0INT);
#else
/* Clears the system interrupt status of GPIO in AINTC.*/
IntSystemStatusClear(SYS_INT_GPIOB0);
#endif

/* Clears the Interrupt Status of GP0[6] in GPIO.*/
GPIOPinIntClear(SOC_GPIO_0_REGS, 7);

GPIOPinWrite(SOC_GPIO_0_REGS, 1, GPIO_PIN_HIGH);
GPIOPinWrite(SOC_GPIO_0_REGS, 2, GPIO_PIN_LOW);
GPIOPinWrite(SOC_GPIO_0_REGS, 3, GPIO_PIN_HIGH);
Delay(1000000);
GPIOPinWrite(SOC_GPIO_0_REGS, 2, GPIO_PIN_HIGH);
GPIOPinWrite(SOC_GPIO_0_REGS, 3, GPIO_PIN_LOW);

/* Enable interrupts for pins of bank 0.*/
GPIOBankIntEnable(SOC_GPIO_0_REGS, 0);
}

При этом по приходу прерывания программа слетает куда-то в область 0xfffd45dc. В чём может быть причина?

Изменено пользователем maxis

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При этом по приходу прерывания программа слетает куда-то в область 0xfffd45dc. В чём может быть причина?

Причина может быть в отсутствии у вас таблицы прерываний. У ARM-ядра L137 (и думаю L138) таблица прерываний находится с адреса 0xFFFF0000.

 

PS: Такие длинные портянки кода, как у вас, следует оформлять используя CODEBOX, а не CODE. Чтобы не листать по неск. экранов....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Причина может быть в отсутствии у вас таблицы прерываний. У ARM-ядра L137 (и думаю L138) таблица прерываний находится с адреса 0xFFFF0000.

Нет, таблица прерываний на месте.

Global Prioritized Vector Register = 0x80005D00

Соответственно по адресу 0x80005D00 лежит одна запись 0x80003980.

В дизасемблере вижу что по адресу 0x80003980 находится функция GPIOIsr.

 

PS: Такие длинные портянки кода, как у вас, следует оформлять используя CODEBOX, а не CODE. Чтобы не листать по неск. экранов....

Исправил.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет, таблица прерываний на месте.

Global Prioritized Vector Register = 0x80005D00

Причём здесь Global Prioritized Vector Register???

Вы ещё раз внимательнее перечитайте моё письмо и почитайте в даташите как работает система прерываний в ARM-ядре.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Причём здесь Global Prioritized Vector Register???

Вы ещё раз внимательнее перечитайте моё письмо и почитайте в даташите как работает система прерываний в ARM-ядре.

Таблица на месте. Вот она:

fnRAMVectors
00000000    00000000    00000000    00000000    00000000    00000000    00000000    00000000
00000000    00000000    00000000    00000000    00000000    00000000    00000000    00000000
00000000    00000000    00000000    00000000    00000000    00000000    00000000    00000000
00000000    00000000    00000000    00000000    00000000    00000000    00000000    00000000
00000000    00000000    00000000    00000000    00000000    00000000    00000000    00000000
00000000    00000000    80003980    00000000    00000000    00000000    00000000    00000000
00000000    00000000    00000000    00000000    00000000    00000000    00000000    00000000
00000000    00000000    00000000    00000000    00000000    00000000    00000000    00000000
00000000    00000000    00000000    00000000    00000000    00000000    00000000    00000000
00000000    00000000    00000000    00000000    00000000    00000000    00000000    00000000
00000000    00000000    00000000    00000000    00000000    00000000    00000000    00000000
00000000    00000000    00000000    00000000    00000000    00000000    00000000    00000000
00000000    00000000    00000000    00000000    00000000

Vector base register содержет правильную ссылку на эту таблицу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы совсем не хотите читать то, что я пишу. Тогда зачем спрашиваете если не слушаете советов?

Повторяю ещё раз:

таблица прерываний находится с адреса 0xFFFF0000

И ещё раз:

почитайте в даташите как работает система прерываний в ARM-ядре

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы совсем не хотите читать то, что я пишу. Тогда зачем спрашиваете если не слушаете советов?

Повторяю ещё раз:

таблица прерываний находится с адреса 0xFFFF0000

И ещё раз:

почитайте в даташите как работает система прерываний в ARM-ядре

Где это почитать можно? Я перерыл OMAP-L138 Technical Reference Manual и нигде ни слова по поводу 0xFFFF0000 и что там должно находится.

 

udp

А нет, нашёл что там действительно содержится вектор табле, и на этом всё. Вот что у меня там находится:

0xEAFF7FFE    0xEAFFFFFD    0xEAFFFFFC    0xEAFFFFFB    0xEAFFFFFA    0xEAFFFFF9    0xEAFFFFF8    0xEAFFFFF7

Изменено пользователем maxis

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А нет, нашёл что там действительно содержится вектор табле, и на этом всё. Вот что у меня там находится:

0xEAFF7FFE    0xEAFFFFFD    0xEAFFFFFC    0xEAFFFFFB    0xEAFFFFFA    0xEAFFFFF9    0xEAFFFFF8    0xEAFFFFF7

Вот - уже теплее ;)

Да - это команды переходов на процедуры обработки исключений.

Не знаю, где это описано в документации L138, но в "OMAP-L137 Applications Processor System Reference Guide" (SPRUG84,C) надо см. раздел "2.4 Exceptions and Exception Vectors" - там описано, и вектора FIQ и IRQ, которые вам нужны.

А ещё почитайте описание на ядро ARM926EJ-S - там описано как работает система прерываний в этом ядре.

То, про что Вы писали (контроллер прерываний AINTC), идёт уже после этого и может опционально использоваться для FIQ и IRQ прерываний. Или не использоваться вовсе :)

Вот как у меня описана таблица векторов, которая располагается с адреса 0xFFFF0000:

exceptionsInit: LDR   PC, ___c_int00      ;Reset Interrupt
               LDR   PC, __UND_handler   ;Undefined Instruction Interrupt
               LDR   PC, __SWI_handler   ;Software Interrupt
               LDR   PC, __PAB_handler   ;Prefetch Abort Interrupt
               LDR   PC, __DAB_handler   ;Data Abort Interrupt
               .long 0                   ;Reserved For Future Expansion
               LDR   PC, __IRQ_handler   ;IRQ Interrupt
               LDR   PC, __FIQ_handler   ;FIQ Interrupt
___c_int00      .long _c_int00
__UND_handler   .long UND_handler
__SWI_handler   .long SWI_handler
__PAB_handler   .long PAB_handler
__DAB_handler   .long DAB_handler
     .long 0
__IRQ_handler   .long IRQ_handler
__FIQ_handler   .long FIQ_handler

Вот ISR IRQ (видите где только начинает использоваться GPVR?):

IRQ_handler:    SUBS  LR, LR, #4
               STMFD SP!, {R0-R3, R12, LR}  ;Store registers on IRQ stack
               LDR   R0, AINTC_GPVR         ;R0 contains address of GPVR (which contains ISR address)
               LDR   R1, [R0]               ;R1 contains address of highest prioritized ISR
               ADD   LR, PC, #0             ;Save return address in LR,
               LDR   PC, [R1]               ;Go to ISR (still in IRQ mode), will return to following line
               LDMFD SP!, {R0-R3, R12, PC}^ ;Restore registers from IRQ stack. Return to program current status

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Наткнулся на вашу тему в надежде решить аналогичную проблему. В ОМАР-L137 загружаю DSP (полностью функционален, проблем нет) и затем ARM. Также, как и в этой теме, АРМ работает, все мигает, но прерывания использовать не выходит. В качестве исходника использовал пример с сайта TI http://processors.wiki.ti.com/index.php/Bo...s_for_OMAP-L137

 

В проект АРМ кроме boot.asm, использованного в примере, добавил ARM9_handler, ARM9_intvecs и ARM9_initstack.asm из qCSL примеров. Что интересно, если запускаю через дебаггер, все работает, но если программа загружается из флеш-памяти, АРМ замирает после первого же прерывания. Для АРМа никакого GEL-файла не используется, для DSP- все инициализируется из кода, в GEL все закомментировано. Буду очень признателен, если чего подскажете. Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В проект АРМ кроме boot.asm, использованного в примере, добавил ARM9_handler, ARM9_intvecs и ARM9_initstack.asm из qCSL примеров. Что интересно, если запускаю через дебаггер, все работает, но если программа загружается из флеш-памяти, АРМ замирает после первого же прерывания. Для АРМа никакого GEL-файла не используется, для DSP- все инициализируется из кода, в GEL все закомментировано. Буду очень признателен, если чего подскажете. Спасибо!

После первого прерывания, т.е. - одно выполняется, а потом всё?

Или не выполняется ни одно?

 

Таблицу прерываний ARM-ядра формируете (с адреса 0xFFFF0000)?

Её должно сформировать DSP-ядро перед снятием RESET с ARM-ядра. См. соответствующий раздел мануала по порядку старта ARM-ядра.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, что откликнулись, боялся, что темя уже заброшена :)

 

На ARM я объявил два прерывания: таймер и CHIPSIG (от DSP). Если прерывание от таймера не активировно, то АРМ молотит как угодно долго (мигает светодиодами и мотает счетчик в адресе общей памяти, так, что я могу через DSP считывать значение счетчика). Как только DSP шлет CHIPSIG, АРМ зависает. Если же таймер прерывание активно с самого начала, то и АРМ вырубается моментально.

 

Что касается инициализации АРМа, то я ее скопировал из того самого примера: DSP загружается сам, подает питание на PRUSS, который делает некие таинственные манипуляции, чтобы врубить АРМ, после чего АРМ таки включается и работает, пока не произойдет первое прерывание. К несчастью, через дебаггер все работает нормально, то есть и таймер и CHIPSIG прерывания происходят как и положено, но стоит загрузить программу в флеш, проблема с прерываниями налицо.

 

Не совсем понятно, что имеется в виду под формированием таблицы прерываний через DSP. Получается, boot.asm, ARM9_IRQ_handler.arm,ARM9_intvecs.asm и ARM9_initstack.asm в проекте дла ARM недостаточно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кажется, нащупал причину: возможно, проблема в части кода, загружаемой через PRUSS. Попробую разобраться, что он конкретно делает ( в примере он грузится в виде массива).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не совсем понятно, что имеется в виду под формированием таблицы прерываний через DSP. Получается, boot.asm, ARM9_IRQ_handler.arm,ARM9_intvecs.asm и ARM9_initstack.asm в проекте дла ARM недостаточно?

Не код, а именно таблица векторов прерываний. Т.е. это таблица команд перехода на стартовые адреса ISR.

Для старта ARM-ядра DSP ядро должно сделать:

1. С помощью PRUSS скопировать начальную таблицу векторов прерываний в область с адреса 0xFFFF0000. Сам DSP не может её туда скопировать, так как не имеет доступа к этой области памяти.

2. Снять сигнал RESET c ARM-ядра. После этого ARM-ядро начинает выполнять код начиная с адреса 0xFFFF0000.

 

Начальная таблица векторов прерываний может содержать только валидный переход по 0-му вектору (вектор RESET), в остальных векторах могут быть просто заглушки. Я обычно так делал.

Вот она из моего проекта:

static const u32 codeARM[] = {
 0xE59FF018,                       //vt0: B boot
 0xEAFFFFFE,                       //vt0: Self loop
 0xEAFFFFFE,                       //vt0: Self loop
 0xEAFFFFFE,                       //vt0: Self loop
 0xEAFFFFFE,                       //vt0: Self loop
 0xEAFFFFFE,                       //vt0: Self loop
 0xEAFFFFFE,                       //vt0: Self loop
 0xEAFFFFFE,                       //vt0: Self loop
 RAM_SDRAM_ARM_RX_BEGIN            //jump: DATA:
};

Как видите - прописан только вектор сброса, передающий управление на начало кода (по адресу RAM_SDRAM_ARM_RX_BEGIN).

 

Чтобы в дальнейшем нормально обрабатывать прерывания, ARM-ядро после старта должно проинициализировать таблицу прерываний уже валидными векторами.

Если оставить заглушки, естественно при первом-же прерывании ARM-ядро зациклится в заглушке.

 

PS: Всё это освещено в мануале, в разделе посвящённом старту ARM-ядра.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...