2013년 6월 7일 금요일

Stellaris Launchpad SysTick Interrupt 사용하기

SysTick 인터럽트를 사용하여 LED를 점멸시켜 보도록 하겠다.


  1. #include "inc/hw_types.h"
  2. #include "inc/hw_memmap.h"
  3. #include "driverlib/systick.h"
  4. #include "driverlib/interrupt.h"
  5. #include "driverlib/sysctl.h"
  6. #include "driverlib/gpio.h"
  7. #include "driverlib/rom.h"
  8. #include "driverlib/pin_map.h"

  9. #define LED_RED GPIO_PIN_1
  10. #define LED_BLUE GPIO_PIN_2
  11. #define LED_GREEN GPIO_PIN_3

  12. const unsigned char color[] = {0x2, 0x6, 0x4, 0xc, 0x8, 0xa};
  13. unsigned char color_sz;

  14. void SysTickIntHandler(void);

  15. int main(void)
  16. {
  17. color_sz = sizeof(color);

  18. ROM_SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
  19. ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
  20. ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, LED_RED|LED_BLUE|LED_GREEN);
  21. ROM_GPIOPinWrite(GPIO_PORTF_BASE, LED_RED|LED_GREEN|LED_BLUE, color[5]);

  22. ROM_SysTickPeriodSet(8000000-1);  // 0.5 sec
  23. ROM_SysTickEnable();
  24. ROM_SysTickIntEnable();
  25. ROM_IntMasterEnable();      // CPSIE instruction

  26. while (1) {
  27. }
  28.  }

  29. void SysTickIntHandler(void)
  30. {
  31. static unsigned char idx = 0;

  32. ROM_GPIOPinWrite(GPIO_PORTF_BASE, LED_RED | LED_GREEN | LED_BLUE, color[idx]);
  33. idx = (idx+1)%color_sz;
  34. }


코드는 위와 같다. 위의 코드에서 일정 시간마다 SysTick 인터럽트가 발생하면 37~43 라인의 SysTickIntHandler 함수가 호출되게 된다. 그러므로 main() 함수에서는 초기 설정을 제외하면 메인 루프(33~34라인)에서는 아무 것도 하지 않고 단순히 무한루프를 돌고 있게 된다.

28~31에서 SysTick 인터럽트를 사용하기 위한 설정을 하고 인터럽트를 활성화 시켜주게 되는데 실제 SysTick 인터럽트가 발생했을 때 SysTickIntHandler()를 호출하게 해 주기 위해서는 startup_gcc.c에 있는 인터럽트 벡터 테이블을 수정해 줘야만 한다.

