Прерывания в ARM-GCC (или опять LPC)

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Russian to

Threaded View
Здравствуйте!

Есть gcc version 3.4.0-macraigor1 и упорный камень LPC2106

Тема: "Опять 25" поморгать светиком по прерыванию таймера.

?нужны ли какие нибудь __attribute__ обработчику прерывания таймера
void TIMER0_ISR  (void); и как их корректно записать.
ИНХО как минимум нужно сказать компилятору что данная подпрограмма работает
в режиме ARM.

Не моргает зараза :-( А вот если не делать ENABLE_INTERRUPTS
и не настроивать VIC, и в основном бесконечном цикле проверять
флаг прерывания таймера то усё моргает как надо, то есть инициализация
таймера прошла без косяков.

?на счёт __attribute__ мануалы курил, смотрел исходники arm.c но
не понятен синтаксис, можно ли прописывать несколько атрибутов и как это
делать
(совершенно нет ярких примеров, а интернету потрачено на поиск экзампелей -
уйма)
Во всех ли случаях __attribute__ заменяет #pragma? особенно что касается
обработчиков прерываний, и указаний какой код генерить arm/thumb/interwork.

Код приводится полностью.
Запускается из RAM, ремап делается... ну что ещё нужно?!

/**********************************************************/
void Initialize(void);
void feed(void);
void Timer0_IRQ_Init (void);
void Timer0_Init(void);
void LPC210xInitVIC(void);

void IRQ_Routine (void)   __attribute__ ((interrupt("IRQ")));
void FIQ_Routine (void)   __attribute__ ((interrupt("FIQ")));
void SWI_Routine (void)   __attribute__ ((interrupt("SWI")));
void UNDEF_Routine (void) __attribute__ ((interrupt("UNDEF")));
void TIMER0_ISR  (void);
void DefDummyInterrupt(void);

#include "LPC210x.h"

#define ENABLE_INTERRUPTS   asm volatile (                      \
                                          "mrs r3,cpsr;"        \
                                          "bic r3,r3,#0xC0;"    \
                                          "msr cpsr,r3"         \
                                          :                     \
                                          :                     \
                                          : "r3"                \
                                         )

int main (void) {
  // Initialize the system
  Initialize();
  Timer0_Init();
  Timer0_IRQ_Init();
  ENABLE_INTERRUPTS;

  IODIR |= 0x0000FFFF;
 
  while (1) {
/* Если раскоментарить нижнюю строку,
   но при инициализвции не разрешать прерывания,
   то светик буде моргать, значит прерывания от таймера всётаки генерятся.
*/
    //if (TIMER0_IR !=0) ;
  }
}

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

#define PLOCK 10<<1
void Initialize(void)  {
  PLLCFG=0x25;
  feed();
  PLLCON=0x1;
  feed();
  while(!(PLLSTAT & PLOCK)) ;
  PLLCON=0x3;
  feed();
// Enabling MAM and setting number of clocks used for Flash memory fetch (4
cclks in this case)
  MAMCR=0x2;
  MAMTIM=0x3;
/* Initialize MEMAP - re-map vector table to RAM */
  MEMMAP = 0x02;
  VPBDIV=0x1;
  LPC210xInitVIC();
}

void feed(void)

// Timer interrupt handler
void TIMER0_ISR(void)
{
  static unsigned char i=0;
  if ((i=!i)==0)
    
  else
    ;
  
  TIMER0_IR = 0xff; // Clear timer 0 interrupt line.
}

//XTAL frequency in Hz
#define XTALFREQ 11059200 * 6 //66355200

//pclk must always be XTALFREQ/4 when using the ROM monitor.
#define PCLKFREQ (XTALFREQ/4)
#define Delay_ms  = 1000
#define Delay_HEX = - Delay_ms / PCLKFREQ
#define TIMER0_START (TIMER0_TCR = 1)

