colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

System Timer Interrupts? (Or using interrupts at all)

Sun Dec 22, 2013 1:33 pm

Hi there.

Section 12 (System Timer) of SoC-Peripherals.pdf states that:

"<blah, blah> output compare register <blah, blah> free running counter values.
When the two values match, the system timer peripheral generates a signal to indicate a match for the appropriate channel. The match signal is then fed into the interrupt controller."

I presume this means that if the interrupt is enabled in some interrupt controller register, then the interrupt controller will generate a TimerOutputCompareX interrupt and jump to some vector location?

Ah. No, I see in section 7.2 ... "An interrupt vector module has NOT been implemented." OK...

At this point I'm finding the documentation unclear (typos, grammar, omissions etc).

Table "ARM peripherals interrupts table." on p.113 makes no mention of any timers.

Table "ARM peripherals interrupts table." on p.113 (yes, the same name) mentions the ARM Timer but Section 14 Timer (ARM side) p.196 "recommends using the system timers" in any case.

The Basic Pending Register (and GPU pending registers 1 and 2) show which IRQs are pending. In the section describing the GPU IRQx(10,11..20) bits of the Basic Pending Register (p.114) reference is made to the GPU interrupts table. I'm guessing some of these might be the TCRx IRQs?

Unfortunately, I can't find the GPU interrupts table. The only IRQ table with 64 entries I can see is the 1st table on p.113. But even if that's been mislabeled, the GPU interrupts mentioned in the Basic Pending Register ( 7,9,10,18,19,53-57,62) don't actually match up with the ones mentioned in that table (29,43,45,46,48-55,57).

And even if I could find the correct table/entry, and set things up to generate an IRQ (or possibly a FIQ) I'm not sure what happens then. Where does code execution jump to?

bts
Posts: 5
Joined: Sun Jul 21, 2013 4:06 pm
Contact: Website

Re: System Timer Interrupts? (Or using interrupts at all)

Sun Dec 22, 2013 2:37 pm

Actually BCM manual is quite garbled as for interrupts... I've managed to generate them (in case of GPIO though), so I'll write things you need to do (it won't be huge difference with enabling timer interrupts):
1) set interrupt vector table - it will tell "where to go" after interrupt is triggered, connect it with your interrupt handler
2) set stack in IRQ mode (it has separate stack pointer)
3) create function enabling interrupts in CPSR
example for these steps: http://pastebin.com/xLeNFDxj , then:
3) set your controller, as described in SoC manual (in my case it was enabling event detection on GPIO pin) - here you have to set your timer
4) set IRQ enable registers as described in SoC manual (page 112, "Enable IRQs 1/2" register)
5) call CPSR enabling function finally.
Then you wait for interrupt to happen and call your handler. Example for these steps I described here: http://cumana.jogger.pl/2013/11/05/rasp ... -keyboard/ - take a look at "keyboadInit". I think that's the best way to look at examples.

Probably you would want to look at dwelch67 code also, I'm not sure but probably he used timer with interrupts.
Last edited by bts on Sun Dec 22, 2013 2:55 pm, edited 1 time in total.
http://cumana.jogger.pl/

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: System Timer Interrupts? (Or using interrupts at all)

Sun Dec 22, 2013 2:49 pm

Thanks.

"Garbled" indeed :D

User avatar
rpdom
Posts: 17977
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: System Timer Interrupts? (Or using interrupts at all)

Sun Dec 22, 2013 3:29 pm

It is indeed a bit "garbled" where interrupts are concerned.

