라즈베리파이의 GPIO 인터럽트를 disable을 하는 방법을 찾던 중에 라즈베리파이에서 asambly languge를 써서 함수를 만들어서, 이 함수를 c언어로 쓴 프로그램에서 사용하는 방법을 써보았다. 이 방법을 사용해서 인터럽트를 disable하는 것은 실패했지만 asambly어를 사용했다는 점과 이것을 c언어로 작성한 프로그램과 합쳤다는 점에서 기록할 만하다.
c코드 main문에 disable()과 enable() 함수는 어셈블리어로 만들었다. 왜냐하면 내부 레지스터를 건드려야 하기 때문에.
c코드(interrupt.c):
//the program for detecting interrupt of falling edge and rising edge on the gpio pin.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <wiringPi.h>
int main(void) {
// sets up the wiringPi library
if (wiringPiSetup () < 0) {
fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno));
return 1;
}
// set Pin 17/0 generate an interrupt on high-to-low transitions
// and attach myInterrupt() to the interrupt
if ( wiringPiISR (S_P_SIGNAL_PIN1, INT_EDGE_FALLING, &startISR) < 0 ) {
fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno));
return 1;
}
어셈블리 코드(interruptASM.s):
//코드 출처: http://embedded-xinu.readthedocs.io/en/latest/arm/ARM-Interrupt-Handling.html#disable
/**
* @file intutils.S
*
* Functions to enable, disable, or restore global interrupts on the ARM.
*
* See http://xinu-os.org/Interrupt_handling_(ARM) for more information.
*/
/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */
.globl enable
.globl disable
.globl restore
/**
* @fn void enable(void)
*
* Enable interrupts globally.
*/
enable: .func enable cpsie i mov pc, lr .endfunc
/**
* @fn irqmask disable(void)
*
* Disable interrupts globally and returns the old state.
* @return state of interrupts before they were disabled
*/
disable: .func disable mrs r0, cpsr cpsid i mov pc, lr .endfunc
/**
* @fn irqmask restore(irqmask)
*
* Restores the global interrupt mask to a previous state.
* @param im
* irqmask of interrupt state to restore
* @return state of interrupts when called
*/
restore: .func restore msr cpsr_c, r0 mov pc, lr .endfunc