Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC2294 + IAR + Прерывания
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Diablo
Добрый вечер!

Решил разобраться с работой прерываний на МК LPC 2294. Начал с самого простого - взял готовый пример поставляемый вместе со средой разработки, но он к сожалению оказался нерабочим. Выяснилось, что не работают прерывания, т.к. если убрать обработчики прерываний и формировать задержку простым счетом , то пример работает.

В связи с этим у меня возникли несколько вопросов:

1) Почему не работают прерывания, в чем может быть причина?
2) Может быть что-то неправильно проинициализировано (не инициализировано вообще) для обработки прерываний в файле startup.s?
3) Можно ли обойтись в проекте без файла startup.s. (вопрос возник т.к. в прилагаемом проекте он отсутствовал).
Возможно при сборке проекта прилинковывается стандартный файл в каталоге со средой, но подходит ли он для моего процессора?

Насколько мне известно, в файле startup.s находится таблица векторов исключительных ситуаций и в нем же производится
инициализация указателей стек для различных режимов работы, настройка какой-либо периферии (опционально), ну и передача
управления функции main. Вместо файла начальной инициализации в настройках проекта указан файл с
расширением *.icf (Linker configuration file), в котором указано расположение векторов исключительных ситуаций и размеры стеков.
Может ли этот файл заменить startup код или же придется писать его ручками?

4) Если нет, то где можно подчерпнуть информацию по его написанию?
В Keil всё очень просто и структура файла довольно понятна, да и в книге Тревора Мартина все подробно описано, а вот в IAR
мне не совсем понятно как это делается.

Заранее благодарю за ответ

P.S. В качестве среды разработки используется IAR EWARM
mempfis_
Возьмите стартап и icf файл из примеров иара для вашего семейства процессоров. стартап пдключите к проекту, а в настройках линкера укажите путь к icf-файлу. Там же в примерах найдёте примеры инициализации VIC, инсталляции прерываний и их обработки.
Diablo
Собственно это я и сделал в первую очередь, весь код взят из примеров IARа, но в итоге прошивка работать не хочет.
mempfis_
Цитата(Diablo @ Apr 16 2012, 20:14) *
Собственно это я и сделал в первую очередь, весь код взят из примеров IARа, но в итоге прошивка работать не хочет.


Выложите чтоли пример проекта который у Вас не идёт.
Diablo
Вот код основной программы

CODE
int main (void)
{
// System initialization, this will map the exception vectors.
LPC2294SystemInit();

// Set up peripheral registers.
LPC2294InitPIO();

// First disable interrupts.
__disable_interrupt();

// Setup interrupt controller.
LPC2294InitVIC();
LPC2294InitTimerInterrupt(TimerBeat);

// Periodic timer initialization.
LPC2294InitTimer();

// Enable interrupts.
__enable_interrupt();

// Start periodic timer.
LPC2294StartTimer();

// Loop forever.
for (;;)
{
LPC2294LedSet();
Sleep(200); // Display for 65 ms.
LPC2294LedClear();
Sleep(200); // Display for 65 ms.
}
}


Вот, что касается обработки прерываний
CODE

static void (*timer_function)(void);

static void TimerInterrupt(void)
{
(*timer_function)(); // Call timer callback function.

T0IR = 0xff; // Clear timer 0 interrupt line.
}

__irq __arm void irq_handler(void)
{
void (*interrupt_function)();
unsigned int vector;

vector = VICVectAddr; // Get interrupt vector.
interrupt_function = (void(*)())vector;
(*interrupt_function)(); // Call vectored interrupt function.

VICVectAddr = 0; // Clear interrupt in VIC.
}

void LPC2294InitVIC()
{
// Setup interrupt controller.
VICProtection = 0;
// Disable all interrupts
VICIntEnClear = 0xffffffff;
VICDefVectAddr = (unsigned int)&DefDummyInterrupt;
}

void LPC2294InitTimerInterrupt(void(*timer_func)())
{
// Setup timer callback function.
timer_function = timer_func;

VICIntSelect &= ~VIC_TIMER0_bit; // IRQ on timer 0 line.
VICVectAddr1 = (unsigned int)&TimerInterrupt;
VICVectCntl1 = 0x20 | VIC_TIMER0; // Enable vector interrupt for timer 0.
VICIntEnable = VIC_TIMER0_bit; // Enable timer 0 interrupt.
}

