inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[임베디드 입문용] 임베디드 개발은 실제로 이렇게 해요.

UART로 printf()를 구현해보자! 4

"UART로 printf()를 구현해보자! 4" 강의에서 문제 발생.

해결된 질문

244

김경환

작성한 질문수 1

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가?
어떻게 접근해야 하지?



->
전혀 모르겠다. 포기. 끝. 무시하고 강의 진행하자.

Raspberry-Pi arduino 임베디드

답변 1

1

ojtube5

아마 버퍼 때문에 그런 것 같아요.
아래는 제가 테스트해본 것은 아닌데요.
이런 식으로 한번 해보세요.
아래 함수 호출하고 전송시작 ㅇㅇ/

void UART_ClearBuffer(void) {

HAL_UART_AbortTransmit(&huart1);

// 약간의 딜레이

HAL_Delay(1);

}

UART 통신의 특징

  • MCU → UART 버퍼 → FT232 칩 → PC

  • 코드를 새로 업로드해도 UART 하드웨어 버퍼는 초기화되지 않음

  • 그래서 이전 데이터가 남아있다가 출력되었다고 예상됨


13강 프로젝트생성해보기 관련 질문

0

22

3

난방실만들기.4 진행 중, m_state 값 초기화가 안됩니다..

0

35

2

IDE 설치 영상 관련 문의

0

51

2

[정보 공유] STM32CubeIDE 버전별 이슈 정리 (1.19 미만 / 2.0.0 이상)

0

137

2

스위치회로 value값 바뀌지 않음

0

46

2

FND 점등에 성공했는데, Controller.c 디버깅 중 문제가 생겼습니다.

0

61

2

FND 7세그먼트 처음 킬 때의 '7777'불이 안 들어옵니다.

0

74

2

포트에 안잡히면 x쉘에서 Port설정을 어떻게 하죠..?

0

59

2

빌드 및 디버깅 오류

0

114

2

보드에 불이 안들어옵니다.

0

74

2

씽크 오류

0

57

1

고추건조기 개발보드 전원연결 문제점..

0

74

2

회로도 핀 연결 질문

0

68

2

elf 파일을 찾을수 없다는 오류

0

72

2

Nucleo 보드로 대체

0

85

2

구매해야 하는 물품 문의

0

97

2

ST-Link 디버깅 에러

0

84

3

강의 사용하시는 pdf는 어디에 있나요?

0

111

2

이전 질문 재질문입니다.!

0

77

2

다른 개발 실습 보드 사용문의

0

96

2

smt32 Cube Ide 설치관련 에러입니다

0

229

2

제가 1년전에 구매해서 이제 뜯어봤는데 납땜이 겹쳐있는데 사용해도 괜찮을까요?

0

94

2

타이머 최대 주파수 질문

0

66

2

초기 신호에 대한 질문

0

90

2