본문 바로가기

CAN

8. HAL 드라이버 수정/추가 (1) 인터럽트가 2번 걸리는 문제

HAL_CAN_IRQHandler에서 전송에 의해 HAL_CAN_IRQHandle 접근했는지 검사하는 블록입니다. 저는 전송이 완료될 때마다 핸들러의 state 맴버 변수나 반환값을 확인하는게 귀찮아서 이 코드 마지막에 printf 함수를 써서 전송 완료를 확인할 수 있게 해봤습니다. 원래 2줄 위에 써야하지만 실수로 아래 코드와 같이 입력했는데 터미널에서 HAL_CAN_IRQHandler2번 접근하는 것을 알게되었습니다.


can example code


terminal example output string can system


 버튼을 눌렀을 때 스위치가 불안정하여 EXTI_ISR에 두번 진입하는 것은 하드웨어 문제이지만(소프트웨어로 어느 정도 해결할 수 있지만), HAL_CAN_IRQHandler에 두번 진입하는 이유는 레퍼런스 매뉴얼을 찾아보면 알 수 있습니다. 인터럽트를 이용한 송신은 CAN_TSR 레지스터의 RQCPx 비트를 인터럽트 소스로 사용하여 전송을 수행합니다. 그리고 RM0091 827, 828페이지에 나와 있듯이 전송이 완료되면 RQCPx 비트가 1로 셋됩니다. 그리고 843 페이지에서 이 비트는 rc_w1으로 나와 있는데, 이것은 1을 쓰면 클리어되는 비트라는 의미이고, 사용자가 직접 해야합니다. 하지만 HAL_CAN_IRQHandler 안에는 이런 기능이 구현되어 있지 않습니다. 따라서 이 블록 안에 아래 코드를 삽입하여 해결했습니다.


CAN->TSR |= ((0x1 << 0) | (0x1 << 8) | (0x1 << 16));


  3 개의 TX 메일박스 중 선택된 메일박스를 정확히 선택해서 지워야 하는 것 아닌가 생각할 수도 있지만, 위에서 설명한 TMEIE 비트로 TME가 아닌 RQCPx를 인터럽트 소스로 선택하는 이유로 3개를 한번에 클리어해도 상관 없습니다.