해결된 질문
작성
·
128
·
수정됨
0
강의 - 섹션16 - "UART로 printf()를 구현해보자! 4" 강의를 따라하던 도중 문제가 발생하여 질문을 올려봅니다.
이게 사실 지금은 무시해야 할 문제이긴 한데, 해결하는 걸 워낙에 좋아해서... 그래서 신경쓰지 말고 지금은 무시하라고 답해주셔도 됩니다! 혹여 봐주신다면 알고 계신 문제인지, 문제 해결 과정에 오류가 있는지 봐주시면 감사합니다!
해결 과정에서 적은 노트는 아래에 적었습니다.
Xshell에 "i = 1"이, 코드 업로드 후 최초 1회 더 출력되는 문제가 있다. 원인을 찾아보자.
->
printf() 함수에 내부적으로 사용되는 _write() 함수가, "syscalls.c" 소스파일에 weak symbol로 정의가 되어 있어서, _write() 함수를 "main.c" 파일에서 retarget하여 printf() 함수를 강의대로 Xshell에 출력하도록 했다.
int _write(int file, char *ptr, int len)
{
HAL_UART_Transmit(&huart1, (const uint8_t*)ptr, len, 10);
return len;
}
결과
i = 1 // user가 설정한 딜레이와 관계없이, 다음의 "i = 1"과 대략 1초 정도의 간격
i = 1 // user가 설정한 HAL_Delay(100), 이후로 동일한 100ms 딜레이
i = 2
i = 3
i = 4
...
"main.c" 코드만으로 보았을 때, 분명 'i'는 1이 증가하여 출력되었으므로, 문제는 printf() 함수에 있음이 분명하다.
->
write() 함수를 통해 원인을 찾고자, write() 함수가 최초 1회는 무시하도록 코드를 다음과 같이 수정한다.
bool ignoreFirstWrite = true;
int _write(int file, char *ptr, int len)
{
if (ignoreFirstWrite)
{
ignoreFirstWrite = false;
}
else
{
HAL_UART_Transmit(&huart1, (const uint8_t*)ptr, len, 10);
}
return len;
}
결과
i = 1 // user가 설정한 HAL_Delay(100), 이후로 동일한 100ms 딜레이
i = 2
i = 3
i = 4
...
!!! _write() 함수가 최초 1회 더 실행되는 것을 확인했다.
int _write(int file, char *ptr, int len)
{
HAL_UART_Transmit(&huart1, (const uint8_t*)ptr, len, 10);
return len;
}
위의 _write() 함수로 하여 두 가지의 테스트를 추가로 진행해본다.
->
1.
'i' 초기값만 바꿔서 코드를 업로드한다.
2.
코드 업로드가 아니라, debug로 실행해본다. (최초 HAL_Init() 함수에서 걸리고, 곧바로 breakpoint 없이 resume한다.)
->
!!! 최초 1회 출력 문제가 사라졌다.
1.
'i' 초기값을 변경하여 업로드한다.
int i = 10;
결과
i = 1
i = 11
i = 12
i = 13
i = 14
...
다시 'i' 초기값을 변경하여 업로드한다.
int i = 0;
결과
i = 11
i = 1
i = 2
i = 3
i = 4
...
!!! 이전에 업로드할 때 _write() 함수로 처음 출력한 문자열이, 다음 업로드 때 출력된다.
정리
1.
_write() 함수가 최초 1회 더 실행된다.
2.
디버그 환경에서는 문제가 발생하지 않는다.
->
전혀 모르겠다.
->
[수정]: float로 테스트 후부터는, 디버그 환경에서도 정수/실수 모두 동일하게 문제가 발생한다.
3.
이전에 업로드할 때 _write() 함수로 처음 출력한 문자열이, 다음 업로드 때 출력된다.
->
마지막에 출력한, 혹은 출력 대기중인 문자열도 아니고, 왜 이전 업로드 때 처음 출력한 문자열일까?
->
원인이 어디인지 찾아보자.
board, FT232, Xshell 혹은 그 사이 어디서 문제인지 찾으려 했으나, 애초에 _write() 함수가 1회 더 실행되는 것이 확실하니,
->
?????
"stdio.h" 구조로 접근해야 하나?
아니, 코드는 새롭게 업로드하는 거고,
이전의 정보가 'board'에 남아있다는 건데,
printf() 함수가, 이전 업로드할 때 최초로 출력했던 문자열을 어떻게 가지고 있을 수 있지?
아니면 PA9 USART1 transmitter에 buffer가?
어떻게 접근해야 하지?
->
전혀 모르겠다. 포기. 끝. 무시하고 강의 진행하자.
답변 1
1
아마 버퍼 때문에 그런 것 같아요.
아래는 제가 테스트해본 것은 아닌데요.
이런 식으로 한번 해보세요.
아래 함수 호출하고 전송시작 ㅇㅇ/
void UART_ClearBuffer(void) {
HAL_UART_AbortTransmit(&huart1);
// 약간의 딜레이
HAL_Delay(1);
}
UART 통신의 특징
MCU → UART 버퍼 → FT232 칩 → PC
코드를 새로 업로드해도 UART 하드웨어 버퍼는 초기화되지 않음
그래서 이전 데이터가 남아있다가 출력되었다고 예상됨