의식의 흐름따라 삽질한 순서 기억 나는대로…
1. 목표
Zynq-7000 SoC 사용 장비에서 CAN BUS 를 통해 다른 장비와 통신 가능한 환경 구성
2. 환경
- Processor : Xilinx Zynq xc7z010 SoC
- BSP : PetaLinux v2016.2
- https://www.xilinx.com/support/documentation/sw_manuals/xilinx2016_2/ug1144-petalinux-tools-reference-guide.pdf
- Kernel : Linux 4.4.0
- RootFS : Debian 7 Jessie
3. 기본 정보
CAN 이란?
- https://www.ni.com/ko-kr/innovations/white-papers/06/controller-area-network–can–overview.html
- https://ko.wikipedia.org/wiki/CAN_버스
- https://www.fescaro.com/ko/archives/249
- 1 pair 케이블 사용(CAN_H / CAN_L), 차동신호 (differential Signal)
- BUS 시작과 끝 장치에 종단 저항(120 옴) 부착 필요
- 식별을 위한 ID 가 포함된 메세지를 전체 장치에 Broadcasting
- ID : 식별 및 우선순위 (클수록 높음)
11 bit (0x0-0x7FF) 또는
29 bit (0x0-0x1FFFFFFFFFF) - Data Length Code (DLC) : 4 bit
- Data : 최대 8 Byte
- ID : 식별 및 우선순위 (클수록 높음)
- CAN Controller 와 CAN Transceiver (Phy) 필요
- MCP2515 많이 사용함 (Linux Kernel 에 Driver 포함)
Linux 에서 CAN
- Character Device Driver : 비 표준
- SocketCAN : CAN Protocol 을 Network Interface 로 구현
- 기존 네트워크 프로그래밍과 비슷하게 사용
- https://blog.naver.com/sonyi/221084250471 – 예제 코드(수신)
- https://en.wikipedia.org/wiki/SocketCAN – 예제 코드(송신)
- ifconfig / ip 명령으로 Controller 관리
- 기존 네트워크 프로그래밍과 비슷하게 사용
$ ## CAN Interface 인식 확인 $ ls -al /sys/class/net $ ifconfig can0 $ ## bitrate 설정 및 활성화 : can0, 250000 bps $ ip link set can0 up type can bitrate 250000 $ ## or $ ip link set can0 type can bitrate 250000 $ ifconfig can0 up
- can-utils Package 를 통해 송수신 테스트 가능
- https://www.fescaro.com/ko/archives/642
- 수신
## 모든 Interface 의 모든 데이터 출력 $ candump any,0:0,#FFFFFFFF ## can0 / can1 로 수신된 모든 데이터 출력 $ candump can0,0:0,#FFFFFFFF $ candump can1,0:0,#FFFFFFFF 모든 Interface 의 모든 데이터 출력 $ candump any,0:0,#FFFFFFFF can0 / can1 로 수신된 모든 데이터 출력 $ candump can0,0:0,#FFFFFFFF $ candump can1,0:0,#FFFFFFFF
- 송신 ( 16진수, 8 Byte 까지)
## ID : 545, Message : 02 00 00 00 00 00 00 00 $ cansend can0 545#0200000000000000 ## ID : 001, Message : AaBbCcDd (Ascii) $ cansend can0 001#4161426243634464
$ ifconfig can0 down $ ip link set can0 type can loopback on $ inconfig can0 up $ candump can0 | grep C0FFEE $ cansend can0 00C0FFEE#00112233445566
Zynq 에서 CAN
1) Zynq 내장 CAN Controller
https://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf
$ cat ./PetaLinuxProject/subsystems/linux/configs/device-tree/zynq-7000.dtsi can0: can@e0008000 { compatible = "xlnx,zynq-can-1.0"; status = "disabled"; clocks = <&clkc 19>, <&clkc 36>; clock-names = "can_clk", "pclk"; reg = <0xe0008000 0x1000>; interrupts = <0 28 4>; interrupt-parent = <&intc>; tx-fifo-depth = <0x40>; rx-fifo-depth = <0x40>; }; can1: can@e0009000 { compatible = "xlnx,zynq-can-1.0"; status = "disabled"; clocks = <&clkc 20>, <&clkc 37>; clock-names = "can_clk", "pclk"; reg = <0xe0009000 0x1000>; interrupts = <0 51 4>; interrupt-parent = <&intc>; tx-fifo-depth = <0x40>; rx-fifo-depth = <0x40>; };
$ cat ./PetaLinuxProject/subsystems/linux/configs/device-tree/pcw.dtsi can0 { status = "okay"; }; can1 { status = "okay"; };
But, CAN Interface 가 정상적으로 활성화 되지 않음!!!
$ ip link set can0 up type can bitrate 250000 xilinx_can e0008000.can can0: bitrate error 0.0% A link change request failed with some changes committed already. Interface can0 may have been left with an inconsistent configuration, please check. RTNETLINK answers: No such device
2) 외부 CAN Controller (MCP2515)
$ cat ./PetaLinuxProject/subsystems/linux/configs/device-tree/system-top.dts spi0 { /* SPI Clock : 10 MHz SPI modes : 0,0 and 1,1 Operates from 2.7V-5.5V */ clocks{ clk8m: can_oscillator { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <8000000>; //8MHz }; }; can2: can@0 { compatible = "microchip,mcp2515"; reg = <0>; //Chip select 0 clocks = <clk8m>; interrupt-parent = <gpio0>; interrupts = <70 0x2>; // EMIO:16, Bare:70, Linux:976 : IRQ_TYPE_EDGE_FALLING spi-max-frequency = <10000000>; // 10MHz status = "okay"; }; can3: can@1 { compatible = "microchip,mcp2515"; reg = <1>; //Chip select 1 clocks = <amp;clk8m>; interrupt-parent = <gpio0>; interrupts = <71 0x2>; // EMIO:17, Bare:71, Linux:977 : IRQ_TYPE_EDGE_FALLING spi-max-frequency = <10000000>; // 10MHz status = "okay"; }; };
4. 정리 및 테스트
- Zynq 내장 CAN Controller 는 알수없는 이유로 Interface 가 활성화 되지 않는다.
- MCP2515 의 Interrupt Pin 을 Zynq 의 Interrupt-Controller (IRQ_F2P) 에 연결시,
Zynq SPI (Shared Peripheral Interrupts) 의 Edge Type 설정 제약으로 사용 불가
MCP2515 는 Falling Edge 만 지원 - Interrupt Pin 을 Zynq 의 EMIO(GPIO) 로 연결 후 에러없이 CAN Interface 가 활성화 됨
$ ip link set can0 up type can bitrate 250000 - 테스트용 ZIG 와는 통신이 되지 않음
메세지를 한번 보냈으나 SPI 신호는 꽤 오랜시간동안 반복(Retry) 후 멈춘다.
추가로 메세지를 보낼 경우 송신 버퍼 에러가 발생 한다.
임시로 송신 버퍼 크기 늘리면 에러는 사라진지만,
송신이 안되고 있는 근본 문제는 여전 하다.
$ sudo ifconfig can0 txqueuelen 1000 - Raspberry Pi 에 MCP2515 Module 을 적용한 장치와는 통신이 잘 된다.
- 테스트용 JIG 에 종단저항 (120 옴) 추가 후 통신이 잘 된다.
- 회선이 불안정 하여 Retry 하다 멈춘 경우,
CAN Interface 를 재설정 (down / up) 해주어야 복구가 된다.