Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Message

Timer interrupt problem

2004-01-23 by bobbruce000

I am using a LPC2106, and I need to monitor 16 pins for   
level changes.  Since there aren't that many external   
interrupt pins, I decided to use a timer interrupt and   
sample the pins every few microseconds.  Since this is   
the most frequent interrupt, I made it the "fast   
interrupt".   
  
But whenever I enable the timer interrupt, the interrupt   
completes one time and then everything freezes up.  I am   
pretty sure I am resetting the timer interrupt correctly.   
This is the routine (R10 is already set to 0xE0004000):   
  
fiq:    mov	r9,#0xff	// Set bottom eight bits   
	str	r9,[r10]	// Reset Timer interrupts   
	subs	pc,r14,#4	// Return from interrupt   
  
If I disable additional interrupts in the handler, then   
the interrupt returns okay, but (obviously) doesn't repeat.   
I know it is running because I added an instruction to   
turn on an LED:  
  
fiq:    mov	r9,#0xff	// Set bottom eight bits   
	str	r9,[r10]	// Reset Timer interrupts   
	str	r9,[r12]	// Light up LED   
	msr	spsr_c,#0xdf	// disable interrupts on return   
	subs	pc,r14,#4	// Return from interrupt   
  
But here is something even weirder:  If I add some nops, and   
make the routine a little longer, then it freezes up, even with   
interrupts disabled:   
  
fiq:	nop   
	nop   
	nop   
	nop   
        mov	r9,#0xff	// Set bottom eight bits   
	str	r9,[r10]	// Reset Timer interrupts   
	str	r9,[r12]	// Light up LED   
	msr	spsr_c,#0xdf	// disable interrupts on return   
	subs	pc,r14,#4	// Return from interrupt   
  
If there are three or fewer nops, the interrupt returns (once),   
but with four or more, it does not.	   
  
Please let me know if you have any idea what I am doing wrong.   
I have been fiddling with this for the last two days with no   
progress.   
	-bob   
  
ps:  Here is the C code that intializes the timer and VIC,  
     followed by the ASM startup code and FIQ handler.  
  
void   
timer0_init(void) {   
  TIMER0_PR  = 0x000000ff; // Prescaler   
  TIMER0_MR0 = 0x00000100; // Match register   
  TIMER0_MCR = 0x00000003; // Reset and interrupt on match   
  TIMER0_TCR = 0x3;	   // Enable and reset counter   
  TIMER0_TCR = 0x1;	   // Start counter   
  TIMER0_IR  = 0xff;	   // Clear any pending interrupts   
  return;   
}   
   
static void   
vic_init(void) {	// Page 61   
   
  VICIntSelect   = 0x00000010;  // The set bit is for FIQ -- Timer 0   
  VICIntEnable   = 0x00000010;  // Timer 0 interrupt is enabled   
  return;   
}   
-------------------------------------------------------------  
_start:	   
b   reset		//   0   Reset   
b   undef_isr      	//   1   Undefined Instruction   
b   swi_isr		//   2   Software Interrupt   
b   prefetch_isr	//   3   Prefetch abort   
b   data_abort_isr	//   4   Data abort   
b   reserved		//   5	 Replace with checksum   
b   irq			//   6   IRQ   
fiq:			//   7   Fast interrupt handler   
        mov	r9,#0xff	// Set bottom eight bits   
	str	r9,[r10]	// Reset Timer interrupts   
	str	r9,[r12]	// Light up LED   
	msr	spsr_c,#0xdf	// disable intrpts: fails if removed   
	subs	pc,r14,#4	// Return from interrupt   
   
.L_StackTop:	.word	0x4000ffe0  // RAM top minus 32 b for IAP   
.L_T0IR:	.word	0xE0004000  // Timer 0 IR port address   
.L_VVA:		.word	0xfffff030  // VIC Vect Addr port address   
.L_IOCLR:	.word	0xE002800C  // IOCLR address   
   
reset:   
	ldr	r0,.L_StackTop	// r0 = top of stack   
	msr	cpsr,#0xd1	// switch to FIQ mode 
	sub	sp,r0,#0x00	// Set FIQ stack pointer   
	ldr	r10,.L_T0IR	// R10 = timer0_ir address   
	ldr	r11,.L_VVA	// R11 = VICVectAddr address   
	ldr	r12,.L_IOCLR	// R12 = IOCLR address   
	// Set up stack pointers for each mode, etc.   
	mov	sp,r0		// Stack for FIQ   
	msr	cpsr,#0xd2	// Switch to IRQ mode   
	sub	sp,r0,#32	// sp_IRQ = sp_FIQ minus 32  
	msr	cpsr,#0xd7	// Switch to Abort mode   
	sub	sp,r0,#64	// Set Abort stack pointer   
	msr	cpsr,#0xdb	// Switch to Undef mode   
	sub	sp,r0,#96	// Set Undef stack pointer   
	msr	cpsr,#0xd3	// Switch to Supervisor mode   
	sub	sp,r0,#128	// Set Supervisor stack pointer   
	msr	cpsr,#0xdf	// Switch to System mode   
	sub	sp,r0,#160	// Set System (main) stack pointer   
	b	main		// Jump to main() C routine

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.