임베디드 용어설명

Raspberry pi cm4 SPI0 CE0 CE1 사용 / ENC28J60, TFT 2.2 LCD 사용

젊은우산 2021. 6. 17. 09:50
반응형

"SPI 5개나 있으니까 두개 연결하면되겠지?"

   멍청한 생각이었다.

 

  그냥 SPI를 이용한다면 파이썬 라이브러리를 통해 SPI 프로그램을 구현하기만 하면 될것이었다.

  하지만 라즈베리파이에서 지원하는 디바이스인 ENC28J60을 사용하려고 하니 문제가 발생했다.

SPI 한 채널 CE0,CE1를 이용한 이더넷과 멀티디바이스 연결

SPI를 사용하는 두개의 모듈 SPI 2.2 TFT 모델과 ENC28J60 을 멀티로 연결 하는 방법은 다음과 같다.

1. 라즈베리파이의 SPI0 - GPIO10(MOSI), GPIO9(MISO), GPIO11(CLK) 연결.

2.2 TFT - Raspberry pi CM4

VCC - 3.3v

GND - Ground

CS - GPIO8

RESET - RUN_PG

DC - GPIO25

MOSI - GPIO10(MOSI)

SCK - GPIO11(CLK)

LED - GPIO6

MISO - GPIO9(MISO)

ENC28J60 - Raspberry pi CM4

VCC - 3.3v

GND - Ground

CS - GPIO7

INT - GPIO23

MOSI - GPIO10(MOSI)

SCK - GPIO11(CLK)

MISO - GPIO9(MISO)

2. /boot/overlays/ENC28J60-overlay.dts 수정 및 컴파일

이미 Raspberry pi os에는 ENC28J60에 대한 SPI 드라이버가 내장되어 있다. 따라서 SPI=on을 해주기만해도 dts에 의해 드라이버를 자동으로 인식한다. 하지만 안타깝게도 CE를 설정해주는 함수는 찾아보기 힘들다.

/boot/overlays/README
...
Name:   enc28j60
Info:   Overlay for the Microchip ENC28J60 Ethernet Controller on SPI0
Load:   dtoverlay=enc28j60,<param>=<val>
Params: int_pin                 GPIO used for INT (default 25)

        speed                   SPI bus speed (default 12000000)


Name:   enc28j60-spi2
Info:   Overlay for the Microchip ENC28J60 Ethernet Controller on SPI2
Load:   dtoverlay=enc28j60-spi2,<param>=<val>
Params: int_pin                 GPIO used for INT (default 39)

        speed                   SPI bus speed (default 12000000)

CE1핀으로 사용하려면  *dts 파일을 작성하여, 사용할 CE1핀이 변경된, dtb로 다시 컴파일 해주어야한다.

(*DTS파일은 Device Tree Specification 의 약자 이다. 라즈베리파이 OS가 빌드 될 때에, 디바이스 드라이버들이 탑재되어 이미지가 빌드된다.)

DTS파일 양식은 리눅스에서 약속된 형태로 사용되므로 구조를 따로 공부해두는 것도 좋다.

  • dtc 는 dts를 컴파일하여 dts로 만들어주는 컴파일러이다.
  • dts = device tree specification (사람이 이해 할 수 있는 수준으로 기술)
  • dtb = device tree blob (DT를 binary로 변환 한 것)
  • dtc = device tree compiler

 

  ENC28J60에 해당되는 Device Tree를 수정해주는 작업

이곳←클릭 enc28j60-overlay.dts 코드를 가져올 수 있다.

컴파일하기 전, 복사한 코드를 아래와 같이 수정하여 준다.

(1) reg를 1로하여 CE1을 사용함을 알리고,

(2) TFT의 frequency 와 맞춰주기위해 16Mhz로 수정해준다.

(3) 또한 인터럽트 핀을 GPIO23번으로 교체한다.

 

cd /boot/overlays
sudo vi ENC28J60-overlay.dts

// Overlay for the Microchip ENC28J60 Ethernet Controller
/dts-v1/;
/plugin/;

/ {
        compatible = "brcm,bcm2708";

        fragment@0 {
                target = <&spi0>;
                __overlay__ {
                        /* needed to avoid dtc warning */
                        #address-cells = <1>;
                        #size-cells = <0>;

                        status = "okay";

                        spidev@0{
                                status = "disabled";
                        };

                        eth1: enc28j60@0{
                                compatible = "microchip,enc28j60";
                                reg = <1>; /* CE1 */
                                pinctrl-names = "default";
                                pinctrl-0 = <&eth1_pins>;
                                interrupt-parent = <&gpio>;
                                interrupts = <23 0x2>; /* falling edge */
                                spi-max-frequency = <16000000>;//12
                                status = "okay";
                        };
                };
        };

        fragment@1 {
                target = <&gpio>;
                __overlay__ {
                        eth1_pins: eth1_pins {
                                brcm,pins = <23>;
                                brcm,function = <0>; /* in */
                                brcm,pull = <0>; /* none */
                        };
                };
        };

        __overrides__ {
                int_pin = <&eth1>, "interrupts:0",
                          <&eth1_pins>, "brcm,pins:0";
                speed   = <&eth1>, "spi-max-frequency:0";
        };
};

