임베디드 소프트웨어를 짜다보면 PC랑 연결해서 디버깅 해야할수도있습니다.

 

저는 UART통신으로 PC랑 연결해서 디버깅하려고 합니다.

임베디드 코드상에서 printf사용하면 그 내용들이 PC로 전달돼서 시리얼 통신 프로그램에 뜨도록 할 수 있습니다.

이때 printf와 비슷한 효과를 내는 fun이라는 함수를 만들어보려고 합니다.

내장함수를 사용하지않고 필요한 함수들은 만들었습니다.

 

일반 printf함수의 경우 가변인자로 매개변수의 개수 제한이 없습니다.

하지만 임베디드의 경우 CPU종속적이기때문에 인수의 개수는 10개로 제한하려고합니다.

 

# 가변인자란?
인수의 개수와 타입이 미리 정해져있지않다는 것

[조건]

1. 함수 형태는 fun(”Hello %d”, &a) 이고 a값이 123일 때 출력은 Hello 123

2. 출력 형식은 %d, %s이런거 대신 %1, %2, %4로 설정

  • 1은 tU08에서 Char로
  • 2는 tU16에서 Char로
  • 4는 tU32에서 Char로

unsigned char은 tU08
unsigned int는 tU16
unsigned long은 tU32 로 정의했습니다.

 

# 함수의 매개변수가 메모리에 저장되는 방식

: stack에 little endian방식으로 저장됩니다.
함수를 호출할 경우 매개변수가 stack에 저장되고 함수가 종료될 경우 stack에서 소멸됩니다.

 

출력 함수 형태 : fun ("asdfas %1", arg )

문자열과 arg를 받아오는 함수이고 %1자리에 arg를 대입해야합니다.

배열로 하나씩 검사해서 %를 만나면 그 뒷자리가 1,2,4중 어떤 것인지 switch로 구분하고 각 case마다 형변환을 합니다.

 

숫자를 대입했을 때 문자로 바꾸는 방식 : 아스키 코드 사용

[숫자 3221을 문자 3221로 출력하기]
3221 / 1000 +0x30 = 0x33 
221 / 100 +0X30 = 0x32
21 /10 +0X30 = 0x32
1 /1 +0X30 = 0x31
=> 0x33 0x32 0x32 0x31을 문자로 출력해보면 3221로 출력되는 것을 확인할 수 있습니다.

 

작성한 코드는 github에 올려뒀습니다.

 

! 코드 오류 발생

1. error: conflicting types for '함수이름' : 함수의 위치가 잘못돼서 발생한 오류입니다.

2. invalid operands to binary % : %, / 연산자는 integer형태일 때만 가능합니다. (int)를 붙여 형변환을 시켜주면 됩니다.

3. invalid use of void expression : 함수가 void로 정의되어있는데 return을 char로 하려면 char로 맞춰줘야합니다.

 

# 코드 작성중 발생한 이슈

1. argbuffer에는 받아온 변수값의 주소를 저장하는데 계산해야하는 것은 해당주소의 값인데

   이를 어떻게 받아올수있을까

   - 해결 전 : tU08 h = argbuffer[argindex]

   - 해결 후 : tU08 h = *(tU08*)argbuffer[argindex]

2. 전역변수로 선언한 format 배열을 0으로 초기화했는데 함수에서 어떻게 입력된 값으로 format을 초기화하지

    - 함수에서 사용되는 format배열은 지역변수이기때문에 같은 이름을 사용할 경우 전역변수로 값을 대입할 수 없습니다. 

      그러므로 전역변수는 format으로 두고 input_fomat이라는 이름으로 값을 받아와서 for문으로 하나씩 format에

      대입했습니다.

 

*(tU08*) 의미

tU08 a1=100;
tU08* b1=&a1;
tU08 c1=*(tU08*)b1;

printf("%d\n",a1); // 100
printf("%d\n",b1); // 6422014
printf("%d\n",c1); // 100

b1 : a1의 주소를 저장

c1 : b1의 값이 a1의 주소이므로 그 주소의 값을 저장(a1값 저장)

본 코드에서 argbuffer에는 입력받은 값의 주소들이 저장되어있습니다.

그러므로 그 주소의 값을 불러와야합니다. 그래서 *(tU08*)을 붙여서 원하는 값을 불러오도록 설계했습니다. 

 

'임베디드' 카테고리의 다른 글

I2C 통신으로 칩 펌웨어 업데이트 방법  (0) 2025.02.06
MCU I2C 통신 데이터 읽는 방법  (0) 2025.02.04
I2C 통신이란?  (0) 2022.11.17

+ Recent posts