I did manage to get timer interrupts working in some of my code though, so it can be done (just don't ask me to post the code, as it is a mess :o )

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: System Timer Interrupts? (Or using interrupts at all)

Sun Dec 22, 2013 8:14 pm

Sidetracking my own thread...

Microcontroller, microprocessor, SOC, cores, architectures -- the documentation often seems problematic in one way or another.

Either things are not documented, or it comes in 1000 page multi-volume tomes.

My worst experience was trying to go through the Texas Instruments 3500 page TRM for the OMAP 3530 (ARM Cortex A8, as used on the beagle board) -- seemingly pages and pages of waffle, but without telling me what I actually wanted to know (like which bits to write to which registers in which order to get the thing set up: power, clocks, memory, interrupts...)

The best documentation I've come across is the Atmel stuff...

Is it just me?

dwelch67
Posts: 971
Joined: Sat May 26, 2012 5:32 pm

Re: System Timer Interrupts? (Or using interrupts at all)

Mon Dec 23, 2013 5:22 am

ARM themselves do a good job with docs IMO. Atmel is generally pretty good, I think that contributes to the avr freaks before and now during the arduinos. The TI msp430 docs are not bad other than you have to jump between at least two docs to find what you need. One doc has addresses for stuff, other details how to use it, but the details are often good including an init sequence for various things. The OMAP docs are as bad as the broadcom/raspberry pi docs in their own way. Eventually you can find something where with the broadcom doc for the raspberry pi chip, some hacking is required.

I think I mentioned this ages ago, not something I want to lead (otherwise it would have happened), but if there were a motivated few backed by some number of others, we could make an open source, community created, set of docs for this chip. There are errata listed on the wiki pages so that may help you...

github.com/dwelch67 I have some examples with and without interrupts, hand holding through polling the interrupts, again, some hacking is required for bare metal on this chip. the interesting thing is that when it comes down to it, this chip is super easy to program, there are not piles of extra logic and fluff between things, if the docs were good, it would be my primary choice for recommendations for teaching folks bare metal, start here and then get more complicated with microcontrollers with their power savings and other such things you have to init.

blah, blah

Anyway, you can fiddle around and use the interrupt status registers to see what line has changed state, it may or may not be documented. one/some of the interrupts are supposedly used by the gpu so we probably shouldnt be mucking with them. just poll and print out the status registers and you will see some active with nothing that the arm has done to set them up. Then others (uart's, etc) you can trigger then see those change state and not get cleared (by the gpu). Even with really good docs I usually take the slow approach where possible (some chips dont give you these kinds of status registers or polling points) and walk the interrupt up to the edge of the processor before going in. with the arm you can bring it into the processor and poll instead of interrupt to verify it has made it that far before committing to an interrupt.

David

SKyd3R
Posts: 11
Joined: Thu Nov 14, 2013 9:30 am

Re: System Timer Interrupts? (Or using interrupts at all)

Fri Mar 07, 2014 12:19 pm

If I use bts' code with this handler (and the function putString implemented to print any String with determined length):

Code: Select all

void kIrqHandler(){
	putString("irq_interrupt",13);
	irqDisable();
}
It never stops to show "irq_interrupt" on the screen. Any suggestion?

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: System Timer Interrupts? (Or using interrupts at all)

Sun Mar 09, 2014 9:37 pm

If you're sure that your putString is working properly, then your handler is obviously not being called. So you've shown us the wrong bit of code :-)
Obviously keyboardInit must be invoked before usage, as well as kIrqHandler needs to be called from ASM interrupt handler (or to be pointed from IVT). It's also necessary to setup interrupts at all, what can be nettlesome. Working examples can be find on dwelch67's github.
Have you done all of this?

You need to:
a) read the Broadcom SOC doc. Sections on GPIO and Interrupts.

b) Enable interrupts globally (with cpsie i)
c) Say which peripherals are enabled to generate interrupts by setting bits in, for example, IRQ_IRQ1_EN.
d) Configure the conditions under which the peripheral actually generates an interrupt. E.g. by setting bits in GPIO_GPFEN0.
Last edited by colinh on Tue Mar 11, 2014 1:18 am, edited 2 times in total.

SKyd3R
Posts: 11
Joined: Thu Nov 14, 2013 9:30 am

Re: System Timer Interrupts? (Or using interrupts at all)

Mon Mar 10, 2014 9:59 am

I end up with some modifications and didn't work. The only think I need is to program the timer in order to show a message.

I hope with this code will be enough to find out why the "irq_interrupt" message won't stop appearing.

Code: Select all

.section .init
.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 dummy
swi_handler: 		.word dummy
prefetch_handler: 	.word dummy
data_handler: 		.word dummy
unused_handler: 	.word dummy
irq_handler: 		.word kIrq
fiq_handler: 		.word dummy

//Copy the interrupts vector to the first memory positions
reset:
    mov r0,$0x8000
    mov r1,$0x0000
    ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
    stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}
    ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
    stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}

	mov sp, $0x8000

//set stack in irq mode
	mrs r0, cpsr
	bic r0, $0b11111111
	orr r0, $0b11010010
	msr cpsr, r0
	mov sp, $0x4000

//come back to svc mode
	mrs r0, cpsr
	bic r0, $0b11111111
	orr r0, $0b11010011
	msr cpsr, r0

loop:
	cmp r0, r1
	strlo r2, [r0], $4
	blo loop

	bl main

dummy:
	b dummy

kIrq:
	push {r0-r7, lr}
	//There is no need to clean status for timer int?
	bl irq_interrupt
	pop {r0-r7, lr}
	subs pc, lr, $4

.section .text
.globl irqEnable
irqEnable:
        mrs r0, cpsr
        bic r0, $0b10000000
        msr cpsr, r0
		cpsie i
        mov pc, lr