void Timer0_Init(void)
{
  IOSET = 0xFFFF;// red led on    
  TIMER0_TCR = TIMER0_PC = TIMER0_CCR = TIMER0_EMR = 0;/*
  TIMER0_MR0 = 0x0024E1C0;
  TIMER0_MCR = 3; // Reset and interrupt on MR0 (match register 0).
  TIMER0_START;
}

#define VIC_TIMER0_bit (1 << VIC_TIMER0)
void Timer0_IRQ_Init (void){
  VICIntSelect &= ~VIC_TIMER0_bit; // IRQ on timer 0 line.
  VICVectAddr0 = (unsigned int)&TIMER0_ISR;
  VICVectCntl0 = 0x20 | VIC_TIMER0; // Enable vector interrupt for timer 0.*/
  VICIntEnable |= 0xFFFF;//VIC_TIMER0_bit; // Enable timer 0 interrupt.
}

void IRQ_Routine (void) {
  unsigned int vector = VICVectAddr;
  void (*interrupt_function)() = (void(*)())vector;
  (*interrupt_function)();
  VICVectAddr = 0;
}
void FIQ_Routine  (void)  { while (1) ;}
void SWI_Routine  (void)  { while (1) ;}
void UNDEF_Routine (void) { while (1) ;}            

C уважением, Герасимов.

;-)


Прерывания в ARM-GCC (или опять LPC)
Здравствуйте!

Что-то я так и не дождался ответа на свой вопрос.
Мож спросил не так? Информация дополнительная нужна (makefile)?

Вот, реальный чел (Я) решил освоить могучий arm-elf-gcc, начав с примитива,
запросил помощи у Знатоков, но так и осталься один в поле :-(

C уважением, Герасимов.

;-)


Re: Прерывания в ARM-GCC (или опять LPC)
Привет Gerasimov!

07 Dec 05 12:54, Gerasimov Gerasim писал Gerasimov Gerasim:

 GG> Что-то я так и не дождался ответа на свой вопрос.
 GG> Мож спросил не так? Информация дополнительная нужна (makefile)?

 GG> Вот, реальный чел (Я) решил освоить могучий arm-elf-gcc, начав с
 GG> примитива, запросил помощи у Знатоков, но так и осталься один в поле
 GG> :-(

    Hу смотрел я твой пример, криминала не увидел. Скорее всего у тебя проблема
вовсе не в сишном модуле, а в ассемблерном. Регистры там какие-нибудь не
сохраняешь, или вектор на неверный адрес управление передает, или стек не там
где-нибудь... Я еще там не очень понял по поводу закоментаренного разрешения
прерываний. Если при ее раскомментаривании светодиод перестает мигать - то
почти наверняка это проблемы со входом или выходом из прерывания.

    А gcc - чего там спрашивать? Он всего лишь из сишного кода генерит
ассемблерный. Смотри что он выдает и анализируй. Если что-то конкретно кажется
не так - спрашивай. А "почему-то не работает" - очень уж неконкретные симптомы.
:)

 GG> C уважением, Герасимов.

Всего наилучшего,                                 [Team PCAD 2000]
Алексей М.
... Смотрю куда глаза глядят...

Прерывания в ARM-GCC (или опять LPC)
Здравствуйте!

