John's 개발자의 관심노트

[FTDI] V2DIP1 사용 후기! USB 개발, USB Bridge 개발 본문

[개발]/그 외 개발환경

[FTDI] V2DIP1 사용 후기! USB 개발, USB Bridge 개발

John-Co 2022. 10. 25. 18:33

V2DIP1-32 개발보드

FTDI 의 V2DIP1 을 가지고 개발할 기회가 생겨서 FTDI 칩을 프로그래밍 해봤는데,

삽질을 좀 너무 많이해서 다시는 잊어먹지 않기위해 글을 적어두려고한다.

 

이거 하면서 진짜 개발자 때려처야하나 라는 생각이 들정도로 삽질을 많이했다...

나는 펌웨어 개발 시 처음 접하는 개발환경일때는 GPIO 제어부터 먼저 해본다.

Library 사용법과 친숙해질 겸, 내가 셋업한 개발환경이 잘 동작하는지 등을 살펴보기 위함이다.

 

근데 GPIO 제어 하나 하는데 반나절 걸렸다... 자괴감 폭발 ...

어떤건 이름에도 IN, OUT 뭐 엉망진창이다 ... 돌아버리는줄 알았다 ... 

저 글자 찾는데 엄청난 시간을 들였다... 왜 안되지... 왜 안될까 ... 한 글자 한 글자 찾아보다가 발견!

 

첫 번째 삽질은, "IOMUX" 이놈 때문에 헷갈렸다.

 

FTDI 에서 제공해주는 Library 환경에서는 PORTA0~7, PORTB0~7 등등 을

내가 원하는 특정 핀과 자유롭게 라우팅해서 사용할 수 있다.

 

자유도가 높아서 좋긴한데, 처음 이 환경을 접했을 때 해메는 부분이 너무 컸다.

 

"vos_iomux_define_output""vos_iomux_define_input" 이라는 API 함수와,

"IOMUX_OUT_GPIO_PORT_X_X" 와, "IOMUX_IN_GPIO_PORT_X_X" 라는 인덱스 값...

그냥 지나치면, IN 과 OUT 을 못보고 지나친 다음에 왜 안돼지 머리 싸메고 있는 스스로를 보게 된다.

 

만일 내가 IC 의 Pin number 10번을 PORT A 의 0번으로 라우팅하고, A0 핀을 출력모드로 설정하려면,

vos_iomux_define_output(10, IOMUX_OUT_GPIO_PORT_A_0);

이런 코드가 된다.

 

물론 나의 부주의로 지나쳤지만, 너무 쓰기 까다롭다.

저 코드에서 단 하나라도 매칭이 잘못되면 동작하지 않으니 참고해야한다.

 

이 다음은, 해당 Port 의 PIN 설정을 해주는 작업이다.

여기서 진짜 멘붕이였다.

   vos_gpio_set_pin_mode(uint8 pinId, uint8 mask);

   vos_gpio_set_port_mode(uint8 portId, uint8 mask);

이 두놈 때문에 거의 2시간을 흘려보냈다.

 

코딩하고 확인하고 다시 확인해도 아무리봐도 맞는데 동작을 안한다.

문서를 구석구석 살피다보니... 지금 라이브러리에서는 해당 함수를 지원하지 않는단다...

이거 개발보드 걍 버리고 싶은 생각이 격하게 들었다.

VNC2 User Guide "해당 함수를 지원하지 사용하지 않는다는 내용"

나를 너무 힘들게하는 FTDI 칩...

어찌되었든 여기까지 시간을 들였으니, 끝까지 가보자는 마음으로 하나 하나 완성을 해나갔다.

 

그 결과 내가 파악한 내용은,

 

VNC2 의 Driver 사용을 위해서는 아래와 같은 작업이 필요하다.

Driver 사용 전, 기본적인 Setup 을 해줘야 하는데

GPIO 는 "gpio_init()" 함수,

UART 는 "uart_init()" 함수,

SPI 는 "spi_init()" 함수를 이용해서,

기본적인 셋업을 진행해주고,

 

해당 셋업 완료 후, Driver Open 함수를 통해서 Hnadle 값을 얻어온다.

이때 사용하는 함수는 "vos_dev_open()" 함수다.

 

이제 반환 받은 핸들을 가지고 세부 컨트롤 작업을 하면되는데,

이 때 사용하는 함수는 "vos_dev_ioctl()" 함수고,

 

이 이후부터는 각 Driver 별로 제공되는 동작 함수들을 사용해서 Application 을 구현하면 된다.

 

위 내용을 GPIO Driver 기반으로 코드를 작성하면 아래와 같다.

(주석도 열심히 달아두었으니, 저 말고 다른분은 삽질하지 않길 바랍니다.)

#incldue "GPIO.h"

#define VOS_DEV_GPIO 0       // 사용할 Driver 순서별로 0,1,2 ... 할당
#define VOS_NUMBER_DEVICES 1 // 총 Open 한 Driver 갯수

VOS_HANDLE hGPIO;    // Handle 할당 및 저장을 위한 변수
vos_tcb_t *tcvGPIO;  // Thread 생성을 위한 스택 포인터

void main(void)
{
    /* FTDI:SKI Kernel Initialisation */
    vos_init(50, VOS_TICK_INTERVAL, VOS_NUMBER_DEVICES);
    vos_set_clock_frequency(VOS_48MHZ_CLOCK_FREQUENCY);
    vos_set_idle_thread_tcb_size(512);
    
    // GPIO 핸들 생성을 위한 컨텍스트
    gpio_context_t gpio_ctx;
    
    // GPIO Thread 생성
    tcvGPIO = vos_create_thread_ex(20, 512, GPIO_THREAD, "Task GPIO", 0);
    
    // Thread Scheduling 시작
    vos_start_scheduler();
    
    while(TRUE)
    {
    	;
    }
}

위 "main()" 함수에서 생성한 GPIO Thread 함수는 아래와 같다.

void GPIO_THREAD()
{
    uint8 ret = 0;
    uint8 data = 0x01;
    uint16 written;
    gpio_ioctl_cb_t ioctl_cb;

    // Handle Open
    hGPIO = vos_dev_open(VOS_DEV_GPIO);

    // PORT A 의 0~3 번 핀을 OUT 으로 설정
    gpio_ioctl_cb.ioctl_code = VOS_IOCTL_GPIO_SET_MASK;
    
    // value 는 bit 별로, b0 = PORTA0, b1 = PORTA1 ...
    gpio_ioctl_cb.value = 0x0f;
    
    // PORT A Pin Configuration
    vos_dev_ioctl(hGPIO, &ioctl_cb);

    while(TRUE)
    {
        // PORT A의 0~3 번 핀을 High 설정
        // data 는 bit 별로, b0 = PORTA0, b1 = PORTA1 ...
        data = 0x0f;
        vos_delay_msecs(100);
        vos_dev_write(hGPIO, &data, 1, &written);

        // PORT A의 0~3 번 핀을 Low 설정
        data = 0x00;
        vos_delay_msecs(100);
        vos_dev_write(hGPIO, &data, 1, &written);
    }
}

위 코드를 작업하고, 12번핀을 오실로스코프로 찍어보면 아래와 같은 출력결과를 확인할 수 있다.

오실로스코프 출력

이로써 VNC2 개발환경과 친해지기 끝!

반응형