sandro76
12-06-2006, 11:16
Sto testando gli interrupt su una scheda con un processore SH 7047.
Il programma che ho realizzato accende l’AD converter e finita la conversione dovrebbe far avvenire un interrupt, che attiva una funzione che mediante un ciclo infinito accende e spegne un led della scheda che è legato a un pin della porta e.
Il main è questo:
#include "iodefine.h"
int i;
void main(void)
{
INTC.IPRG.BIT._AD01=0x0A; /* da la priorità 10 a l’interrupt dell’ AD*/
PFC.PEIORL.WORD|=0xFFFF; /*tutta la porta e output*/
PFC.PECRL1.WORD&=0x0000; /*tutta la porta e general i/o*/
PFC.PECRL2.WORD&=0x0000; /*tutta la porta e general i/o*/
PE.DRL.WORD=0x0000; /*data register della PE*/
MST.CR2.BIT._AD1=0; /*accende l’AD, inizialmente è in stand by*/
AD1.ADCR.BIT.ADST=0; /*AD start =0*/
AD1.ADCSR.BIT.ADF=0; /*flag a 0*/
AD1.ADCSR.BIT.ADIE=1; /*abilita l’ interrupt*/
AD1.ADCSR.BIT.ADM=00; /*1 canale*/
AD1.ADCR.BIT.CKS=0; /*velocita di scansione max*/
AD1.ADCSR.BIT.CH=0x1; /* II canale*/
AD1.ADCR.BIT.ADCS=0; / *modo single scan*/
AD1.ADCR.BIT.ADST=1; /*parte l’AD*/
}
Gli altri file che trovo sono
Inthandler .h:
void INT_Manual_Reset_PC(void) __attribute__ ((interrupt_handler));
void INT_Manual_Reset_SP(void) __attribute__ ((interrupt_handler));
void INT_Illegal_code(void) __attribute__ ((interrupt_handler));
void INT_Illegal_slot(void) __attribute__ ((interrupt_handler));
void INT_CPU_Address(void) __attribute__ ((interrupt_handler));
void INT_DTC_Address(void) __attribute__ ((interrupt_handler));
void INT_NMI(void) __attribute__ ((interrupt_handler));
…
void INT_MTU4_TCIV4(void) __attribute__ ((interrupt_handler));
void INT_ADI0(void) __attribute__ ((interrupt_handler));
void INT_ADI1(void) __attribute__ ((interrupt_handler));
void INT_DTC_SWDTEND(void) __attribute__ ((interrupt_handler));
…
Penso che definisca come interrupt le varie funzioni definite. Lo lascio così;
Inthandler.c:
#include "inthandler.h"
#include "iodefine.h" /*lo ho aggiunto io per far riconoscere le strutture in ADI1*/
void INT_Manual_Reset_PC(void)
{
/*add your code here*/
}
void INT_Manual_Reset_SP(void)
{
/*add your code here*/
}
void INT_Illegal_code(void)
{
/*add your code here*/
}
…
void INT_ADI1(void) /*qui sono andato a scrivere il codice della funzione attivata dall’ interrupt*/
{
int i;
while (1)
{
for (i=0;i<30000;i++)
PE.DRL.WORD|=0x4000; /*queste maschere portano a 1 e 0 il pin 14 che corrisponde al led*/
for (i=30000; i<60000; i++)
PE.DRL.WORD&=0xBFFF;
i=0; }
}
…;
vects:
#include "inthandler.h"
extern void start (void); /* Startup code (in start.s) */
extern void stack (void); /* stack from linker script */
/**----------------------------------
** Typedef for the function pointer
**-----------------------------------*/
typedef void (*fp) (void);
#define VECT_SECT __attribute__ ((section (".vects")))
const fp HardwareVectors[] VECT_SECT = {
start, /* 0 Power-on reset, Program counter (PC) */
INT_Manual_Reset_PC,
INT_Manual_Reset_SP,
INT_Illegal_code,
(fp)0, /*Reserved 5*/
INT_Illegal_slot,
(fp)0, /*Reserved 7*/
(fp)0, /*Reserved 8*/
…
INT_ADI0,
INT_ADI1,
…
Dovrebbe realizzare la vector table. Non lo tocco;
iodefine.h: che associa i registri a strutture con nomi più mnemonici;
start.asm:
! Start.asm
.list
.section .text
.global _start ! global Start routine
.extern _hw_initialise ! external Sub-routine to initialise Hardware
.extern _main
.extern _data
.extern _mdata
.extern _edata
.extern _ebss
.extern _bss
.extern _stack
.extern _vects
#if DEBUG
.extern _exit
#endif
_start:
! initialise the SP for non-vectored code
mov.l stack,r15
! Call hw_initialise
mov.l hw_initialise,r1
jsr @r1
nop
!load data section from ROM to RAM only if ROMSTART is defined
#if ROMSTART
! initialise sections
mov.l edata,r1 ! edata in r1
mov.l mdata,r2 ! mdata in r2
mov.l data,r0 ! data in r0
cmp/eq r0,r1
bt start_1
nop
start_l:
mov.b @r2,r3 !get from src
mov.b r3,@r0 !place in dest
add #1,r2 !inc src
add #1,r0 !inc dest
cmp/eq r0,r1 !dest == edata?
bf start_l
nop
start_1:
#endif // ROMSTART
! zero out bss
mov.l ebss,r1
mov.l bss,r0
cmp/eq r0,r1
bt start_3
sub r2,r2
start_2:
mov.b r2,@r0
add #1,r0
cmp/eq r0,r1
bf start_2
nop
start_3:
#ifdef CPPAPP
!Initialize global constructor
mov.l _InitCtors,r1
jsr @r1
nop
#endif
mov.l main,r1
jsr @r1
nop
! call to exit
#if DEBUG
mov.l _exit_k,r1
jsr @r1
nop
#endif
#if RELEASE
exit:
bra exit
nop
#endif
.ALIGN 4
hw_initialise:
.long _hw_initialise
stack:
.long _stack
main:
.long _main
#ifdef CPPAPP
_InitCtors:
.long ___main
#endif
data:
.long _data
mdata:
.long _mdata
edata:
.long _edata
bss:
.long _bss
ebss:
.long _ebss
#if DEBUG
_exit_k:
.long _exit
#endif
.end
Che non so cosa fa(?);
hwinit:
#include "iodefine.h"
void hw_initialise (void) {
// TODO: add hardware initialisation code here
}
Qui penso che dovrei scrivere le inizializzazioni hardware che invece ho messo sul main, ma facendolo non ho avuto comunque miglioramenti.
Compilato e monitorato col debbugger mi accade che:
1) se metto il PC sull’ indirizzo del main (come ho fatto per testare gli altri programmi senza interrupt finora) il programma mi esegue tutto il main, ma finito salta all’indirizzo 00000000 e si blocca senza eseguire l’interrupt. L’AD si accende e finisce la conversione perché la sua flag visualizzando i registri vedo che la flag di fine conversione va a 1.
(dimenticavo: ho scaricato il programma sulla memoria interna del processore: FFFFD000, all’indirizzo 00000000 che è una memoria flash c’è il monitor per il debugger).
2) se vado dove si trova inizialmente il PC lo trovo all’ indirizzo corrispondente di _start.
Eseguendo passo passo o mandandolo in esecuzione mi si blocca dopo hwinit:
MOV.L R14,@-R15 void hw_initialise (void) {
MOV R15,R14
.DATA.W H'FFFF } si blocca qui col messaggio break=illegal general istruction
Sapete dove sbaglio?
Il programma che ho realizzato accende l’AD converter e finita la conversione dovrebbe far avvenire un interrupt, che attiva una funzione che mediante un ciclo infinito accende e spegne un led della scheda che è legato a un pin della porta e.
Il main è questo:
#include "iodefine.h"
int i;
void main(void)
{
INTC.IPRG.BIT._AD01=0x0A; /* da la priorità 10 a l’interrupt dell’ AD*/
PFC.PEIORL.WORD|=0xFFFF; /*tutta la porta e output*/
PFC.PECRL1.WORD&=0x0000; /*tutta la porta e general i/o*/
PFC.PECRL2.WORD&=0x0000; /*tutta la porta e general i/o*/
PE.DRL.WORD=0x0000; /*data register della PE*/
MST.CR2.BIT._AD1=0; /*accende l’AD, inizialmente è in stand by*/
AD1.ADCR.BIT.ADST=0; /*AD start =0*/
AD1.ADCSR.BIT.ADF=0; /*flag a 0*/
AD1.ADCSR.BIT.ADIE=1; /*abilita l’ interrupt*/
AD1.ADCSR.BIT.ADM=00; /*1 canale*/
AD1.ADCR.BIT.CKS=0; /*velocita di scansione max*/
AD1.ADCSR.BIT.CH=0x1; /* II canale*/
AD1.ADCR.BIT.ADCS=0; / *modo single scan*/
AD1.ADCR.BIT.ADST=1; /*parte l’AD*/
}
Gli altri file che trovo sono
Inthandler .h:
void INT_Manual_Reset_PC(void) __attribute__ ((interrupt_handler));
void INT_Manual_Reset_SP(void) __attribute__ ((interrupt_handler));
void INT_Illegal_code(void) __attribute__ ((interrupt_handler));
void INT_Illegal_slot(void) __attribute__ ((interrupt_handler));
void INT_CPU_Address(void) __attribute__ ((interrupt_handler));
void INT_DTC_Address(void) __attribute__ ((interrupt_handler));
void INT_NMI(void) __attribute__ ((interrupt_handler));
…
void INT_MTU4_TCIV4(void) __attribute__ ((interrupt_handler));
void INT_ADI0(void) __attribute__ ((interrupt_handler));
void INT_ADI1(void) __attribute__ ((interrupt_handler));
void INT_DTC_SWDTEND(void) __attribute__ ((interrupt_handler));
…
Penso che definisca come interrupt le varie funzioni definite. Lo lascio così;
Inthandler.c:
#include "inthandler.h"
#include "iodefine.h" /*lo ho aggiunto io per far riconoscere le strutture in ADI1*/
void INT_Manual_Reset_PC(void)
{
/*add your code here*/
}
void INT_Manual_Reset_SP(void)
{
/*add your code here*/
}
void INT_Illegal_code(void)
{
/*add your code here*/
}
…
void INT_ADI1(void) /*qui sono andato a scrivere il codice della funzione attivata dall’ interrupt*/
{
int i;
while (1)
{
for (i=0;i<30000;i++)
PE.DRL.WORD|=0x4000; /*queste maschere portano a 1 e 0 il pin 14 che corrisponde al led*/
for (i=30000; i<60000; i++)
PE.DRL.WORD&=0xBFFF;
i=0; }
}
…;
vects:
#include "inthandler.h"
extern void start (void); /* Startup code (in start.s) */
extern void stack (void); /* stack from linker script */
/**----------------------------------
** Typedef for the function pointer
**-----------------------------------*/
typedef void (*fp) (void);
#define VECT_SECT __attribute__ ((section (".vects")))
const fp HardwareVectors[] VECT_SECT = {
start, /* 0 Power-on reset, Program counter (PC) */
INT_Manual_Reset_PC,
INT_Manual_Reset_SP,
INT_Illegal_code,
(fp)0, /*Reserved 5*/
INT_Illegal_slot,
(fp)0, /*Reserved 7*/
(fp)0, /*Reserved 8*/
…
INT_ADI0,
INT_ADI1,
…
Dovrebbe realizzare la vector table. Non lo tocco;
iodefine.h: che associa i registri a strutture con nomi più mnemonici;
start.asm:
! Start.asm
.list
.section .text
.global _start ! global Start routine
.extern _hw_initialise ! external Sub-routine to initialise Hardware
.extern _main
.extern _data
.extern _mdata
.extern _edata
.extern _ebss
.extern _bss
.extern _stack
.extern _vects
#if DEBUG
.extern _exit
#endif
_start:
! initialise the SP for non-vectored code
mov.l stack,r15
! Call hw_initialise
mov.l hw_initialise,r1
jsr @r1
nop
!load data section from ROM to RAM only if ROMSTART is defined
#if ROMSTART
! initialise sections
mov.l edata,r1 ! edata in r1
mov.l mdata,r2 ! mdata in r2
mov.l data,r0 ! data in r0
cmp/eq r0,r1
bt start_1
nop
start_l:
mov.b @r2,r3 !get from src
mov.b r3,@r0 !place in dest
add #1,r2 !inc src
add #1,r0 !inc dest
cmp/eq r0,r1 !dest == edata?
bf start_l
nop
start_1:
#endif // ROMSTART
! zero out bss
mov.l ebss,r1
mov.l bss,r0
cmp/eq r0,r1
bt start_3
sub r2,r2
start_2:
mov.b r2,@r0
add #1,r0
cmp/eq r0,r1
bf start_2
nop
start_3:
#ifdef CPPAPP
!Initialize global constructor
mov.l _InitCtors,r1
jsr @r1
nop
#endif
mov.l main,r1
jsr @r1
nop
! call to exit
#if DEBUG
mov.l _exit_k,r1
jsr @r1
nop
#endif
#if RELEASE
exit:
bra exit
nop
#endif
.ALIGN 4
hw_initialise:
.long _hw_initialise
stack:
.long _stack
main:
.long _main
#ifdef CPPAPP
_InitCtors:
.long ___main
#endif
data:
.long _data
mdata:
.long _mdata
edata:
.long _edata
bss:
.long _bss
ebss:
.long _ebss
#if DEBUG
_exit_k:
.long _exit
#endif
.end
Che non so cosa fa(?);
hwinit:
#include "iodefine.h"
void hw_initialise (void) {
// TODO: add hardware initialisation code here
}
Qui penso che dovrei scrivere le inizializzazioni hardware che invece ho messo sul main, ma facendolo non ho avuto comunque miglioramenti.
Compilato e monitorato col debbugger mi accade che:
1) se metto il PC sull’ indirizzo del main (come ho fatto per testare gli altri programmi senza interrupt finora) il programma mi esegue tutto il main, ma finito salta all’indirizzo 00000000 e si blocca senza eseguire l’interrupt. L’AD si accende e finisce la conversione perché la sua flag visualizzando i registri vedo che la flag di fine conversione va a 1.
(dimenticavo: ho scaricato il programma sulla memoria interna del processore: FFFFD000, all’indirizzo 00000000 che è una memoria flash c’è il monitor per il debugger).
2) se vado dove si trova inizialmente il PC lo trovo all’ indirizzo corrispondente di _start.
Eseguendo passo passo o mandandolo in esecuzione mi si blocca dopo hwinit:
MOV.L R14,@-R15 void hw_initialise (void) {
MOV R15,R14
.DATA.W H'FFFF } si blocca qui col messaggio break=illegal general istruction
Sapete dove sbaglio?