Боле менее разобрался, пока мигаю светиками из прерываний двух таймеров, но
приходится работать только из FLASH, из RAM мой код исполнятся не захотел и
возится с этим явлением наскучило. Буду пока FLASH`ку протирать :-)

В общем в статапе
_vectors:
..............
        ldr    PC, IRQ_Addr
...............
IRQ_Addr:       .word   IRQ_Routine            /* defined in main.c  */
........................

в main.c

void IRQ_Routine (void)      __attribute__ ((interrupt("IRQ")));
............
void IRQ_Routine (void) {
 unsigned int vector = VICVectAddr;
 void (*interrupt_function)() = (void(*)())vector;
   VICVectAddr = 0;
   (*interrupt_function)();
}
void TIMER0_ISR(void)
{
  ................
  timer0->IR.d = 0xff;
}

// Timer1 interrupt handler
void TIMER1_ISR(void)
{
  ................
  timer1->IR.d = 0xff;
}

Вот появились вопросы (мануал предварительно читал)
1) Как заставить gcc сохранять регистры (все, или только необходимые)при входе
в  заданную процедуру, например void TIMER1_ISR(void)? Писать для этого
макрос? Например CodeWarrior понимает #pragma interrupt_called что заставляет
его сохранять все регистры при входе в процедуру (не обязательно обработчик
прерываний)

2) Возникает естественное желание (на этапе освоения нового проца)посмотреть,
какой ассемблерный код получается после компилятора, ключ -S помогает, но
плохо, (во первых он отключает саму компиляцию и приходится стирать все
о-файлы иначе листинг не получается) в общем как "собрать" исходники и
одновременно получить их асслемблерные листинги, и желательно общий листинг с
абсолютными адресами (но их знает только ld из memory-map), или это
невозможно?

 AM>     А gcc - чего там спрашивать? Он всего лишь из сишного кода генерит
 AM> ассемблерный. Смотри что он выдает и анализируй. Если что-то конкретно
 AM> кажется не так - спрашивай. А "почему-то не работает" - очень уж
 AM> неконкретные симптомы. :)

C уважением, Герасимов.

;-)


Re: Прерывания в ARM-GCC (или опять LPC)
Hello, Gerasimov!
You wrote to Alex Mogilnikov on Thu, 12 Jan 2006 04:11:02 +0000 (UTC):

 GG> Боле менее разобрался, пока мигаю светиками из прерываний двух
 GG> таймеров, но приходится работать только из FLASH, из RAM мой код
 GG> исполнятся не захотел и возится с этим явлением наскучило. Буду пока
 GG> FLASH`ку протирать :-)
  Не понятно, в какой среде ты работаешь. Если CrossStudio, то там с этим
все нормально. Чтобы работали прерывания из RAM, должен быть соответствующим
образом инициализирован регистр MEMMAP. В CrossStudio это делается само из
скрипта Philips_LPC210X_Target.js . Чтобы быстро вызывались обработчики
прерываний, достаточно в векторе написать "ldr pc, [pc, #-0xFF0]" , таким
образом он дотягивается до VICVectAddr относительно pc, и сразу из вектора
прыгает куда надо. В CrossStudio это включается дефайном
VECTORED_IRQ_INTERRUPTS.

 GG> 2) Возникает естественное желание (на этапе освоения нового
 GG> проца)посмотреть, какой ассемблерный код получается после компилятора,
 GG> ключ -S помогает, но плохо, (во первых он отключает саму компиляцию и
 GG> приходится стирать все о-файлы иначе листинг не получается) в общем как
 GG> "собрать" исходники и одновременно получить их асслемблерные листинги,
 GG> и желательно общий листинг с абсолютными адресами (но их знает только
 GG> ld из memory-map), или это невозможно?
  В CrossStudio можно посмотреть неплохой дизассембированный листинг, просто
открывая объектники или выходной .elf из project manager-а. Также в gcc есть
ключ, предписывающий сохранять промежуточные файлы: -save-temps.

With best regards, Sergey Belyakov.  E-mail: snipped-for-privacy@mail.ru



Re: Прерывания в ARM-GCC (или опять LPC)
Привет Gerasimov!

12 Jan 06 07:11, Gerasimov Gerasim писал Alex Mogilnikov:

 GG> Вот появились вопросы (мануал предварительно читал)
 GG> 1) Как заставить gcc сохранять регистры (все, или только
 GG> необходимые)при входе в  заданную процедуру,

    Вынеси эту функцию в отдельный модуль и компилируй с -fcall-saved-reg.

    Еще можно дать этой функции атрибут naked и сделать ей пролог и эпилог