.globl irqDisable
irqDisable:
        mrs r0, cpsr
        mvn r2, $0b10000000
        orr r2, r2, r0
        msr cpsr, r0
		cpsid i
        mov pc, lr
This is the way I program the timer:

Code: Select all

void init_interrupts(){
	hdmi_console_putString("init_interrupts",15);
	*Enable_IRQsB = 0x000000ff;
	irqEnable();
	*Timer_Compare1=*TimerStamp_Low+0x00000100;
}
Being:

Code: Select all

static unsigned int *Enable_IRQsB = (unsigned int*)0x2000B218;
static unsigned int *Timer_Compare1 = (unsigned int *)0x20003010;
Thanks a lot for your help.

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: System Timer Interrupts? (Or using interrupts at all)

Tue Mar 11, 2014 1:50 am

OK, you're trying to use The system timer, specifically System Timer Compare 1. As the first few posts in this thread note, the SoC documentation isn't very good here. In particular it doesn't bother telling you which interrupt to enable :-) In the absence of this critical bit of information, you seem to be trying to enable everything in Base Interrupt enable register. Good guess, but no.

You need to set bit 1 (ie 1 << 1 = 2) (for ST_C1) in Interrupt Enable Register 1 (that's at 0x2000B210). [ instead of doing *Enable_IRQsB = 0x000000ff;]

Code: Select all

static unsigned int *Enable_IRQs1 = (unsigned int*)0x2000B210;
...
*Enable_IRQs1 = 1 << 1;
Regarding the comment in kIrq: //There is no need to clean status for timer int?

Yes, there is a need to clear the interrupt, by writing a 1 to bit 1 of the CS register. See p.172 of the SoC doc.


The rest of the code has a couple of oddities:

1. in your interrupt enable/disable routines you don't need cpsie i and
mrs r0, cpsr
bic r0, $0b10000000
msr cpsr, r0


They do the same thing. The cpsie i is less to type though. :)

2. I'm not sure what your loop: bit of code is supposed to do. It looks like a bit of copy/paste that shouldn't be there.

dwelch67
Posts: 971
Joined: Sat May 26, 2012 5:32 pm

Re: System Timer Interrupts? (Or using interrupts at all)

Wed Mar 12, 2014 2:08 am

I think both here in other bare metal forum posts and in my examples at github I showed it is pretty straight forward to just poll the interrupt status registers,and figure out from that which interrupt is the one tied to whatever it is you have enabled. You dont and wont want to enable the arm processor interrupt and write a handler until you know that.

there are some interrupts that the GPU is using if you simply poll the register(s) and print out ANY changes you will get some periodic stuff that is not the interrupt you are searching for. So you would then mask those bits out of your print any change.

Basically I have been able to use this approach to isolate which interrupt is which on this platform and elsewhere, fairly quickly...Once you know or think you know which interrupt line is tied to your peripheral, you can with polling clear it through the peripheral see via polling the interrupt status register(s) again that it cleared. Then continue with the education of that peripheral and the last thing would be to then actually interrupt the processor and deal with the processor side stuff if any of clearing/managing its interrupt controller.

David

SKyd3R
Posts: 11
Joined: Thu Nov 14, 2013 9:30 am

Re: System Timer Interrupts? (Or using interrupts at all)

Wed Mar 12, 2014 12:15 pm

That post was really useful colinh, thanks a lot.

But since I read dwelch67's post I wonder how I could know what interrupt is the handler running for. I mean, there are lots of interrupts that could trigger the irq handler, and I can find out the pending interrupts but I don't know how to check what interrupt causes the handler's execution.

dwelch67
Posts: 971
Joined: Sat May 26, 2012 5:32 pm

Re: System Timer Interrupts? (Or using interrupts at all)

Wed Mar 12, 2014 6:48 pm

I think that core has basically just the irq and the fiq inputs, so you just read the pending interrupt status register at the beginning of the handler (if you have more than one interrupt you know you have enabled) and then from that you know which one or ones are pending, you go into a loop and you stay in the handler until all the pending interrupt bits for interrupts you are handling are cleared.

Newer/different arm processors have a much more complicated interrupt scheme with as many as 256 discrete interrupts, and there you either get in some register or some easy to get to place a value that indicates what caused the interrupt (if it is a single entry point). the cortex-ms have dozens/hundreds of individual vectors so you have a handler for every discrete interrupt.

fiq vs irq on the arm11 and other traditional single interrupt arms (dual fiq and irq), depending on the chip/system design, can give you the option of isolating one or a few of the interrupts into the fiq handler making the figuring out who caused it easier.

David

Return to “Bare metal, Assembly language”