Showing Posts From

잘못

디버그 UART를 잘못 설정했는데 2시간이 걸렸다

디버그 UART를 잘못 설정했는데 2시간이 걸렸다

디버그 UART를 잘못 설정했는데 2시간이 걸렸다 출근 평소보다 30분 일찍 왔다. 어제 코드가 거의 완성됐거든. 오늘은 UART로 로그 찍어서 동작 확인만 하면 된다. 간단하다고 생각했다. 커피 마시고 보드 켰다. 터미널 실행했다. 아무것도 안 나온다. '응?'기본 체크 먼저 기본부터. USB-to-Serial 어댑터 인식되나? 확인. /dev/ttyUSB0 있다. 케이블 연결됐나? 확인. TX-RX 크로스 맞다. 보드 전원 들어왔나? 확인. LED 켜져 있다. 터미널 열었다. 여전히 아무것도 안 나온다. 검은 화면만. '코드 문제인가?' 코드 다시 확인했다. UART_Init(115200, UART_PARITY_NONE, UART_STOPBITS_1); printf("System Start\n");문제없어 보인다. printf도 UART로 리다이렉트 해놨다. '하드웨어 문제?' 오실로스코프 꺼냈다. TX 핀에 프로브 연결. 파형 나온다. 뭔가 보내고 있다. '그럼 왜 안 보이지?'보레이트부터 가장 기본. 보레이트 설정. 코드: 115200 터미널: 115200 맞다. 그런데 혹시? 9600으로 바꿔봤다. 안 된다. 19200으로 바꿨다. 안 된다. 230400으로 올렸다. 역시 안 된다. 다시 115200으로 돌렸다. '보레이트는 아니네.' 시계 봤다. 벌써 1시간 지났다. 데이터 비트 8비트가 표준이다. 근데 혹시나. 터미널 설정 들어갔다.Data bits: 8 Parity: None Stop bits: 1다 맞다. '뭐가 문제야.' 코드 다시 봤다. UART_Init(115200, UART_PARITY_NONE, UART_STOPBITS_1);UART_Init 함수 정의로 들어갔다. void UART_Init(uint32_t baudrate, uint8_t parity, uint8_t stopbits) { // ... USART->CR1 |= (parity << 10); USART->CR2 |= (stopbits << 12); // ... }레지스터 설정 보인다. 문제없어 보인다. '그럼 뭐지?'스펙 문서 할 수 없다. Reference Manual 펼쳤다. STM32 RM0090. 1700페이지짜리. USART 챕터 찾았다. 30장. 페이지 넘기다가 한 문장 보였다. "The USART_CR1 register must be configured before enabling the USART." '당연한 소리 아닌가?' 더 읽었다. "When M bit is set, data length is 9 bits..." 'M 비트?' 코드 다시 봤다. USART->CR1 |= (parity << 10);비트 10번이 패리티 인에이블이다. 맞다. 그런데 비트 12번. "Bit 12: M - Word length" 이게 뭐지. 스펙 읽었다.0: 8 data bits 1: 9 data bits'아.' 문제 발견 코드 다시 확인했다. #define UART_PARITY_NONE 0x00 #define UART_PARITY_EVEN 0x01 #define UART_PARITY_ODD 0x03PARITY_ODD가 0x03이다. 이걸 비트 10에 시프트하면? 0x03 << 10 = 0x0C00 비트 10번이랑 11번이 켜진다. 아니다. 비트 11번이랑 12번이다. 12번이 M 비트다. '세상에.' 패리티 설정하면서 데이터 길이를 9비트로 바꿔버린 거다. 터미널은 8비트로 받는데 보드는 9비트로 보내니까 데이터가 안 맞는다. 그래서 깨진 텍스트만 나왔던 거다. 아니다. 아예 안 보였다. 완전히 동기화가 안 됐다. 수정 코드 수정했다. #define UART_PARITY_NONE 0x00 #define UART_PARITY_EVEN 0x01 #define UART_PARITY_ODD 0x01 // PE 비트만아니다. 이것도 이상하다. 함수 자체를 다시 짰다. void UART_Init(uint32_t baudrate, uint8_t parity, uint8_t stopbits) { // M 비트 클리어 USART->CR1 &= ~USART_CR1_M; // 패리티 설정 if (parity == UART_PARITY_EVEN) { USART->CR1 |= USART_CR1_PCE; USART->CR1 &= ~USART_CR1_PS; } else if (parity == UART_PARITY_ODD) { USART->CR1 |= USART_CR1_PCE; USART->CR1 |= USART_CR1_PS; } // 나머지 설정... }컴파일. 업로드. 리셋. 터미널 봤다. System Start GPIO Init Done Timer Init Done Ready나온다. '드디어.' 시계 봤다. 2시간 10분 지났다. 교훈 UART는 간단하다고 생각했다. TX, RX 연결하고 보레이트 맞추면 된다고. 틀렸다. 보레이트, 패리티, 스톱비트, 데이터 비트. 하나만 달라도 안 된다. 더 정확히는 레지스터 하나만 잘못 건드려도 전부 꼬인다. 비트 연산 조심해야 한다. Define 쓸 때 값 확인해야 한다. 스펙 문서 읽어야 한다. 처음부터. '오늘 할 일은 뭐였지?' 로그 찍고 기능 테스트하는 거였다. 로그 찍는 데만 2시간 썼다. 기능 테스트는 내일. 점심시간 지났다. 배고프다.UART 설정 하나에 오전이 날아갔다. 내일은 진짜 기능 개발이나 해야지.