static volatile int ms_ctr = 0;

// Timer interrupt callback
void TimerBeat(void)
{
// Called at 1000 Hz rate.
ms_ctr++; // Sleep counter.
}

void Sleep(int milliseconds)
{
while (ms_ctr < milliseconds) ;
ms_ctr = 0;
}


Файл конфигурации линкера
CODE
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00000080;
define symbol __ICFEDIT_region_ROM_end__ = 0x0003FDFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x40000040;
define symbol __ICFEDIT_region_RAM_end__ = 0x40003FDF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x2000;
define symbol __ICFEDIT_size_svcstack__ = 0x10;
define symbol __ICFEDIT_size_irqstack__ = 0x100;
define symbol __ICFEDIT_size_fiqstack__ = 0x0;
define symbol __ICFEDIT_size_undstack__ = 0x0;
define symbol __ICFEDIT_size_abtstack__ = 0x0;
define symbol __ICFEDIT_size_heap__ = 0x1000;
/**** End of ICF editor section. ###ICF###*/

define symbol __CRP_start__ = 0x000001FC;
define symbol __CRP_end__ = 0x00000204;/*0x000001FF*/

/* Memory used by RealMonitor*/
define symbol __RM_start__ = 0x40000040;
define symbol __RM_end__ = 0x4000011F;

define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__] - mem:[from __CRP_start__ to __CRP_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__] - mem:[from __RM_start__ to __RM_end__];
define region CRP_region = mem:[from __CRP_start__ to __CRP_end__];

define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block SVC_STACK with alignment = 8, size = __ICFEDIT_size_svcstack__ { };
define block IRQ_STACK with alignment = 8, size = __ICFEDIT_size_irqstack__ { };
define block FIQ_STACK with alignment = 8, size = __ICFEDIT_size_fiqstack__ { };
define block UND_STACK with alignment = 8, size = __ICFEDIT_size_undstack__ { };
define block ABT_STACK with alignment = 8, size = __ICFEDIT_size_abtstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };

initialize by copy { readwrite };
do not initialize { section .noinit };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };

place in ROM_region { readonly };
place in RAM_region { readwrite,
block CSTACK, block SVC_STACK, block IRQ_STACK, block FIQ_STACK,
block UND_STACK, block ABT_STACK, block HEAP };
place in CRP_region { section .crp };


Файл startup.s
CODE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Part one of the system initialization code,
;; contains low-level
;; initialization.
;;
;; Copyright 2006 IAR Systems. All rights reserved.
;;
;; $Revision: 47021 $
;;

MODULE ?cstartup

;; Forward declaration of sections.
SECTION IRQ_STACK:DATA:NOROOT(3)
SECTION FIQ_STACK:DATA:NOROOT(3)
SECTION ABT_STACK:DATA:NOROOT(3)
SECTION SVC_STACK:DATA:NOROOT(3)
SECTION UND_STACK:DATA:NOROOT(3)
SECTION CSTACK:DATA:NOROOT(3)

;
; The module in this file are included in the libraries, and may be
; replaced by any user-defined modules that define the PUBLIC symbol
; __iar_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.

SECTION .intvec:CODE:NOROOT(2)

PUBLIC __vector
PUBLIC __vector_0x14
PUBLIC __iar_program_start
EXTERN irq_handler,fiq_handler