컴파일 하기전 기존 파일을 따로 백업해두자 

sudo mv enc28j60.dtbo enc28j60.dtbo_backup

새로만든 dts 파일을 적용시키자.

sudo dtc -@ -I dts -O dtb -o enc28j60.dtbo enc28j60-overlay.dts

위 코드를 실행시키면 dts파일을 컴파일하여 enc28j60.dtbo 파일로 만들어져서 나온다.

 

3. /boot/config.txt 수정

   config.txt파일은 부팅시에 장치들의 설정을 미리 설정해두는 파일이다.

   이때 TFT LCD모듈과 이더넷모듈을 같은 클락(SCK)을 사용해야 정상적으로 동작한다. SCK 클럭 수를 16Mhz로 통일시킨다. dtoverlay=spi0-2cs, 로 바꾸어주어서 cs핀을 두개 이상사용한다고 입력해준다. enc28j60의 int_pin 을 23으로 바꾼다. 

아래와 같은 코드를 추가해준다.

sudo vi /boot/config.txt
...

dtparam=spi=on
dtoverlay=spi0-2cs, cs1_pin=7
dtoverlay=enc28j60, int_pin=23

# --- added by adafruit-pitft-helper Mon Apr 12 16:24:03 2021 ---
#hdmi_force_hotplug=1  # required for cases when HDMI is not plugged
dtparam=i2c1=on
dtparam=i2c_arm=on
dtoverlay=pitft22,rotate=90,speed=16000000,fps=24
# --- end adafruit-pitft-helper Mon Apr 12 16:24:03 2021 ---

4. 리부트

sudo reboot

5. 결과확인

TFT 는 SPI0.0 을 사용한다.

ENC28J60 은 SPI0.1 을 사용한다.

네트워크가 IP자동할당 붙어있는 것을 확인 할 수 있다.

dmesg | grep spi 
pi@raspberrypi:/boot/overlays$ dmesg | grep spi
[    5.268578] enc28j60 spi0.1: Ethernet driver 1.02 loaded
[    5.458739] graphics fb1: fb_ili9340 frame buffer, 320x240, 150 KiB video memory, 4 KiB buffer memory, fps=25, spi0.0 at 16 MHz
[    7.719114] enc28j60 spi0.1 eth1: link down
[    7.719133] enc28j60 spi0.1 eth1: multicast mode
[    7.719306] enc28j60 spi0.1 eth1: multicast mode
[    7.734465] enc28j60 spi0.1 eth1: multicast mode
[    7.734707] enc28j60 spi0.1 eth1: multicast mode
[    7.785027] enc28j60 spi0.1 eth1: multicast mode
[    7.785251] enc28j60 spi0.1 eth1: multicast mode
[    8.610802] enc28j60 spi0.1 eth1: link up - Half duplex
...

ifconfig
pi@raspberrypi:/boot/overlays$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.174  netmask 255.255.255.0  broadcast 192.168.1.255
        RX packets 5725  bytes 1423850 (1.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1216  bytes 93691 (91.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.57  netmask 255.255.255.0  broadcast 192.168.1.255
        RX packets 7430  bytes 1172572 (1.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 76  bytes 19756 (19.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device interrupt 58

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

 

 

인터넷 속도 측정 결과 비교

  • 100M 인터넷 환경에서 측정
  • 라즈베리파이 ethernet 포트에서 다운로드 83.25 Mbit/s , 업로드 92.92 Mbit.s
  • SPI 이더넷포트 다운로드 5.87 Mbit/s , 4.31Mbit/s
  • python3 speedtest-cli 사용 
pi@raspberrypi:~$ python3 speedtest-cli
Retrieving speedtest.net configuration...
Testing from Korea Telecom (14.51.232.196)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by kdatacenter.com (Seoul) [20.65 km]: 23.189 ms
Testing download speed................................................................................
Download: 83.25 Mbit/s
Testing upload speed......................................................................................................
Upload: 92.92 Mbit/s
pi@raspberrypi:~$ python3 speedtest-cli
Retrieving speedtest.net configuration...
Testing from Korea Telecom (14.51.232.196)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by kdatacenter.com (Seoul) [20.65 km]: 24.863 ms
Testing download speed................................................................................
Download: 5.87 Mbit/s
Testing upload speed......................................................................................................
Upload: 4.31 Mbit/s
pi@raspberrypi:~$

위에 나온것은 Raspberry pi cm4의 이더넷 포트에 연결한 것이다. 다운로드속도 83.25 Mbit/s가 나오고 있다.

ENC28J60 은 이보다 더 낮은 속도인 5.87 Mbit/s 나온다. 속도저하의 원인은 아직 발견 못했지만, LCD화면도 나오고 인더넷 연결도 원할 한 것을 확인하였다. 웹서핑 정도는 충분한 인터넷속도를 보여준다.

반응형