@bravosung님의 cdcAvailable() 외 uint8_t cdcread(void), void cdcdatain(uint8_t rx_data), uint32_t cdcwrite(uint8_t *p_data, uint32_t length), uint32_t cdc_get_baud(void) 등의 함수는 usbd_cdc_if.c파일에 정의 되어있고, 직전 강좌에서는 이 함수들을 extern 예약어를 사용하여uart.c 파일에 불러와 사용했습니다. 그런데 이 함수들을 cdc.h 파일에서 선언하면서 extern 예약어를 사용하지 않았습니다. 빌드 과정 중에 수행되는 링킹에서 컬파일러가 알아서 연결해준다고 했는데, 이 보다는 cdc.h 파일에 usbd_cdc_if.h 파일을 include하고, 함수를 선언하지 않는 것이 더 낫지 않을까 하는 생각인데 맞나요? 참고로 저는 stm32를 지금 막 학습하고 있는 쌩 초보입니다. 설명 좀 부탁 드립니다.
안녕하세요 바람님 질문있습니다 버퍼를 생성 하기위한 함수 qbufferCreate를 만드실때 p_buf가 NULL일때 index만 관리하도록 한다는 부분에서 실제 p_buf가 NULL로 되서 qbufferCreate로 만들어진 버퍼는 사용할수 없기 때문에 false를 반환하게 하고 다시 버퍼를 만들어 줘야 하는게 아닌가요? 버퍼가 없는상태에서 인덱스만 증가되는 방식이 이해가 안되네요....
영상을 제작할 당시에 qbuffer는 1바이트씩만 데이터를 처리할 수 있게 만들어져서 만약 여러바이트가 있는 데이터를 처리할때 예를 들어 CAN 통신 버퍼같은 것을 사용할때 별도의 버퍼를 선언하고 qbuufer 함수로는 버퍼 인덱스만 사용 할려고 했습니다. 하지만 최근에 업데이트한 qbuffer는 여러바이트의 데이터도 처리 할 수 있도록 변경하였기 때문에 CAN통신 버퍼로도 사용 가능합니다. github.com/chcbaram/stm32g431/blob/main/stm32g431_fw/src/common/core/qbuffer.c 인덱스만 별도로 처리한다는 것은 버퍼에 대한 처리는 별도로 한다는 의미입니다. 인덱스처리만 필요하면 따로 구현해줘도 되구요.
uart.c 파일에서 cdcAvailable() 함수의 선언은 #include "cdc.h"에 되어있고, 정의는 usbd_cdc_if.c 파일에 있습니다. usbd_cdc_if.c 파일에 정의되어 있는 cdcAvailable() 함수를 uart.c 파일에서 어떻게 가져오는지 잘 이해가 안됩니다. F3로 추적해봐도 연결고리를 못찾겠네요. ㅠ
@@chcbaram 함수 원형이 선언된 헤더파일(cdc.h)을 include한 소스파일을 컴파일하고, 함수가 정의된 소스파일(usb_cdc_if.c)을 각각 컴파일한 다음, Link 때 합친다는 말씀이시죠? 그렇다면 이번 영상처럼 헤더파일 이름(cdc.h)과 정의된 파일명(usb_cdc_if.c)이 달라도 되는거네요. 함수선언은 A.h, 함수정의는 A.c 이렇게 이름을 같게 해야 하는걸로 알고 있었습니다. 이제 이해가 갑니다. 감사합니다^^
@@bravosung 네 컴파일할때는 함수 본체는 없어도 다른 어딘가에 있다는 것을 알려주기 위해서 선언부가 반드시 있어야 하구요. 컴파일 후에 링킹 할때 링커는 모든 컴파일된 오브젝트파일에서 심볼 이름(변수, 함수명등)으로 찾기 때문에 위치가 중요하지는 않습니다. 단, static으로 정의한 변수나 함수는 해당 c 파일에서만 사용할 수 있도록 이름이 변형되기 때문에 만약 다른 c 파일에서 해당 변수나 함수를 사용하게 되면 없는 변수나 함수라고 나옵니다. 영상의 방법이 썩 좋은 방법은 아닙니다. 변수나 함수가 원래 의도했던 모듈에 있는게 맞고, 그렇지 않은경우 함수포인터나 함수 호출 방식으로 사용하는게 더 좋을 것 같습니다. 제 코드 중에 이렇게 변경된 프로젝트도 있으니 참고하시면 될 것 같습니다.