Posts: 6
Joined: Wed Oct 30, 2019 1:58 pm

[ASM][raspbian][RPi3] interrupt handler

Sat Nov 16, 2019 1:21 am

When an interrupt occurs (for example IRQ), the program stops current operation and goes to a known location in memory, in this case 0x18, and then executes the instructions stored at this address.

Could someone tell, how to (under raspbian) declare a subroutine that points to the address of IRQ vector?
I use GCC assembler.

Posts: 1311
Joined: Wed Dec 07, 2016 2:29 pm

Re: [ASM][raspbian][RPi3] interrupt handler

Sat Nov 16, 2019 2:27 am

You don't get to play with any of that on linux you request to install an interrupt
google "linux request_irq"

What was said on other thread still stands you have responsibilities and some things are protected and you have no access without security checks.

Please stay in one area and don't cross point posts to multiple areas. Either area is fine just choose one.

There is a slightly easier way on linux because it already has timers with callback and they deal with all the interrrupt stuff for you.
It's probably the safest way to play until you learn some more and it does pretty much what you want all be it with a bit more jitter and 1 msec accuracy.

It goes like this

Code: Select all

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/timer.h>

/* Your timer struct created so you can play with timer */ 
static struct timer_list my_timer;

void my_timer_callback( unsigned long data )
     /* do your timer stuff here */

void cleanup_my_timer (void)
    /* remove kernel timer when unloading module */

int main (void)
  /* setup your timer to call my_timer_callback */
  setup_timer(&my_timer, my_timer_callback, 0);

  /* setup timer interval to 1000 msecs */
  mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000));

/* Do some stuff and use timer */

/* Release the timer callback */

  return 0;

Posts: 6
Joined: Wed Oct 30, 2019 1:58 pm

Re: [ASM][raspbian][RPi3] interrupt handler

Sat Nov 16, 2019 3:42 pm

Thanks for your answer.
It may not have helped me directly - because I do not know C language, so I do not know how to use the code you provided - but I remembered about syscalls :)

It seems that sys_nanosleep probably suits my application. (blinking LED)
Here is the code I made. The LED blinks for 30 seconds every one second. Although I have the impression that sometimes it is not one second.
If anyone has a better suggestion (in pure assembly, without insertions in C), it would be nice to share it here ;)

Code: Select all

	.global _start

@do not forget about sudo!!!


ldr	r0, =mem
ldr	r1, =0x101002	/* O_RDWR | O_SYNC */
mov	r7, #5		/* open */
svc	#0
mov	r4, r0		/* file descriptor */

mov	r0, #0		/* kernel chooses address */
mov	r1, #4096	/* map size */
mov	r2, #3		/* PROT_READ | PROT_WRITE */
mov	r3, #1		/* MAP_SHARED */
@ldr	r5, =0x3F003	/* offset SYSTEM TIMER*/
@ldr	r5, =0x3F00B	/* offset ARM TIMER*/
ldr	r5, =0x3F200	/* offset GPIO */ 
mov	r7, #192	/* mmap2 */
swi	0

@access GPIOs via r0
			@set pin18 as output
ldr	r1, [r0, #4]	@read GPSEL1
orr	r1, r1, #1<<24	@bits 26-25-24=001
str 	r1, [r0, #4]	@set new configuration into GPSEL1

mov	r6, #30		@counter

cmp	r6, #0
beq	_exit

stmdb	sp!, {r0, r1, r7}
ldr     r0, =timespecsec
ldr     r1, =timespecsec
mov     r7, #162    		@ 162 syscall nanosleep
swi     0
ldmia	sp!, {r0, r1, r7}

sub	r6, r6, #1

tst	r6, #1
beq	_set
b	_clr

b 	_loop

mov	r0, #0		/* return code */
mov	r7, #248	/* exit */
svc	#0

_set:				@set pin18
stmdb	sp!, {r1, r2}
ldr 	r1, [r0, #28]		@read GPSET0
mov 	r2, #1			@set bit
mov 	r1, r2, lsl #18		@rotate to pin 18 and place in r1
str 	r1, [r0, #28]
ldmia	sp!, {r1, r2}
b	_set_clr_powrot

_clr:				@clr pin18
stmdb	sp!, {r1, r2}
ldr 	r1, [r0, #40]		@read GPCLR0
mov 	r2, #1			@clr bit
mov 	r1, r2, lsl #18		@rotate to pin 18 and place in r1
str 	r1, [r0, #40]
ldmia	sp!, {r1, r2}
b	_set_clr_powrot

mem:	.asciz	"/dev/mem"
timespecsec:   .word   1

Return to “Bare metal, Assembly language”