펌웨어로 무언가를 개발하려면 제일 먼저 하는 건, LED 켜고 끄기다. 사실 더 이전에 하는 일은 전원이 정상 들어오는지?
뻥 터지지 않는지? 오실레이터가 정상적으로 발진하는지, JTAG과 CPU가 정상적으로 통신하는지... 등이 있다.
그래서 가장 마지막에 테스트하는 GPIO로 LED가 제어가 된다면 개발 관련해서는 50% 이상은 한 것이나 마찬가지이다.
(개발 관련은..)
- GPIO -
출력 설정을 하려면 GPIO_PinModeSet 함수를 이용하면 된다. 포트와 PIN 번호를 가지고 풀업을 하지 말지
그리고 초기 출력값을 무엇으로 할지 결정하면 된다.
또 CMU_ClockEnable 함수로 GPIO 클럭 활성화도 같이 해주면 된다. 위는 PORTD의 4번 핀에 있는 LED를 풀업으로 초기값 '1'로 설정하는 방법이다. 나중에 상황에 맞춰 GPIO_PinOutSet 함수를 사용하면 되고 Toggle을 하고 싶을 때는 GPIO_PinOutToggle 함수로 간단하게 토글을 할 수 있다. 그다음으로 개발하는 것은 디버깅 로그 확인 및 통신을 위해 UART, Serial 통신이다.
- USART -
8비트 마이 컴퓨터로 개발할 때는 데이터시트를 보면서 baudrate를 계산하기 위해 크리스탈 클럭과 계산 공식으로 일일이 다 계산을 했었는데 지금은 제공하는 함수만 사용하면 된다. (아는 지인은 이런 부분 때문에 아래 직원들이 개발할 줄 모른다고 타박을 놓기도 하더라.. 물론 나도 인정하는 부분)
void uart_serial_init()
{
#if defined(_CMU_HFPERCLKEN0_MASK)
CMU_ClockEnable(cmuClock_HFPER, true);
#endif
USART_TypeDef *usart = USART1;
USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;
CMU_ClockEnable(cmuClock_GPIO, true);
CMU_ClockEnable(cmuClock_USART1, true);
GPIO_PinModeSet(gpioPortA, 6, gpioModePushPull, 1);
GPIO_PinModeSet(gpioPortA, 5, gpioModeInputPull, 1);
init.enable = usartDisable;
init.baudrate = 115200;
USART_InitAsync(usart, &init);
#if defined(GPIO_USART_ROUTEEN_RXPEN)
GPIO->USARTROUTE[1].RXROUTE = (gpioPortA << _GPIO_USART_RXROUTE_PORT_SHIFT)
| (5 << _GPIO_USART_RXROUTE_PIN_SHIFT);
GPIO->USARTROUTE[1].TXROUTE = (gpioPortA << _GPIO_USART_TXROUTE_PORT_SHIFT)
| (6 << _GPIO_USART_TXROUTE_PIN_SHIFT);
// Enable RX and TX
GPIO->USARTROUTE[1].ROUTEEN = GPIO_USART_ROUTEEN_RXPEN | GPIO_USART_ROUTEEN_TXPEN;
// Configure and enable USART0
#else
usart->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN | RETARGET_LOCATION;
#endif
FlushQueue (ENUM_UART_DEBUG);
USART_IntClear(USART1, USART_IF_RXDATAV);
NVIC_ClearPendingIRQ(USART1_RX_IRQn);
/* Enable RX interrupts */
USART_IntEnable(USART1, USART_IF_RXDATAV);
NVIC_SetPriority (USART1_RX_IRQn, 4 /*5*/);
NVIC_EnableIRQ(USART1_RX_IRQn);
USART_Enable(usart, usartEnable);
}
static uint32_t uart_tx_write(uint8_t *pui8Data, uint32_t ui32NumBytes)
{
uint32_t i = 0;
while (i < ui32NumBytes)
{
USART_Tx(USART1,pui8Data[i++]);
}
return i;
} // uart_tx_write()
uart_tx_write 함수로 데이터를 전송하면 테라텀등의 터미널 프로그램으로 데이터를 받아 볼 수 있게 된다. 그런데 다른 칩은 모르겠는데 EFR32BG21 칩이 특이한 기능이 있어서 개발에 큰 도움이 된 적이 있다. 보통 CPU의 각 핀은 멀티 funtion을 지원하더라도 다른 핀과 기능을 바꾸는 기능은 없었다. 그런데 EFR32BG21은 Digital Peripheral Connectivity 라 해서 디지털 리소스(UART나 i2c, timer 등)을 라우팅할 수 있다고 한다. 게다가 Rx, Tx 같은 기능이 다른 핀 설정까지도!
사실 하드웨어 팀에서 UART Tx와 Rx를 꼬와서 개발을 해버렸다. EV 보드에서 잘 되는 게 안돼서 회로도를 보니 핀 이 잘못되어 있었던 것... 하드웨어 팀한테 점 터를 날려달라 할까 하다가 데이터시트를 보고 설마 하고 핀 설정을 바꿔서 하니... 바로 동작했다. 펌웨어 개발 10년 만에 이렇게 놀란건 NXP 이후로 처음인 것 같다. 설정하는 방법은 간단하다. 위 소스의 RXROUTE 와 TXROUTE 의 핀설정을 바꿔주기만 하면 되었다. GPIO_PinModeSet도 같이 변경하였다.
다음에는 특이했던 인터럽트 핸들러와 타이머 인터럽트를 정리해 봐야겠다.
'개발이야기' 카테고리의 다른 글
[libcurl] ftp 업로드 (put) (0) | 2023.07.24 |
---|---|
EFR32BG21 BLE SPP 개발 (3부 인터럽트, BLE) (0) | 2023.07.03 |
EFR32BG21 BLE SPP 개발 (1부, 프로젝트 구성) (0) | 2023.03.15 |
[ESP32/idf] Panic, watchdog 이벤트 발생 시 참조할 사항 (1) | 2022.10.14 |
펌웨어와 커스텀 부트로더(SRAM과 보안,MPU) (1) | 2022.10.14 |