ассемблерными вставками. Hо это слишком низкоуровневое решение чтобы применять
его только ради сохранения регистров.

 GG>  например void TIMER1_ISR(void)? Писать для этого макрос?

    ? Как макрос может влиять на кодогенерацию? Разберись, какая программа что
делает в процессе сборки: кто из цепочки
препроцессор-компилятор-ассемблер-линкер какую части работы выполняет, что
получает на вход и что выдает на выход.

 GG> 2) Возникает естественное желание (на этапе освоения нового
 GG> проца)посмотреть, какой ассемблерный код получается после компилятора,
 GG> ключ -S помогает, но плохо, (во первых он отключает саму компиляцию и

    Hе отключает:

alx% arm-elf-gcc --help|grep -- -S
  -S                       Compile only; do not assemble or link

    Ассемблерный код как раз и получается в результате компиляции. -S отключает
ассемблирование и линковку. Компиляцию отключает -E:

alx% arm-elf-gcc --help|grep -- -E
  -E                       Preprocess only; do not compile, assemble or link

 GG> приходится стирать все о-файлы иначе листинг не получается)

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

 GG> в общем
 GG> как "собрать" исходники и одновременно получить их асслемблерные
 GG> листинги,

    Листинг генерируется ассемблером при наличии -a:

  -a[sub-option...]       turn on listings
                          Sub-options [default hls]:
                          c      omit false conditionals
                          d      omit debugging directives
                          h      include high-level source
                          l      include assembly
                          m      include macro expansions
                          n      omit forms processing
                          s      include symbols
                          =FILE  list to FILE (must be last sub-option)

 GG>  и желательно общий листинг с абсолютными адресами (но их
 GG> знает только ld из memory-map), или это невозможно?

    Ты сам себе ответил. Это невозможно, так как ассемблер не знает, по каким
адресам ассемблируемая секция будет потом размещена линкером. Абсолютные адреса
смотрят в map-файле (который делает линкер, если ему сказать -Map) или в
отладчике.

    В SDCC'шном линкере была такая фича: он пытался найти листинг от линкуемых
объектников, и если находил, вписывал в них абсолютные адреса. Hо такое
поведение - экзотика.

Всего наилучшего,                                 [Team PCAD 2000]
Алексей М.
... Чудо-йогурт Био. Чемпион среди какао.

Re: Прерывания в ARM-GCC (или опять LPC)
Hi!


GG> 2) Возникает естественное желание (на этапе освоения нового
GG> проца)посмотреть,
GG> какой ассемблерный код получается после компилятора, ключ -S помогает, но
GG> плохо, (во первых он отключает саму компиляцию и приходится стирать все
GG> о-файлы иначе листинг не получается) в общем как "собрать" исходники и
GG> одновременно получить их асслемблерные листинги, и желательно общий листинг
GG> с
GG> абсолютными адресами (но их знает только ld из memory-map), или это
GG> невозможно?

 Попробуй objdump из твоего набора (ключи по вкусу).

 objdump -dStl твой.elf

--

EM

Re: Прерывания в ARM-GCC (или опять LPC)
 GG>> 2) Возникает естественное желание (на этапе освоения нового
 GG>> проца)посмотреть,  какой ассемблерный код получается после компилятора,
 GG>> ключ -S помогает, но  плохо, (во первых он отключает саму компиляцию и
 GG>> приходится стирать все  о-файлы иначе листинг не получается) в общем как
 GG>> "собрать" исходники и  одновременно получить их асслемблерные листинги,
 GG>> и желательно общий листинг с  абсолютными адресами (но их знает только
 GG>> ld из memory-map), или это  невозможно?

 EM>  Попробуй objdump из твоего набора (ключи по вкусу).

 EM>  objdump -dStl твой.elf

Не получилось, зато получилось с листингом, добавил -Wa,-ahlns=$(<:.c=.lst)при
компиляции, однако (h) include high-level source так и не получил (так понимаю
строки ассемблера должны предварять строки сишного исходника), странно почему?

;-)


Site Timeline