startup_gcc.c는 이전 포스트(Stellaris Launchpad #1)에서 사용했던것과 동일한 startup_gcc.c (~/stellarisware/boards/ek-lm4f120xl/blinky/startup_gcc.c) 를 약간 수정해서 사용한다.


...
//*****************************************************************************
//
// The entry point for the application.
//
//*****************************************************************************
extern int main(void);

// External Interrupt handler declaration

void SysTickIntHandler(void);

//*****************************************************************************
//
// Reserve space for the system stack.
//
//*****************************************************************************
static unsigned long pulStack[64];
...
    IntDefaultHandler,                      // The PendSV handler
    SysTickIntHandler,                      // The SysTick handler
    IntDefaultHandler,                      // GPIO Port A
...


빨간색 라인을 추가하고 파란색 라인 부분은 원래 IntDefaultHandler,      // the SysTick handler 로 되어 있는데 IntDefaultHandler 대신 파란색 부분 같이 SysTick 인터럽트가 발생했을 때 실제 호출될 인터럽트 핸들러 함수 이름으로 바꿔주면 된다.

링커 스트립트 파일과 Makefile은 이전에 사용한것을 그대로 사용해 주면 된다.

정상적으로 바이너리 파일을 만들어 보드로 다운로드 하면 LED D1의 색깔이 주기적으로 바뀌는 걸 볼 수 있다.

Stellaris Launchpad #1

Stellaris Launchpad 환경설정이 끝났으면 실제 프로그램을 플래쉬로 옮겨 실행시켜 보겠다.

TI stellaris launchpad에 들어 있는 LM4F 프로세서에는 칩의 ROM에 stellarisware peripheral access library 가 이미 들어있기 때문에 그 함수들을 사용하면 되고 그런 함수들은 함수 이름이 'ROM_'으로 시작한다.

일단 간단한 프로그램을 만들어 보자. 파일 이름은 ledtest1.c로 하겠다.



  1. #include "inc/hw_gpio.h"
  2. #include "inc/hw_memmap.h"
  3. #include "inc/hw_sysctl.h"
  4. #include "inc/hw_types.h"
  5. #include "driverlib/gpio.h"
  6. #include "driverlib/rom.h"
  7. #include "driverlib/sysctl.h"
  8.  
  9. #define LED_RED GPIO_PIN_1
  10. #define LED_BLUE GPIO_PIN_2
  11. #define LED_GREEN GPIO_PIN_3
  12.  
  13. int main()
  14. {
  15.   ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 SYSCTL_USE_PLL SYSCTL_XTAL_16MHZ SYSCTL_OSC_MAIN);
  16.   ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
  17.   ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, LED_RED|LED_BLUE|LED_GREEN);
  18.   for (;;) {
  19.     // set the red LED pin high, others low
  20.     ROM_GPIOPinWrite(GPIO_PORTF_BASE, LED_RED|LED_GREEN|LED_BLUE, LED_RED);
  21.     ROM_SysCtlDelay(5000000);
  22.     ROM_GPIOPinWrite(GPIO_PORTF_BASE, LED_RED|LED_GREEN|LED_BLUE, 0);
  23.     ROM_SysCtlDelay(5000000);
  24.   }
  25. }



    위의 프로그램을 컴파일해서 stellaris launchpad에 다운로드 할 수 있는 바이너리 파일을 만들기 위해서는 startup 파일과 linker script 파일이 필요하다.

    컴파일러에 따라 다른 파일이 필요한데 맥에서 cross-gcc(arm-none-eabi-gcc)를 사용하는 경우 stellarisware에 들어있는 startup_gcc.c (~/stellarisware/boards/ek-lm4f120xl/blinky/startup_gcc.c)와 blinky.ld (~/stellarisware/boards/ek-lm4f120xl/blinky/blinky.ld) 파일을 사용하면 된다.

    startup_gcc.c 파일을 위의 소스코드와 같은 디렉토리에 복사 해 넣은 다음 아래와 같은 Makefile을 만들어 준다.


    1. #
    2. # Makefile for Stellaris Launchpad
    3. #

    4. STELLARISDIR=/Users/nautes/stellarisware
    5. PROCESSOR=LM4F120H5QR
    6. LOADER_SCRIPT=blinky.ld

    7. CC=arm-none-eabi-gcc
    8. CFLAGS=-g \
    9. -mthumb \
    10. -mcpu=cortex-m4 \
    11. -mfpu=fpv4-sp-d16 \
    12. -mfloat-abi=softfp \
    13. -Os \
    14. -ffunction-sections \
    15. -fdata-sections \
    16. -MD \
    17. -std=c99 \
    18. -Wall \
    19. -pedantic \
    20. -DPART_${PROCESSOR} \
    21. -c \
    22. -I${STELLARISDIR} \
    23. -DTARGET_IS_BLIZZARD_RA1

    24. TARGET:=ledtest1
    25. BOOTSTRAP:=startup_gcc.o

    26. SRCS:=ledtest1.c
    27. OBJS:=$(SRCS:.c=.o) $(BOOTSTRAP)

    28. .c.o:
    29. ${CC} ${CFLAGS} $<
    30. $(TARGET): $(OBJS)
    31. # arm-none-eabi-ld -T ${LOADER_SCRIPT} --entry ResetISR -o $@ ${BOOTSTRAP} ${TARGET}.o --gc-sections
    32. arm-none-eabi-ld -T ${LOADER_SCRIPT} --entry ResetISR -o $@ $(OBJS) --gc-sections
    33. arm-none-eabi-size ${TARGET}
    34. arm-none-eabi-objcopy -O binary ${TARGET} ${TARGET}.bin

    35. clean:
    36. rm ${TARGET} *.d *.o *.bin
    5번 라인에서 빨간색 부분은 자신이 stellarisware를 설치한 디렉토리 이름으로 바꿔줘야만 한다.

    디렉토리에 ledtest1.c, blinky.ld, startup_gcc.c, Makefile이 다 있으면 프로그램을 make하면 된다.

    $ ls
    Makefile blinky.ld ledtest1.c startup_gcc.c
    $ make
    arm-none-eabi-gcc -g -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -Os -ffunction-sections -fdata-sections -MD -std=c99 -Wall -pedantic -DPART_LM4F120H5QR -c -I/Users/nautes/stellarisware -DTARGET_IS_BLIZZARD_RA1 ledtest1.c
    arm-none-eabi-gcc -g -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -Os -ffunction-sections -fdata-sections -MD -std=c99 -Wall -pedantic -DPART_LM4F120H5QR -c -I/Users/nautes/stellarisware -DTARGET_IS_BLIZZARD_RA1 startup_gcc.c
    arm-none-eabi-ld -T blinky.ld --entry ResetISR -o ledtest1 ledtest1.o startup_gcc.o --gc-sections
    arm-none-eabi-size ledtest1
       text   data    bss    dec    hex filename
        902      0    261   1163    48b ledtest1
    arm-none-eabi-objcopy -O binary ledtest1 ledtest1.bin
    $ lm4flash ledtest1.bin
    ICDI version: 9270
    $

    lm4flash 명령이 정상적으로 실행되면 빌드 된 바이너리 파일이 보드로 다운로드 되고 바로 실행이 시작되기 때문에 보드의 리셋스위치 바로 아래 있는 D1 LED(아래 사진의 파란색 원 부분)가 빨간색으로 반짝이는걸 볼 수 있다.