의식의 흐름따라 삽질한 순서 기억 나는대로…
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) 해주어야 복구가 된다.
 

 
			