ARM
__vector:
;;
ldr pc,[pc,#+24] ;; Reset
B . ;; Undefined instructions
B . ;; Software interrupt (SWI/SVC)
B . ;; Prefetch abort
B . ;; Data abort
__vector_0x14:
DC32 0 ;; RESERVED
ldr pc,[pc,#+24] ;; IRQ
ldr pc,[pc,#+24] ;; FIQ

DC32 __iar_program_start ;; Reset
DC32 0 ;; Undefined instructions
DC32 0 ;; Software interrupt (SWI/SVC)
DC32 0 ;; Prefetch abort
DC32 0 ;; Data abort
DC32 0 ;; RESERVED
DC32 irq_handler ;; IRQ
DC32 fiq_handler ;; FIQ

; --------------------------------------------------
; ?cstartup -- low-level system initialization code.
;
; After a reser execution starts here, the mode is ARM, supervisor
; with interrupts disabled.
;



SECTION .text:CODE:NOROOT(2)

; PUBLIC ?cstartup
EXTERN ?main
REQUIRE __vector

ARM

__iar_program_start:
?cstartup:

;
; Add initialization needed before setup of stackpointers here.
;
; LPC2148 Errata
; Date: August 5, 2005
; Document Release: Version 1.0
; Device Affected: LPC2148
; Incorrect read of data from SRAM after Reset and MAM is not enabled or partially enabled MAM.1
; Init MAM before acsses to SRAM
MAMCR DEFINE 0xE01FC000 ; MAM Control Register
MAMTIM DEFINE 0xE01FC004 ; MAM Timing register

ldr r0,=MAMCR
ldr r1,=MAMTIM
ldr r2,=0
str r2,[r0]
ldr r2,=7
str r2,[r1]
ldr r2,=2
str r2,[r0]

;
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
;
; --------------------
; Mode, correspords to bits 0-5 in CPSR

MODE_MSK DEFINE 0x1F ; Bit mask for mode bits in CPSR

USR_MODE DEFINE 0x10 ; User mode
FIQ_MODE DEFINE 0x11 ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12 ; Interrupt Request mode
SVC_MODE DEFINE 0x13 ; Supervisor mode
ABT_MODE DEFINE 0x17 ; Abort mode
UND_MODE DEFINE 0x1B ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F ; System mode

mrs r0,cpsr ; Original PSR value
bic r0,r0,#MODE_MSK ; Clear the mode bits
orr r0,r0,#SVC_MODE ; Set Supervisor mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(SVC_STACK) ; End of SVC_STACK

bic r0,r0,#MODE_MSK ; Clear the mode bits
orr r0,r0,#ABT_MODE ; Set Abort mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(ABT_STACK) ; End of ABT_STACK

bic r0,r0,#MODE_MSK ; Clear the mode bits
orr r0,r0,#UND_MODE ; Set Undefined mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(UND_STACK) ; End of UND_STACK

bic r0,r0,#MODE_MSK ; Clear the mode bits
orr r0,r0,#FIQ_MODE ; Set FIR mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(FIQ_STACK) ; End of FIR_STACK

bic r0,r0,#MODE_MSK ; Clear the mode bits
orr r0,r0,#IRQ_MODE ; Set IRQ mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(IRQ_STACK) ; End of IRQ_STACK

bic r0,r0,#MODE_MSK ; Clear the mode bits
orr r0,r0,#SYS_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(CSTACK) ; End of CSTACK


#ifdef __ARMVFP__
; Enable the VFP coprocessor.
mov r0, #0x40000000 ; Set EN bit in VFP
fmxr fpexc, r0 ; FPEXC, clear others.

; Disable underflow exceptions by setting flush to zero mode.
; For full IEEE 754 underflow compliance this code should be removed
; and the appropriate exception handler installed.
mov r0, #0x01000000 ; Set FZ bit in VFP
fmxr fpscr, r0 ; FPSCR, clear others.
#endif

; Add more initialization here


; Continue to ?main for more IAR specific system startup

ldr r0,=?main
bx r0

#ifndef __RAM_DEBUG
SECTION .crp:CODE:ROOT(2)
DATA
/* Code Read Protection
CRP 0x87654321 - Read Memory is disabled.
- Write to RAM is disabled.
- Go command is disabled.
- Copy RAM to Flash is disabled.
- JTAG is disabled.
*/
DCD 0xFFFFFFFF
#endif

END



mempfis_
Сравнил lpc22 с lpc23/lpc17 (с которыми я работал) - есть существенные отличия.

Если предположить что код из примера рабочий, то уточните вот что.
В процедуре
Код
// System initialization.
//
void LPC2294SystemInit(void)
{
#ifdef iRAM
  MEMMAP = 2;             // Map interrupt vectors to internal ram
#else
#ifdef iFLASH             // Map interrupt vectors to internal flash
  MEMMAP = 1;
#else
  BCFG0 = 0x20003CE3;     // BCFG0: Flash Bus Configuration
  BCFG1 = 0x20003CE3;     // BCFG1: Ram Bus Configuration
  PINSEL2 = 0x0E6149E4;   // PINSEL2: CS0, CS1, CS2, OE, WE, BLS0..3, D0..31, A2..23, JTAG
#ifdef xFLASH
  MEMMAP = 3;             // Map interrupt vectors to the first external device (flash in this case)
#else
  MEMMAP = 2;             // Map interrupt vectors to internal ram for debugging from external ram
#endif
#endif
#endif
}


производится отображение таблицы векторов на flash или ram. Вы определили константу iFLASH тобы все ваши вектора были отображены на flash?
в icf файле вроде ничего криминального нет - размер flash/ram соответствует lpc2294, также размер стека достаточный.
Стартап вроде нормальный. Могу предложить вообще удалить его из проекта - пусть иар подставит дефолтный для данного семейства.


Привожу для сравнения стартап для lpc23xx
CODE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Part one of the system initialization code,
;; contains low-level
;; initialization.
;;
;; Copyright 2006 IAR Systems. All rights reserved.
;;
;; $Revision: 30870 $
;;

MODULE ?cstartup

;; Forward declaration of sections.
SECTION IRQ_STACK:DATA:NOROOT(3)
SECTION FIQ_STACK:DATA:NOROOT(3)
SECTION SVC_STACK:DATA:NOROOT(3)
SECTION ABT_STACK:DATA:NOROOT(3)
SECTION UND_STACK:DATA:NOROOT(3)
SECTION CSTACK:DATA:NOROOT(3)

;
; The module in this file are included in the libraries, and may be
; replaced by any user-defined modules that define the PUBLIC symbol
; __iar_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.

SECTION .intvec:CODE:NOROOT(2)

PUBLIC __vector
PUBLIC __iar_program_start
PUBLIC __vector_0x14

EXTERN undef_handler, swi_handler, prefetch_handler
EXTERN data_handler, irq_handler, fiq_handler
ARM ; Always ARM mode after reset
__vector:
ldr pc,[pc,#24] ; Absolute jump can reach 4 GByte
__undef_handler:
ldr pc,[pc,#24] ; Branch to undef_handler
__swi_handler:
ldr pc,[pc,#24] ; Branch to swi_handler
__prefetch_handler:
ldr pc,[pc,#24] ; Branch to prefetch_handler
__data_handler
ldr pc,[pc,#24] ; Branch to data_handler
__vector_0x14
dc32 0xFFFFFFFF
__irq_handler:
ldr pc,[pc, #-0x0120] ; Branch to irq_handler
__fiq_handler:
ldr pc,[pc,#24] ; Branch to fiq_handler

; Constant table entries (for ldr pc) will be placed at 0x20
dc32 __iar_program_start
dc32 __undef_handler
dc32 __swi_handler
dc32 __prefetch_handler
dc32 __data_handler
dc32 0xFFFFFFFF
dc32 0xFFFFFFFF
dc32 __fiq_handler

; --------------------
; Mode, correspords to bits 0-5 in CPSR

MODE_MSK DEFINE 0x1F ; Bit mask for mode bits in CPSR

USR_MODE DEFINE 0x10 ; User mode
FIQ_MODE DEFINE 0x11 ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12 ; Interrupt Request mode
SVC_MODE DEFINE 0x13 ; Supervisor mode
ABT_MODE DEFINE 0x17 ; Abort mode
UND_MODE DEFINE 0x1B ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F ; System mode

CP_DIS_MASK DEFINE 0xFFFFFFF2

SECTION .text:CODE:NOROOT(2)

EXTERN ?main
REQUIRE __vector
EXTERN low_level_init

ARM

__iar_program_start:
?cstartup:

I_Bit DEFINE 0x80 ; when I bit is set, IRQ is disabled
F_Bit DEFINE 0x40 ; when F bit is set, FIQ is disabled

#define VIC_INT_ENABLE 0xFFFFF014
; Disable all interrupts
ldr r0,=VIC_INT_ENABLE
mov r1,#0xFFFFFFFF
str r1,[r0]

; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.

mrs r0,cpsr ; Original PSR value
bic r0,r0,#MODE_MSK ; Clear the mode bits
orr r0,r0,#SVC_MODE ; Set Supervisor mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(SVC_STACK) ; End of SVC_STACK

bic r0,r0,#MODE_MSK ; Clear the mode bits
orr r0,r0,#UND_MODE ; Set Undefined mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(UND_STACK) ; End of UND_MODE

bic r0,r0,#MODE_MSK ; Clear the mode bits
orr r0,r0,#ABT_MODE ; Set Data abort mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(ABT_STACK) ; End of ABT_STACK

bic r0,r0,#MODE_MSK ; Clear the mode bits
orr r0,r0,#FIQ_MODE ; Set FIR mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(FIQ_STACK) ; End of FIQ_STACK

bic r0,r0,#MODE_MSK ; Clear the mode bits
orr r0,r0,#IRQ_MODE ; Set IRQ mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(IRQ_STACK) ; End of IRQ_STACK

bic r0,r0,#MODE_MSK | I_Bit | F_Bit ; Clear the mode bits
orr r0,r0,#SYS_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
ldr sp,=SFE(CSTACK) ; End of CSTACK

#ifdef __ARMVFP__
; Enable the VFP coprocessor.
mov r0, #BASE_ARD_EIM ; Set EN bit in VFP
fmxr fpexc, r0 ; FPEXC, clear others.

; Disable underflow exceptions by setting flush to zero mode.
; For full IEEE 754 underflow compliance this code should be removed
; and the appropriate exception handler installed.
mov r0, #0x01000000 ; Set FZ bit in VFP
fmxr fpscr, r0 ; FPSCR, clear others.
#endif

; Add more initialization here


; Continue to ?main for more IAR specific system startup

ldr r0,=?main
bx r0

END


Diablo
Отображение векторов производится на Flash

Что касается удаления startup из проекта, то изначально его там и не было. Подставить решил, когда начал проверять работу прерываний, но эффекта все равно никакого нет.
Diablo
Что-то я вообще ничего не понимаю!

Зашил сегодня программу через JTAG и проследил выполнение по шагам - всё работает как надо. Но стоит только отключить JTAG и перезагрузить МК, программа работать перестаёт. Такое ощущение, что управление пользовательской программе не передаётся.

Возможно задам глупый вопрос, но можно ли через JTAG посмотреть, куда попадает программа сразу после сброса?
esaulenka
Цитата
Такое ощущение, что управление пользовательской программе не передаётся.


Если у меня складывается такое ощущение, я первым делом проверяю, не попал ли контроллер в бут (флешмэджиком). Помогало неоднократно :-)

Если оно так и есть, проверьте контрольную сумму (подробности - в user manual, искать "Criterion for valid user code") и уровень на соответствующей ноге.


Цитата
Возможно задам глупый вопрос, но можно ли через JTAG посмотреть, куда попадает программа сразу после сброса?

Глупый или нет, но я ответ не знаю. У меня (keil) при старте отладки просто выставляет program counter = 0, и всё работает вне зависимости от загрузчика. Как посмотреть, что там с "настоящим" резетом, непонятно.

Хотя нет, вру. В настройках отладчика есть выбор сброса контроллера. Возможно, какие-то варианты дадут нужный Вам результат.
Diablo
Цитата
Если у меня складывается такое ощущение, я первым делом проверяю, не попал ли контроллер в бут (флешмэджиком). Помогало неоднократно :-)

А можете в двух словах объяснить как это сделать или дать ссылку на документацию по Flash Magic? Просто никогда им не пользовался sm.gif

И ещё, такое "непонятное" поведение микроконтроллера наблюдается только тогда, когда включаю обработку прерываний, если их убрать, то прошивка грузится и работает. Если же добавить код хотя бы инициализации VIC, то работать перестаёт. Т.е если бы контроллер попадал в бут или была бы неправильная КС, то прошивка не работала бы в обоих случаях. Или я не прав?
esaulenka
FlashMagic - это утилита для прошивки NXP'шных контроллеров через UART с помощью встроенного бутлоадера.
Скачать можно по первой же ссылке в гугле.


Цитата
...такое поведение наблюдается только тогда...

Тогда, действительно, моя теория несостоятельна.

Надо разбираться, что там по вектору IRQ лежит. Видимо, контроллер с первым же прерыванием улетает "не туда".
А под JTAG'ом прерывания работают? Странно, вроде б должно быть одинаково.
Diablo
Посмотрел я сегодня что и как располагается в памяти и вроде бы всё на своих местах.

Вот таблица исключительных ситуаций, начинается как ей и положено с 0 адреса
CODE

0x0: 0xe59ff018 LDR PC, [PC, #0x18] ; [0x20] ?cstartup
0x4: 0xeafffffe B 0x4
0x8: 0xeafffffe B 0x8
0xc: 0xeafffffe B 0xc
FIQ_MODE:
USR_MODE:
0x10: 0xeafffffe B FIQ_MODE ; 0x10
__vector_0x14:
0x14: 0xa3202fc0 [ARM instr]
0x18: 0xe59ff018 LDR PC, [PC, #0x18] ; [0x38] irq_handler
0x1c: 0xe59ff018 LDR PC, [PC, #0x18] ; [0x3c] fiq_handler
0x20: 0x00000284 ANDEQ R0, R0, R4, LSL #5
0x24: 0x00000000 ANDEQ R0, R0, R0
0x28: 0x00000000 ANDEQ R0, R0, R0
0x2c: 0x00000000 ANDEQ R0, R0, R0
0x30: 0x00000000 ANDEQ R0, R0, R0
0x34: 0x00000000 ANDEQ R0, R0, R0
0x38: 0x00000080 ANDEQ R0, R0, R0, LSL #1
0x3c: 0x000000b8 STRHEQ R0, [R0], -R8


После рестарта выполняем инструкцию PC, [PC, #0x18], т.е загружаем в PC значение, находящееся по адресу 0х20.
При возникновении прерывания переходим к выполнению функции по адресу 0х80.

По 284 адресу у меня находится startup, а по 80 функция-обработчик прерывания
CODE

__irq __arm void irq_handler(void)
{
irq_handler:
0x80: 0xe24ee004 SUB LR, LR, #4
0x84: 0xe92d503f PUSH {R0-R5, R12, LR}
vector = VICVectAddr; // Get interrupt vector.
.....

?cstartup:
__iar_program_start:
0x284: 0xe59f0084 LDR R0, _?0 ; MAMCR
ldr r1,=MAMTIM
0x288: 0xe59f1084 LDR R1, _?1 ; MAMTIM
ldr r2,=0
.....


Сравнивал дизассемблированный код, работающий под JTAG и файл прошивки, который заливал Flash Magic-ом и они совпадают.

Поправьте меня пожалуйста если я что неправильно сказал, все-таки я совсем новичок в этом деле. Не может же быть чтобы все было правильно, но программа не работала.

esaulenka
Я ни разу не видел IAR ARM. Покажите, пожалуйста, irq_handler. Просто интересно.

А в остальном... Наверное, кто-то затирает MEMMAP, и в случае прерывания всё пропадает. Почему под JTAG'ом это не происходит, не знаю.
Попробуйте опросить MEMMAP прямо перед разрешением прерывания. Там должна быть единичка.


Разглядывал даташит "по диагонали", и не разобрался, что за ноги BOOT0/BOOT1. С ними всё правильно? Хотя, по идее, в противном случае совсем бы не работало.

И дурацкий вопрос: другое прерывание пробовали?

Вот ещё:
Цитата
define symbol __ICFEDIT_region_RAM_start__ = 0x40000040;
define symbol __ICFEDIT_region_RAM_end__ = 0x40003FDF;

В даташите указан диапазон 0x40000000 - 0x40002FFF. Если первое значение как-то пофиг (хотя зачем закладывать место на ремап векторов, если этого не делать?), то со вторым явный косяк.


И ещё чЮдная цитата из errata:
Pin TD1 (pin 22, H2) must not be driven LOW during reset. If LOW on reset the device behavior is undetermined.
Diablo
Вот пожалуйста sm.gif
CODE

__irq __arm void irq_handler(void)
{

void (*interrupt_function)();
unsigned int vector;

vector = VICVectAddr; // Get interrupt vector.
interrupt_function = (void(*)())vector;
(*interrupt_function)(); // Call vectored interrupt function.

VICVectAddr = 0; // Clear interrupt in VIC.

}


Насчет MEMMAP не знаю, надо будет посмотреть.

Другое прерывание пробовал, та же история.

А почему 0x40002FFF? В доках на микроконтроллер 0x40003FFF верхняя граница.
esaulenka
Цитата
А почему 0x40002FFF? В доках на микроконтроллер 0x40003FFF верхняя граница.

Потому что я не задумываясь привёл цифру из UserManual, Table 17. LPC21xx and LPC22xx memory and peripheral configuration.
Там десяток опечаток - для всех контроллеров с 16 килобайт ОЗУ указано это значение.
Если верить на слово, что там всё-таки 16 килобайт, то Ваша цифра правильнее.

А обработчик прерывания у IAR'а дурацкий :-)
Кейл даёт следующий стартап:
Код
; Exception Vectors  Mapped to Address 0.
;  Absolute addressing mode must be used.
Vectors         LDR     PC, Reset_Addr        
                LDR     PC, Undef_Addr
                LDR     PC, SWI_Addr
                LDR     PC, PAbt_Addr
                LDR     PC, DAbt_Addr
                NOP                           ; Reserved Vector
                LDR     PC, [PC, #-0x0FF0]    ; Vector from VicVectAddr
                LDR     PC, FIQ_Addr

В этом случае сразу же одной командой загружается адрес прерывания из соответствующего регистра (он не просто так расположен в самом конце адресного пространства!). VICVectAddr = 0; в конце прерывания надо делать самостоятельно.
Diablo
Keil вообще намного проще для освоения для новичка, как мне кажется.

Но ничего не поделаешь, надо пользоваться IARом sm.gif
esaulenka
Ну попробуйте переделать эту Вашу программу на кейл, может, проблема и всплывёт...
mempfis_
Проверил адреса VIC/TIM0/GPIO0 - совпадают с lpc23xx
Немного отличий в VIC - в lpc2294 меньше векторов прерываний
Слегка подкорректировал VIC (надеюсь всё исправил правильно).
Подкорректировал файл линкера под размер памяти в lpc2294
Убрал инициализацию PLL (не проверял, но думаю должно работать от встроенной RC-цепочки на 4 МГц)
Светодиод вывел на GPIO0 пин 2 (как в примере)

Скидываю Вам проект под iar5.40
У меня есть книга на английском Мартина Тревора - там описана организация векторных и невекторных прерываний. Но она весит 10МБ. Если у Вас нет могу скинуть по частям.

book

.

.
Diablo
To mempfis_

Спасибо огромное, обязательно попробую этот пример.
Что касается книги, то сам начал её недавно читать, очень доступно написано, кстати есть уже и на русском языке.

To esaulenka
Цитата
Ну попробуйте переделать эту Вашу программу на кейл, может, проблема и всплывёт...

Пробовал, проекты отличались только стартапом. Переносил недостающие части и Кейловского файла в свой, но увы...

Цитата
Наверное, кто-то затирает MEMMAP

И вы совершенно правы sm.gif Сегодня посмотрел JTAGом содержимое регистров после рестарта микроконтроллера. Значение MEMMAP = 3, т.е. режим использование внешней памяти, после записи в него 1 программа продолжает работу. Только мне в связи с этим непонятен один момент, если сразу после рестарта происходит ремап векторов во внешнюю память, то почему без проблем выполняется программа без использования прерываний?
mempfis_
Цитата(Diablo @ Apr 20 2012, 17:47) *
И вы совершенно правы sm.gif Сегодня посмотрел JTAGом содержимое регистров после рестарта микроконтроллера. Значение MEMMAP = 3, т.е. режим использование внешней памяти, после записи в него 1 программа продолжает работу. Только мне в связи с этим непонятен один момент, если сразу после рестарта происходит ремап векторов во внешнюю память, то почему без проблем выполняется программа без использования прерываний?


При работе без прерываний не возникает исключительных ситуаций (FIQ, IRQ, Data Abort (пусть меня поправят гуру)), поэтому всё работет.

У меня есть книга Тревора на русском в печатном виде. Но сам я пользуюсь в основном user manualи подглядываю в примеры.
Diablo
Цитата
При работе без прерываний не возникает исключительных ситуаций (FIQ, IRQ, Data Abort (пусть меня поправят гуру)), поэтому всё работет


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