DSP

TMS320C6748 을 활용한 DSP _ GPIO (LAB1)

알 수 없는 사용자 2019. 9. 19. 03:52
반응형

<이 내용은 강원대학교 전자공학과 실시간 신호처리 과목에서 진행된 내용을 기반으로 작성되었습니다.>

 

 

이번에 다루는 내용은 단순한 GPIO포트 설정을 통해 LED를 조작하는 내용이다.

기초중의 기초인 LED 조작을 예제를 통해 하나씩 하나씩 많은 것들을 알아 가보자.

 

시작에 앞서 중요한 사실을 하나 언급하고 가도록 한다.

보드를 자세히 보면 중앙에 스위치가 8개 달려있는 것을 볼 수 있다. 이 스위치들은 딥스위치라 불린다. 딥스위치의 앞 4개는 부트모드를 설정하는데 사용되고, 4개는 유저모드로 사용할 수 있다. Offhigh, On이면 low로 인식된다.

 

 

GPIO

해당 보드에는 푸시버튼 스위치 3개와(하나는 리셋스위치여서 유저스위치는 2개이다.) 4개의 유저 LED가 있다. 해당 기능들은 GPIO포트에 연결되어 있다.

보통 임베디드를 위한 보드들은 GPIO포트가 default 설정인 경우가 많다. 하지만 DSP를 위한 우리의 보드는 GPIO포트가 default 설정이 아니다. 따라서 GPIO를 사용하기 위해서는 하나씩 설정을 해 주어야 한다. (GPIO 설정 시 direction 설정 또한 해줘야 한다.)

 

 GPIO는 뱅크로 묶여져 있다. 핀을 표기 할 때 GPIO0-1 이런 식으로 표기를 하는데, 0은 뱅크를 나타내는 숫자이다. 16개를 하나의 뱅크로 묶어 총 8개의 뱅크가 존재한다.

 

 원하는 핀을 정확한 위치에 매칭시키기 위해 SysConfigForPinMux( ) 함수를 실행시켰다. 이 함수는 다음 사진과 같은 내용을 담고 있다.

 

여기서 CSL_FINST는 매크로이다.

매크로에서 ##은 매크로 변수를 이어 하나의 문자열 형태로 바꾸어준다.

 

CSL_FINST(sys0Regs->PINMUX13, SYSCFG_PINMUX13_PINMUX13_11_8, GPIO6_13);

위의 문장에서 CSL_FINS( )로 넘어가는 가장 마지막 인자는 “CSL_SYSCFG_PINMUX13_PINMUX13_11_8_GPIO6_13” 이 될 것이다. 그러면 해당 인자를 넘겨받은 CSL_FINS( ) val값에 맞는 크기 만큼 시프트를 시킨 후 OR를 통해 field insert를 진행한다. 한마디로 해당 핀의 레지스터를 찾아가 그 핀의 사용정보를 GPIO로 설정해주는 것이다.

 

그런데 PINMUX13은 어디에 정의되어 있을까? 따라가보자.

 

어마무시하다. 해당파일은 이전에 설치한 퀵스타트를 통해 자동으로 생성된 파일이다. 보드는 정확하게 저런 형태의 레지스터를 가지고 있다. 레지스터의 시작 번지는 항상 연속적인 것이 아니다. 중간중간 비어있는 숫자들이 있는 경우도 많다. 자세히 보면 RSVD라는 변수명들이 섞여있는 것을 확인 할 수 있다. RSVD는 바로 이런 빈 공간들을 나타낸 것들이다. 빈 공간까지 표현해 두었기 때문에 이제 구조체의 변수를 정확히 시작 변수에 만들어 놓으면 레지스터에 올바르게 접근이 가능한 것이다.

이렇게 말이다. 이렇게 sys0Regs라는 포인터만 만들어서 쓴 것이다. 완벽하다.

 

+ 위 레지스터 이름들 중 KICK0R, KICK1R이라는 레지스터가 있다. 이 레지스터들은 시스템과 관련된 레지스터를 변경 시 키 레지스터를 넣어주고 그 뒤에 시스템 레지스터를 변경 가능하도록 할 때 사용되는 레지스터이다.

 

 이제 원하는 핀들을 GPIO로 설정하였다. 하지만 한가지 하지 않은 것이 있다. 바로 direction이다. , in, out을 정해야 한다. 이건 관련 레지스터가 존재하여서 그 레지스터 값을 0 또는 1로 설정할 때 정해진다. 이 설정을 LED_DIPSW_Init(); 에서 해준 것이다.

Interrupt

LED를 키고 끄는 것은 단순한 GPIO 설정만으로 가능했다. 하지만 버튼을 사용할 땐 인터럽트를 사용할 줄 알아야 한다.

GP2P4같은건 푸쉬버튼이다. 푸쉬버튼은 보통 이벤트를 발동 시킬 용도로 사용하기 때문에 인터럽트 용도로 사용하려 한다. 모든 gpio핀은 다 인터럽트를 발생시킬 수 있다. 대신 설정을 해줘야 한다. gpio핀이 100개쯤 있으면 인터럽트를 발생시킬 수 있는 핀은 100개가 다 되지는 않는다. 뱅크 하나당 한개씩의 인터럽트를 수용할 수 있다. 뱅크는 핀 16개라고 앞에서 설명하였다.

 

인터럽트는 뱅크의 인터럽트로 인식된다. 그럼 각 핀 당 인터럽트를 하려면..? 뱅크가 달라야 한다... 그러나 사실 실질적으로 인터럽트는 많이 만들 수 있다. 구별가능한 뱅크는 개수가 정해져 있지만 내부에 status 레지스터가 하나 있어서 어느 핀에 의해서 인터럽트가 발생했는지 알 수 있다. 즉 원한다면 뱅크에 의한 인터럽트에서 해당 레지스터를 살펴 본 후 어느 핀에 의해 인터럽트가 발생했는지 판별 할 수 있다.(나중에 살펴보도록 하겠다.)

 

어찌되었든 인터럽트는 뱅크 단위로 설정할 수 있다.

위 사진을 보자.

 

GPIO_EnableInterrupt( 2, ENABLE ); 는 뱅크 2를 인터럽트 인에이블 한다.

GPIO_ClearInterruptState( GP2 ); 이게 바로 state 레지스터를 초기화 시키는 것이다.

리셋을 걸면 대부분 초기값을 가진다. 근데 개발환경에서 쓸 때 다운로드 시 발생하는 리셋은 파워리셋과 다르게 동작한다. 그래서 일부 레지스터들은 초기화가 되지 않을 수 있다. 만약 전원을 끄고 켜야 동작한다면 레지스터가 초기화가 안된 것이다.

 

DSP는 사실 일종의 advanced micro process 이다. 그렇기 때문에 기본적인 led조작부터 시작한 것이다!

반응형