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(아래 사진의 파란색 원 부분)가 빨간색으로 반짝이는걸 볼 수 있다.



    2013년 5월 30일 목요일

    HoRNDIS - 맥용 RNDIS 드라이버

    대부분의 ARM 개발 보드 또는 안드로이드 폰의 Native USB tethering 기능을 사용하려면 필수적으로 필요한것이 RNDIS 프로토콜 드라이버이다. 
    RNDIS 프로토콜은 MS에서 개발한 자체 프로토콜이라 Mac OS X에서 사용하기가 거의 힘들었다.
    하지만 HoRNDIS가 나와 이제 맥에서도 RNDIS 프로토콜을 사용할 수 있게 되었다.
    kext 형태이기 때문에 TAP/TUN kext를 사용하는 프로그램들(OpenVPN, CISCO VPN, tunnelblick등)과도 충돌하지 않고 사용할 수 있다.

    http://joshuawise.com/horndis-screenshot.png
    HoRNDIS (http://joshuawise.com/horndis) 를 설치해주고 RNDIS 프로토콜을 사용하는 장치를 USB포트에 연결하면 위와 같이 새로운 네트웍 디바이스가 보이게 되므로 필요한 설정을 해 주면 된다.