BaseFlight_USART - FabLabSeoul/WingProject GitHub Wiki
์คํ์์ค Multiwii BaseFlight์ USART ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ถ์ํ ๊ธ์ด๋ค. ์์ธํ ๋ด์ฉ๋ณด๋ค๋ ๊ฐ๋ ์ ์ผ๋ก ์ค๋ช ํ๋ค. ์์ธํ ์๊ณ ์ถ๋ค๋ฉด ์์ค๋ฅผ ๋ณด์.
์ด ๊ธ์ Stm32 value line discovery ๋ณด๋๋ฅผ ํ ๋๋ก ํ๊ณ ์๋ค.
์์ ๋ STM32\stm32vldiscovery_package\Project\Examples\Serial_Baseflight ๊ฒฝ๋ก์ ์๋ค. Base flight์ USART ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํด PC์ ์๋ฆฌ์ผ ํต์ ํ๋ ์์ ๋ค. ์์ํ๋ฉด Start ๋ฌธ์์ด์ ๋ณด๋ด๊ณ , ์ด ๊ฐ์ ๋ฌธ์๋ฅผ ๋ฐ์ผ๋ฉด, ๊ทธ ๋ฌธ์ ๊ทธ๋๋ก ์ฌ์ ์กํ๋ ์์ ๋ค.
###Baseflight USART
baseflight์ USART๋ ์ฌ๋ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ฌถ์ฌ์๋ ํํ๋ค.
- drv_uart.c,h : usart ์์ฑ ๋ฐ ์ด๊ธฐํ, ์ธํฐ๋ฝํธ ์ฒ๋ฆฌ
- drv_serial.c,h : usart ์ถ์ํ
- serial.c : baseflight ์ ์ฉ ์๋ฆฌ์ผํต์ ์ฒ๋ฆฌ, CLI(command line interface)
์ค์ baseflight์ USART ๋ถ๋ถ๋ง ๊ฐ์ ธ๋ค ์ฐ๊ณ ์ถ์ผ๋ฉด, drv_uart.c,h ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ง ์์ผ๋ฉด ๋๋ค. ๋๋จธ์ง ๋ ๊ฐ๋ baseflight์์ ์ฐ์ด๊ธฐ ์ํด ๋ชจ๋ํ ๋ ํํ๋ก ๋์ด์๋ค.
drv_serial.c,h
์๋ฆฌ์ผ ํต์ ์ ์ํ ํฌํธ ๊ตฌ์กฐ์ฒด์, ์๋ฆฌ์ผ ํฌํธ ์ถ์ํ๋ฅผ ์ํ ํจ์ ํฌ์ธํฐ ํ ์ด๋ธ์ ์ ์ธํ๊ณ ์๋ค.
๊ฐ์ฅ ํต์ฌ์ธ serialPort_t ๊ตฌ์กฐ์ฒด๋ฅผ ๋์ฌ๊ฒจ๋ณด์.
typedef enum portMode_t {
MODE_RX = 1 << 0,
MODE_TX = 1 << 1,
MODE_RXTX = MODE_RX | MODE_TX,
MODE_SBUS = 1 << 2,
} portMode_t;
typedef struct serialPort {
const struct serialPortVTable *vTable; // serial port ๊ฐ์ํจ์ ํ
์ด๋ธ, ํ์ฌ๋ ํ๋๋ง ์ฐ์.
portMode_t mode; // Rx,Tx ์ค์
uint32_t baudRate;
uint32_t rxBufferSize; // receiver buffer size
uint32_t txBufferSize; // transmitter buffer size
volatile uint8_t *rxBuffer; // receiver buffer pointer
volatile uint8_t *txBuffer; // transmitter buffer size
uint32_t rxBufferHead; // receiver buffer ์ ์ ๋ณด๊ฐ ์ ์ฅ๋ index
uint32_t rxBufferTail; // receiver buffer ์ ์ ๋ณด๊ฐ ์ ์ฅ๋ ์ฒซ ๋ฒ์งธ index
uint32_t txBufferHead; // transmitter buffer ์ ์ ๋ณด๊ฐ ์ ์ฅ๋ index
uint32_t txBufferTail; // transmitter buffer ์ ์ ๋ณด๊ฐ ์ ์ฅ๋ ์ฒซ ๋ฒ์งธ index
// FIXME rename member to rxCallback
serialReceiveCallbackPtr callback;
} serialPort_t;
mode, baudRate ๋ณ์๋ก ์ฐ๊ธฐ์ฉ, ์ฝ๊ธฐ์ฉ ํ์ ์ ๊ฒฐ์ ํ๋ฉฐ, Serial BaudRate๋ฅผ ์ค์ ํ๋ค.
์๋ฆฌ์ผํต์ ์ ์ํด ๋ฒํผ๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค. ๋ฒํผ๋ Ringํํ์ด๋ฉฐ, xxBufferHead ๋ณ์๊ฐ ์ ๋ณด๊ฐ ์ ์ฅ๋ index๋ฅผ ๊ฐ๋ฅดํค๋ฉฐ, xxBufferTail์ ์ฒซ ๋ฒ์งธ ์ ๋ณด๊ฐ ์ ์ฅ๋ index๋ฅผ ๊ฐ๋ฅดํจ๋ค. ์๋ฅผ๋ค์ด ๋ฒํผ์ ๋ณด๋ฅผ transmittํ๋ค๋ฉด, Tail index๋ถํฐ Head index๊น์ง ํ๋์ฉ ์ ์กํ๊ฒ ๋๋ค. ๋ชจ๋ ๋ฒํผ๊ฐ ์ ์ก ๋์๋ค๋ฉด, Tail index == Head index ์ํ๊ฐ ๋๋ค. ์ด ๋น๊ต๋ก ๋ฒํผ๊ฐ ๋น์ด์๋์ง ํ๋จํ๋ค.
C์ธ์ด๋ก C++์ virtual function์ ํ๋ด๋ธ ํจ์ ํฌ์ธํฐ ๊ตฌ์กฐ์ฒด serialPortVTable
์ด ์๋ค. ์ด ์์ ์์๋ ๋๊ฐ์ ํจ์๋ง ์ฌ์ฉํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์, ์ด ๊ตฌ์กฐ์ฒด๋ ์ฐ๊ณ ๋ ์์ง๋ง, ์ ๋๋ก ์ฐ์ง ์๊ณ ์๋ค.
serialPortVTable
์ ์๋ฆฌ์ผ read, write์ ์๋ฆฌ์ผ ํต์ ์ํ๋ฅผ ์ค์ ํ๊ณ , ์ป์ด์ค๋ ํจ์ํฌ์ธํฐ ๋ชจ์ ๊ตฌ์กฐ์ฒด๋ค.
struct serialPortVTable {
void (*serialWrite)(serialPort_t *instance, uint8_t ch);
uint8_t (*serialTotalBytesWaiting)(serialPort_t *instance);
uint8_t (*serialRead)(serialPort_t *instance);
// Specified baud rate may not be allowed by an implementation, use serialGetBaudRate to determine actual baud rate in use.
void (*serialSetBaudRate)(serialPort_t *instance, uint32_t baudRate);
bool (*isSerialTransmitBufferEmpty)(serialPort_t *instance);
void (*setMode)(serialPort_t *instance, portMode_t mode);
};
drv_serial.c ์์๋ drv_uart.c,h ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋ ํจ์๋ค์ ๋ํํ๊ณ ์๋ค. ์๋ฆฌ์ผํต์ ์ ๋ํ ์์ธํ ๋ด์ฉ์ drv_uart ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ํ์ธ ํ ์ ์๋ค.
drv_uart.c,h
USART ํต์ ์ ์ํ ํต์ฌ ๊ตฌ์กฐ์ฒด๊ฐ ์ ์ธ๋์ด์๊ณ , ์๋ฆฌ์ผํฌํธ๋ฅผ ์์ฑํ๊ณ , DMA, Interrupt๋ฅผ ์์ฑํ๊ณ , ์ธํฐ๋ฝํธ๋ฅผ ์ฒ๋ฆฌํ๋ ์ฝ๋๊ฐ ์๋ค. ๋ค์๋งํ๋ฉด, ์๋ฆฌ์ผํต์ ์ ํต์ฌ ์ฝ๋๊ฐ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋ค.
typedef struct {
serialPort_t port; // ์๋ฆฌ์ผ ํต์ ํฌํธ ์ ๋ณด
// FIXME these are uart specific and do not belong in here
DMA_Channel_TypeDef *rxDMAChannel; // receiver DMA ์ฑ๋ ํฌ์ธํฐ
DMA_Channel_TypeDef *txDMAChannel; // transmitter DMA ์ฑ๋ ํฌ์ธํฐ
uint32_t rxDMAIrq;
uint32_t txDMAIrq;
uint32_t rxDMAPos; // DMA reciever์ผ ๋, ๋ฒํผ๋ฅผ ์ฝ์ ์์น๋ฅผ ๋ํ๋ธ๋ค.
bool txDMAEmpty; // DMA buffer๊ฐ ๋น์ด์์ ๋ true๊ฐ ๋๋ค.
USART_TypeDef *USARTx; // ํต์ ํ๋ UART ํฌ์ธํฐ
} uartPort_t;
๊ตฌ์กฐ์ฒด uartPort_t๋ DMA๋ฐฉ์๊ณผ Interrupt ๋ฐฉ์ ๋ชจ๋๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ์ค๊ณ๋์ด ์๋ค. ์์ธํ ์๊ธฐํ์๋ฉด rxDMAChannel ์ด NULL์ด๋ผ๋ฉด ์ธํฐ๋ฝํธ ๋ฐฉ์์ ์ฌ์ฉํ๊ณ , NULL์ด ์๋๋ผ๋ฉด DMA๋ฐฉ์์ ์ฌ์ฉํด ์๋ฆฌ์ผํต์ ์ ํ๋ค.
์๋ฆฌ์ผํต์ ์ ๊ด๋ จ๋ ์ ๋ณด๋ serialPort_t port;
์์ ๊ด๋ฆฌํ๋ค. uartPort_t๋ DMA, Interrupt๋ฅผ ์ ์ด๋ฅผ ์ํ ๊ฐ์ฒด๋ผ๊ณ ๋ณด๋ฉด ๋๋ค.
drv_uart ํค๋ ํ์ผ
#pragma once
#define UART_BUFFER_SIZE 64
#define UART1_RX_BUFFER_SIZE 256
#define UART1_TX_BUFFER_SIZE 256
#define UART2_RX_BUFFER_SIZE 128
#define UART2_TX_BUFFER_SIZE 64
#define UART3_RX_BUFFER_SIZE 256
#define UART3_TX_BUFFER_SIZE 256
#define MAX_SERIAL_PORTS 3
// FIXME this is a uart_t really. Move the generic properties into a separate structure (serialPort_t) and update the code to use it
typedef struct {
serialPort_t port;
// FIXME these are uart specific and do not belong in here
DMA_Channel_TypeDef *rxDMAChannel; // receiver DMA ์ฑ๋ ํฌ์ธํฐ
DMA_Channel_TypeDef *txDMAChannel; // transmitter DMA ์ฑ๋ ํฌ์ธํฐ
uint32_t rxDMAIrq;
uint32_t txDMAIrq;
uint32_t rxDMAPos; // DMA reciever์ผ ๋, ๋ฒํผ๋ฅผ ์ฝ์ ์์น๋ฅผ ๋ํ๋ธ๋ค.
bool txDMAEmpty; // DMA buffer๊ฐ ๋น์ด์์ ๋ true๊ฐ ๋๋ค.
USART_TypeDef *USARTx;
} uartPort_t;
extern const struct serialPortVTable uartVTable[];
serialPort_t *uartOpen(USART_TypeDef *USARTx, serialReceiveCallbackPtr callback, uint32_t baudRate, portMode_t mode);
// serialPort API
void uartWrite(serialPort_t *instance, uint8_t ch);
uint8_t uartTotalBytesWaiting(serialPort_t *instance);
uint8_t uartRead(serialPort_t *instance);
void uartSetBaudRate(serialPort_t *s, uint32_t baudRate);
bool isUartTransmitBufferEmpty(serialPort_t *s);
์๋ฆฌ์ผํฌํธ๋ฅผ ์์ฑํ๋ ํจ์๋ uartOpen()
๋ค. USART1,2,3 ํฌํธ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ์์ฑ๋๋๋ฐ, baseflight๋ ๊ฐ USARTํฌํธ๋ง๋ค ์ ํด์ง ์ญํ ์ด ์๋ ๋ฏํ๋ค. ๊ณต์ฉ usart ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ฐ๊ณ ์ถ๋ค๋ฉด, serialUSART1,2,3()
ํจ์๋ฅผ ์์ ํด์ค์ผ ํ๋ค.
serialUSART1()
๋ก ์๋ฆฌ์ผํฌํธ๊ฐ ์์ฑ๋์๋ค๋ฉด, Transmitter๋ DMA channel4 ๋ก ๋์ํ๋ค. DMA1_Channel4_IRQn ์ผ๋ก DMA ์ธํฐ๋ฝํธ๋ก ์ ์ด ๋๋ค. receiver๋ DMA๋ก ๋์ํ๋ค. ์๋ฆฌ์ผํต์ ์ผ๋ก ๋ถํฐ ๋ฐ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ค๋ฉด, uartPort_t.rxDMAPos๋ฅผ ์ด์ฉํด์ผํ๋ค. rxDMAPos๋ ํต์ ์ผ๋ก๋ถํฐ ์ฝ์ ์ ๋ณด ๊ฐ์๋ฅผ ๋ปํ๋ฉฐ, read()
ํจ์๋ฅผ ํธ์ถ ํ ๋๋ง๋ค -1 ์ฉ ์ค์ด๋ ๋ค. rxDMAPos ๊ฐ๊ณผ๋ ๋ค๋ฅด๊ฒ ์ค์ ๋ฒํผ์์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ๋๋ 0 ~ buffersize ์์ผ๋ก ๊ฐ์ ธ์ค๊ฒ ๋๋ค. ์์ธํ ๋ด์ฉ์ uartRead()
ํจ์์์ ํ์ธํ์.