2016년 10월 28일 금요일

어셈블리 코드로 함수만들고 컴파일


라즈베리파이의 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>


#define S_P_SIGNAL_PIN1 7
#define S_P_SIGNAL_PIN2 25

void startISR(void) {
   printf("falling edge detected\n");
}

void stopISR(void) {
   printf("rising edge detected.\n");
}

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;
  }

  if ( wiringPiISR (S_P_SIGNAL_PIN2, INT_EDGE_RISING, &stopISR) < 0 ) {
      fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno));
      return 1;
  }

  while ( 1 ) {
    printf("interrupt disable------\n");
disable();
delay(1000);
printf("interrupt enable------\n");
enable();
delay(1000);
  }

  return 0;
}

어셈블리 코드(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



gcc -c interrupt.c
as -o interruptASM.o interruptASM.s
gcc -o interrupt interrupt.o interruptASM.o
sudo ./interrupt


참고
ARM assambler in Raspberry Pi:
http://thinkingeek.com/2013/01/09/arm-assembler-raspberry-pi-chapter-1/

댓글 없음:

댓글 쓰기

clear images were obtained