dont have a clue where you are stuck we need more info, but maybe a small skeleton will confirm you are at least doing these few things. have you done an arm7 before or is this the first time, or you are well versed in the arm7/arm world but just cant get the interrupts to work?
start.s
.globl _start
_start:
.globl _start
_start:
ldr pc,reset_handler
ldr pc,undefined_handler
ldr pc,swi_handler
ldr pc,prefetch_handler
ldr pc,data_handler
ldr pc,unused_handler
ldr pc,irq_handler
ldr pc,fiq_handler
reset_handler: .word reset
undefined_handler: .word hang
swi_handler: .word hang
prefetch_handler: .word hang
data_handler: .word hang
unused_handler: .word hang
irq_handler: .word irq
fiq_handler: .word hang
reset:
;@ (PSR_IRQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD2
msr cpsr_c,r0
ldr sp,=0x40002000
;@ (PSR_FIQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD1
msr cpsr_c,r0
ldr sp,=0x40003000
;@ (PSR_SVC_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD3
msr cpsr_c,r0
ldr sp,=0x40004000
bl notmain
hang: b hang
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.globl GET32
GET32:
ldr r0,[r0]
bx lr
.globl dummy
dummy:
bx lr
.globl enable_irq
enable_irq:
mrs r0,cpsr
bic r0,r0,#0x80
msr cpsr_c,r0
bx lr
irq:
push {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
bl c_irq_handler
pop {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
subs pc,lr,#4
yes that is too many registers...only need the volatile ones the compiler covers the others.
notmain:
void c_irq_handler ( void )
{
}
void notmain ( void )
{
unsigned int ra;
for(ra=0;ra<100;ra++) dummy(ra);
}
flash.ld
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
ram : ORIGIN = 0x40000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.bss : { *(.bss*) } > ram
}
guess I didnt need .bss
build
arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -O2 -c notmain.c -o notmain.o
arm-none-eabi-ld -T flash.ld start.o notmain.o -o so.elf
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy so.elf -O binary so.bin
always examine your so.list
they have an interesting way to determine if you have a flash there or if they should dump into their bootloader
Criterion for valid user code: The reserved ARM interrupt vector
location (0x0000 0014) should contain the 2’s complement of the
check-sum of the remaining interrupt vectors. This causes the checksum
of all of the vectors together to be 0.
I didnt do that yet, can do that by hand or have a program come along after and do it programmatically.
change it to this
ldr pc,reset_handler
ldr pc,undefined_handler
ldr pc,swi_handler
ldr pc,prefetch_handler
ldr pc,data_handler
.word 0xb8a06f58 @ldr pc,unused_handler
ldr pc,irq_handler
ldr pc,fiq_handler
and that should work fine.
If this is completely useless to elementary then let me know will delete this answer no problem.
notmain.c
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void enable_irq ( void );
#define T0IR 0xE0004000
#define T0TCR 0xE0004004
#define T0PC 0xE0004010
#define T0MCR 0xE0004014
#define T0TC 0xE0004008
#define T0MCR0 0xE0004018
void c_irq_handler ( void )
{
PUT32(T0IR,1);
}
void notmain ( void )
{
PUT32(T0TCR,2);
PUT32(T0TCR,0);
PUT32(T0TC,0);
PUT32(T0MCR0,0x100000);
PUT32(T0MCR,0x1); //3);
PUT32(T0TCR,1);
while(1)
{
if(GET32(T0IR&1)) break;
}
PUT32(T0IR,1);
PUT32(T0TCR,2);
PUT32(T0TCR,0);
PUT32(T0TC,0);
PUT32(T0MCR0,0x100000);
PUT32(T0MCR,0x1); //3);
PUT32(T0IR,1);
enable_irq();
PUT32(T0TCR,1);
while(1) continue;
}
just banged this out from the manual didnt check if there was a clock enable for the timer, etc. Personally I get the gpio up first, blink an led with a big counter loop
for(ra=0;ra<0x20000;ra++) dummy(ra);
then use a timer in a polling mode (just get it started free-running) to blink based on time from this can figure out the clock speed, that leads into the uart, get the uart, up, have a trivial routine for printing data
void hexstring ( unsigned int d )
{
//unsigned int ra;
unsigned int rb;
unsigned int rc;
rb=32;
while(1)
{
rb-=4;
rc=(d>>rb)&0xF;
if(rc>9) rc+=0x37; else rc+=0x30;
uart_send(rc);
if(rb==0) break;
}
uart_send(0x0D);
uart_send(0x0A);
}
octal is even easier but man is it hard to think in octal...
THEN finally the interrupt stuff, take code like the above and I would poll and print the various registers in the timer, would see if that interrupt register does fire in a polling mode first (second, third, fourth... without enabling interrupts to the processor (dont do that for a while).
Once I can see it at the peripheral level, which some dont work that way but assume this one does. Then in this case there is a VIC, and I assume this register
VICRawIntr 0xFFFFF008
should also be asserted if the timer interrupt is asserted and has fired. confirm it is (bit 4 it appears) confirm it goes away when the interrupt is cleared in the peripheral.
VICIntSelect resets to zero which is irq, that is what we want dont need to touch it for now.
I assume set bit 4 in VICIntEnable
then do the polling thing again printing out to see what is going on.
Now I would expect to see the interrupt show in VICIRQStatus (still completely polling do not enable the irq to the processor yet) and go away when the peripheral clears, or figure out how to clear it if the peripheral interrupt being cleared does not make it this far.
NOW it is time to enable the irq to the processor, and I personaly would shove a byte into the uart to see it pop out. or flick an led on or something.
in theory we just clear the periheral and return to safely return to the application.
I follow the same procedure no matter what processor it is mcu or full sized, etc. interrupts can be nightmares and the more code you write without testing the more likely to fail. sometimes one line of code per test is required. YMMV.
again if this is completely useless sorry, will delete. I think I have one/some 2148s but not a 2138, and am not going to order one just to write/test working code. been using arm since this ARMV7TDMI was out and becoming popular to the present armv8s which are far more painful. the pi-zero and such are quite fun as they are old school like this arm7...
I figure the timer would be the easier one to get a real interrupt from. another might be a gpio pin although I think that is more work but would tie a jumper between pins, make one an output the other an input with interrupt edge detection if this chip has it use the output gpio to change the state of the input in a clean manner, and go through the whole polling process of watching the interrupt hit each layer in turn and confirm you can remove the interrupt each time at each layer. then bang on the edge of the core, and then finally let it into the core.