티스토리 뷰
이번글에서는 SPI의 송신과 수신 기능을 DMA를 이용하여 구현해보는 방법에 대해서 설명하도록 하겠다.
이미 앞의 글에서 설명한 DMA를 이용한 UART 송신 기능을 이해하였다면 이번 글에서 설명할 SPI 송수신 기능은 UART와 별다를것이 없음을 알게 될 것이다.
DMA를 이용한 SPI 송수신 기능을 확인하기 위한 회로는 SPI와 같은 회로를 사용하겠다.
STM32F reference manual의 DMA 챕터에서 SPI 송수신을 위한 DMA 채널 번호를 확인한다.
위의 표에서와 같이 SPI 송수신을 위한 DMA 채널은 2번과 3번임을 알 수 있다.
그리고, SPI에서 DMA를 이용한 송수신과 관련된 신호와 타이밍정보는 다음과 같은 그림을 보고 분석해 본다.
Manual 문서를 반복해서 읽고 난 후 DMA를 이용한 SPI통신을 수행하는 방법을 충분히 이해 했으면 실제로 코드를 만들어 보도록 하겠다.
SPI통신을 수행하기 위한 초기화 코드인 spi_init() 함수는 위와 같다.
4번줄에 TX와 RX 동작단계에서 DMA로 request 신호를 제공하기 위하여 DMA enable비트를 설정하여 주어야 한다.
SPI 통신을 위한 DMA controller 초기화 코드는 다음과 같다.
spi_dma_init()함수에서 DMA controller를 초기화 하는데, RX와 TX에 대해서 각각 초기화를 수행한다.
11, 18번 줄에서 peripheral address register에는 모두 SPI의 data register 주소를 알려준다.
나머지 코드는 TX, RX 모두 동일하고 단지 다른 것은 DMA read 동작을 peripheral에서 할것인지, memory에서 할것인지 알려주는 부분이다.
당연히 RX는 peripheral에서 read 동작을 수행하여야 하고, TX는 memory에서 read 동작을 수행하여야 하므로 각각의 동작에 맞게 direction 비트를 설정해 주어야 한다.
outbuf가 가리키는 주소에서 데이터를 내보내고, 수신된 데이터를 inbuf가 가리키는 주소에 넣어주기 위한 dma_spi_xfer() 함수는 위와 같다.
먼저 DMA controller의 동작을 중지 시키기 위하여 enable 비트를 clear한 후 rx channel의 memory address register에 inbuf 주소를 넣어주고, tx channel의 memory address register에는 outbuf 주소를 넣어준다. 송수신 데이터 크기는 모두 len값을 넣어준다.
Memory address와 counter값을 register에 써주고 난 후 곧바로 enable 비트를 set하여 DMA의 송수신 채널을 동작 시킨다. 이렇게 하면 SPI의 송신과 수신 기능이 동시에 동작하게 된다.
먼저 TX 동작이 완료 될때까지 기다린 후, TX 동작이 완료된것을 확인한 후 RX 동작이 완료될 때까지 기다린다.
마지막 RX 데이터가 메모리에 저장되면 dma_spi_xfer() 함수가 끝나게 된다.
ATtiny85의 Signature ID를 읽기 위한 코드는 위와 같다. 이 코드는 이미 이전에 설명하였으므로 여기에서는 설명을 생략한다.
main() 함수를 위와 같이 작성한 후 실제 보드에서 실행하여 원하는 결과가 나오는 지 확인해 본다.
원하는 결과가 제대로 나온것을 확인할 수 있다. 즉, DMA를 이용하여 SPI 송,수신 기능이 정상적으로 수행된것을 확인한 것이다.
역시, UART에서 만들어 본 코드처럼 CPU가 DMA에게 송수신 기능을 요청한 다음 그 기능이 완료되는 동안 다른 일을 할 수가 있다.
'ARM Cortex-M' 카테고리의 다른 글
DMA - ADC (0) | 2017.05.28 |
---|---|
DMA - UART (0) | 2017.05.22 |
DMA (2) | 2017.05.13 |
SPI (3) | 2017.05.03 |
I2C (0) | 2017.04.22 |