본문 바로가기

CAN

8. HAL 드라이버 수정/추가 (2) HAL_CAN_Receive 개선 및 HAL_CAN_Receive_All로 업그레이드

함수의 선언입니다.

hal_can_receive

잘 보면 두개의 RX 메일박스 FIFO 중 하나를 선택해서 수신하고 있습니다. , 두개의 RX 메일박스를 동시에 수신할 수 없다는 의미입니다. 그래서 FIFONumber 변수를 HAL_CAN_Receive 함수 내부로 넣어주고, CAN_RFxR 레지스터에서 FMP 필드를 읽어오기 위한 변수 FMP0FMP1을 만든 후에 while 문을 다음과 같이 수정합니다. 참고로 __HAL_CAN_MSG_PENDING 함수도 CAN_RFxR 레지스터에서 FMP 필드를 읽어 오는 함수입니다. 이렇게 하면 두개의 RX 메일박스 FIFO를 모두 검사할 수 있습니다.

 

hal_can_msg_peding fmp0 fmp1 rx mailbox fifo



그런데 HAL_CAN_Receive 함수에는 한가지 문제가 더 있습니다. 바로 핸들을 잠그고 while문에 진입하는 것인데요. 그렇게 되면 RTOS 사용시 메시지를 수신하기 전에는 다른 테스크에서 더 이상 이 핸들을 사용할 수 없게 됩니다. 그런데 while문은 단지 검사만 수행할 뿐, 핸들을 완전히 사용하는 것이 아닙니다. 따라서 while 블록에선 핸들을 잠시 풀어줍니다. <개선1> 하지만 여기서 또 문제가 발생합니다. while 블록 안에서 ISR 또는 다른 테스크로 문맥전환이 발생했고, 그 테스크에서 해당 핸들을 잠그고 사용하는데 작업을 완료하기 전에 어떤 이유로 인해 다시 문맥전환이 발생하여 while문으로 복귀했다고 가정해 봅시다. 이때 메시지가 수신되면 while문 바로 밑에 있는 __HAL_LOCK(hcan); 때문에 HAL_CAN_Receive 함수를 바로 탈출하게 됩니다. 따라서 핸들을 함부로 풀어줄 수 없습니다. 이 문제를 해결하기 위해서 while문에 조건 하나를 더 추가해 줍니다. <개선2>

 

__hal_unlock hal can



, ISR이나 다른 테스크에서 해당 핸들을 잠궜다면, 원래 테스크에 복귀하고 메시지가 수신되었더라도 while문을 탈출하지 않게 됩니다.