보고만 있어도 기분이 좋아지는 사람, 그리고 사람들...
가족...
Embedded Linux-Xenomai RTOS with Realtime Ethernet Control Networking
또 간만에 블로그 새글이 올라가는군...
이번 글 제목이 아주 거창하다.
한물간 PXA270 프로세서에 실시간 운영체제인 Linux-Xenomai를 포팅하고 거기에 실시간 Ethernet 디바이스 드라이버 (RTDM - Realtime Driver Model/Module)를 올려 Ethernet을 이용한 제어 네트워크를 구성해 보았다.
[Let me publish this thread in English also because I've gathered a lot of useful information from the English web pages.
Please be patient with my lack of English.
RS-232/422/485, CAN, USB, IEEE1394, Ethernet등 통신 네트워크를 펌웨어 레벨에서 코딩을 해보다 보니 제어용 네트워크를 구성하기 위한 각각의 장단점들이 어느정도 눈에 들어 온다.
우선 RS-232/422/485 (흔히 UART)계열은 심플하지만 물리 레벨에서 에러에 대응하기가 힘들고 속도 또한 최대 수Mbps까지만 가능하다. 트랜시버 칩들 사양을 보면 수Mbps가 가능하지만 UART 제어기의 한계로 인해 보통 수백Kbps만 주로 사용된다.
구현이 간단하고 MODBUS등 상위 프로토콜 스택을 올려 몇몇 서보모터에 사용된다.
CAN통신은 제어 네트워크 구성에 최적화 되어있다.
이름도 Control Area Network다.
패킷자체가 물리레벨에서 노드들간에 중재(Arbitration)가 이루어 지도록 만들었다.
우선순위가 높은 ID를 갖는 패킷이 하드웨어단에서 가장 먼저 전송되도록 구성된다.
고안해낸 기술자들이 정말 대단하다는 말밖엔...
에러에 강인하고 통신거리가 길게는 수Km대나 된다.
왠만한 8/16/32bit 컨드롤러에 UART처럼 내장되어 싼값에 사용할 수 있는 장점이 있다.
다만 최대 전송 속도가 1Mbps라 많이 아쉽다.
서보모터 제어에 아주 많이 사용된다.
전송 속도 한계로 인해 보통 한개 버스에 6~12개 정도 서보모터만 연결해서 사용하므로 다축 제어 네트워크 구성시 채널 수를 늘릴 필요가 발생될 수 있다.
USB는 수십~수백byte의 데이터를 주로 사용하는 제어 네트워크 구성에 몇가지 애로사항이 있다.
우선 너무 복잡하다. 수많은 디스크립터들...
USB디바이스 드라이버나 USB클라이언트용 펌웨어를 코딩해보신 분이라면 잘 아실 것이다.
디스크립터만 보다 시간 다 보낸다...
디스크립터 찍어 볼려고 printk() 만 주구장창 토나오게 코딩했던 기억이 있다.
핸드 쉐이킹에 사용되는 패킷이 많아 제어용 네트워크 보다 대량의 데이터 전송에 적합하다.
또한 호스트용 제어기와 클라이언트용 제어기가 달라 부품수 한개, 펌웨어 코딩 종류 한개라도 줄이려는 개발자에겐 부담스럽다.
IEEE1394는 참 잘만들었다. 32bit 기반으로 설계되어 32bit 프로세서에 아주 좋다.
프로토콜 특성상 핸드쉐이킹 오버헤드가 적어 480Mbps의 USB2.0 보다 400Mbps의 IEEE1394a의 성능이 훨씬더 좋다.
USB와 라이벌(?) 관계였으나 어느순간 일반 시장에서 사라져 버렸다.
왜일까?
우선 개발자 입장에서 보면 1394관련 문서는 돈주고 사야된다.
무료로 배포되는 USB와 다르다.
IEEE1394 펌웨어 코딩하려고 자료들좀 뒤져볼라 치면 회원 가입해야 하고 돈 내라고 하고...
짜증이 몰려온다. 여간 불편한게 아니었다. 당연히 USB로 가는수 밖에...
1394 컨트롤러도 제한적이고 구하기 쉽지 않으며, 그러다 보니 단가가 쎄다.
군용 항공기 표준으로 사용되는듯 하다. 헝그리 개발자는 자료 구하기가 힘들다.
이밖에 1553B가 있으나 1Mbps가 최대이고 군용이라 제어기 구하기 쉽지않다.
제어기도 엄청 비싸고 크다. 군용 항공기에서 오랬동안 써왔기 때문에 검증됐다는거 말고는 별 매력이 없다.
라인 연결시에도 노드별 신호 분배기(Stub) 같은걸 계속 달아줘야 하는 참 거추장스러운 네트워크이다.
Ethernet 프레임을 이용한 EtherCAT이 있는데 호스트(Master)측은 일반 이더넷 컨트롤러를 사용해도 되지만 노드(Slave)측에는 별도의 전용 하드웨어 칩이 필요하다.
OS기반으로 돌아가는 서보모터에 일부 달려나온다.
[I've programming experience with some serial network, UART(RS-232/422/485), CAN, USB, IEEE1394, Ethernet at the firmware level for manipulation of the registers and raw packets.
So, I could make my own view to apply some well known serial network to the real-time control.
Advantages and disadvantages for using real-time control network
UART
- ADVT: simple, low cost
- DISA: rack of hardware error robustness, low speed (up to X[Mbps])
CAN
- ADVT: this was born for control network, low cost
- DISA: low speed (up to X[Mbps])
USB
- ADVT: abundant, high speed
- DISA: complex(so many descripters), seperated to host and client hardware chip, not suitable for control network because of lot of handshaking overheads
IEEE1384
- ADVT: high speed, well organized
- DISA: exclusive (you may pay some money just to read the protocol specification), expensive
EtherCAT
- ADVT: designed for control network, high speed
- DISA: special hardware chip for client device is needed
Ethernet (this is not mean the TCP/IP)
- ADVT: abundant, high speed, little simple, low cost
- DISA: not suitable for control network but can be overcome
And there are so many serial protocols such as 1553B, SPI, I2C, LIN and so on for local area networking.
But I choosed the Ethernet because of abundant, high speed, little simple and low cost.
The Ethernet is not desined for real-time control network.
Back pressure, PAUSE, Jamming packet generation features are crashing the predictive charater of the packet transmission.
But I think I can overcome in some condition.
이제 이번에 설명할 Ethernet이다.
잘 아시다 시피 원래 Ethernet는 제어용으로 설계된 네트워크가 아니다.
그러나 우선, 아주 흔해 제어기 구하기가 쉽다. 종류와 벤더가 많으니 단가도 싸다.
Gbps까지 나오니 속도도 넘쳐난다. 고속 스위칭 허브도 싸게 구할 수 있다.
랜케이블... 쓰레기통에 버려야 할 많큼 많다.
헝그리 개발자에겐 아주 매력적이다.
다만 Ethernet을 제어용으로 쓰기 위해서는 다음 사항을 유의 해야 한다.
- Full Duplex 사용: Half Duplex 사용시 JAM신호와 같은 Bus Arbitration 패킷이 제어에 필수 요소인 예측 가능성을 없애 버린다. 그러나 걱정 할 필요 없다. 요즘 Half Duplex 구성은 구경하기 힘들다.
- 호스트-노드 (Master-Slave) 구성: Ethernet는 P2P 구성이 기본이다 (모두가 Master). 하지만 제어를 위해 한개 호스트를 지정해 그 호스트가 모든 버스를 제어하도록 한다. 보통 제어 네트워크를 구성하면 제어 알고리즘이 돌아가는 측에 Feedback 루프가 돌고 있으므로 어쩔 수 없이 한개 호스트는 반드시 존재 해야 한다.
- 호스트: 해당 노드들에 필요한 데이터를 요청하여 읽고 명령을 보낸다.
- 노드: 호스트의 데이터 요청이 있을때만 패킷을 전송하며 그 외에는 오직 수신만 한다. 명령이 수신되면 해당 명령을 수행한다.
- Ethernet 레지스터 설정시 Back Pressure나 JAM신호 발생, PAUSE 신호 발생 등 Bus Arbitration 기능은 모두 정지 시킨다.
서론이 참 많이 길었다.
이제 시작...
<> EtherCONN (Ethernet CONtrol Network)
이더넷을 이용한 제어 네트워크 구성 명칭을 나는 'EtherCONN (Ethernet CONtrol Network)' 이라고 부르려고 한다.
[I'll call my project as 'EtherCONN (Ethernet CONtrol Network) and the standard Ethernet frame is used as like bellow.]
이더넷 패킷은 잘 아시는것 처럼 맨 위와 같다.
이더넷 프레임의 데이터를 위 두번째 처럼 구성한다.
[Upper diagram is standard Ethernet frame and lower is my EtherCONN.
You can use your own value for 2byte EtherType/Length(TL) like 0x0601. I used this field as Length and this is IEEE 803.2 Ethernet frame.
The Ethernet's Data field is separated into 3 region. ADDR(4byte address), CTRL(4byte control) and DATA.]
Type/Length 부분은 본인 임의대로 정해 사용하면 된다. 길이를 지정해 IEEE 803.2프레임으로 사용해도 되고 0x0601과 같이 잘 사용되지 않는 Type을 적용해도 된다.
이더넷 프레임의 데이터 부분을 4바이트 주소와 4바이트 제어코드 그리고 128바이트의 데이터로 구분한다. 그러므로 EtherCONN 프레임은 최대 150바이트가 된다.
EtherCONN 노드들 중에는 메모리가 부족한 8bit 기반이 될 수도 있기에 데이터 크기를 128바이트로 제한 했다 (필요에 따라 그 이상 혹은 그 이하로 설정해 사용할 수도 있다).
주소는 가상의 주소로 해당 노드의 가상 주소에 호스트가 읽기 쓰기를 수행 한다.
호스트입장에서 노드는 마치 읽고 쓰기가 가능한 메모리 장치와 같다고 볼 수 있다.
호스트는 xx:xx:xx:xx:xx:xx 맥어드레스를 갖고 있는 노드의 메모리를 읽고 쓰는 것이다.
한번에 움직이는 데이터는 최대 128byte이므로 한개 노드가 호스트에 제공 가능한 가상 메모리 크기는 다음과 같다.
2^32(4G) x 128byte = 512GB
호스트가 노드의 메모리에 쓰기를 하는지 읽기를 하는지 알려줄 필요가 있으므로 4바이트 제어코드에 담는다. []안의 숫자는 비트 번호이다.
ctrl[31] : 0=write, 1=read
ctrl[30:16]: reserved
ctrl[15:0] : data length
즉, ctrl의 31비트를 0으로 해서 호스트가 노드에 전송 할경우 데이터 쓰기가 되고 1일 경우 읽기가 되며 이때 노드는 ADDR(4)에서 지정한 주소지의 데이터를 호스트에 보내야 한다.
128바이트 데이터를 모두다 사용 하지 않을 수도 있으므로 ctrl[15:0]에 데이터 크기를 지정하며 1바이트만 주고 받을 수도 있다.
아래 예시를 보면 이해가 좀 쉬울듯 하다.
[The EtherCONN Nodes are work as just like a memory device as seen in Host, so the Host's jobs are just reading and writing data from/to the Nodes.
The ADDR is 4-byte address for memory to access which is existed virtually in the EtherCONN Node.
The 4-byte CTRL has bit-mapped control to specify read or write cycle (packet). Simply, when the 31st bit is zero '0' the packet is write packet (Host->Node or Node->Host), so the receiver should store to his internal memory or perform the pre-promised action by the data in that packet.
When the 31st bit is one '1' in the CTRL the packet is read request. And the receiver of this packet should send a packet back with data specified at the read request packet's address.
Bit 15~0 of the CTRL represent the length of the DATA in byte to read or write.
I've limited the EhterCONN data up to 128-byte because of possibllity of low performance Node based on 8/16bit micro-processor but, you can change this limitation by your own way.
Check the EtherCONN packet example bellow, and you may easily understand.]
<> 제어 시나리오
간단한 제어 시나리오를 생각해 보자. 호스트는 주기 100ms로 제어 알고리즘을 돌리고 있는것으로 가정한다.
1. 0ms에는 센서 노드에 읽기 패킷을 보내고 구동 노드(모터,솔레노이드,LED,스피커,열선 등등)에는 초기값을 쓰기 패킷에 보낸다.
2. 다음 100ms에는 전에 보낸 읽기 패킷에 의한 센서노드의 응답이 FIFO(링버퍼)에 저장되어 있으므로 센서 값을 FIFO에서 읽어 제어 루틴을 1회 돌린다.
3. 제어 루틴에서 만들어진 출력 값은 구동 노드에 쓰기 패킷으로 보낸다. 동시에 센서 노드에도 읽기 패킷을 보낸다.
4. 2번으로 간다.
때에 따라 로봇이나 매니퓰레이터처럼 모든 구동 노드들의 동시구동(Sync/Trigger)이 필요 할 때가 있을 것이다. 이때는 브로드캐스팅 맥어드레스(FF:FF:FF:FF:FF:FF)를 사용하면 간편하게 해결된다.
위 제어 시나리오가 잘 돌기 위해서는 정확한 100ms 실시간 태스크를 돌려줄 OS가 필요하고 EtherCONN 노드는 읽기 패킷을 수신하자 마자 가장 빠르게 호스트에 응답해야 한다.
호스트에 대한 노드의 응답은 보통 OSless 펌웨어 기반으로 인터럽트에 의한 응답이므로 빠르다 (RTOS를 적용 할 경우 사용된 RTOS의 인터럽트 지연시간에 많이 의존할 것이다). 데이터 준비등이 필요하나 for() 루프에 의한 수백 바이트 데이터 복사는 수~수십[us]이내에 끝난다.
중요한것은 호스트의 읽기 패킷이 랜케이블을 타고 스위칭 허브를 지나 노드에 전달 되고 노드의 응답이 다시 랜케이블과 스위칭 허브를 지나 호스트까지 전달 되는 물리적인 시간 지연 (latency) 이다.
이더넷 프레임을 이 제어용으로 사용 했을 경우 그 시간 지연이 알고 싶었으며 그 수치가 충분히 제어 네트워크를 구성 할 만큼으로 나오는지가 참 궁금 했다.
<> Embedded Linux-Xenomai 포팅
우선 실시간 운영체제가 필요하므로 RTOS를 준비 한다.
예전에 작은 휴머노이드 로봇에 Embedded Linux-Xenomai를 포팅해 보행 알고즘을 RT-Task로 구동 시켰었는데 하루 종일 구동시켜도 아주 안정적으로 잘 되었었다. 당시에는 리눅스 커널 2.6대를 포팅해서 사용했었으나 이번에 3.10대 커널 버전으로 업그레이드 하여 포팅 하였다. Xenomai 패치 역시 그 상위 버전을 사용하였으며 2.6대 커널과 좀 달랐다.
우선 2.6대 커널에서는 Xenomai 2.3대 버전 패치를 사용했었으며 실시간 태스크 시간지연(latency) 측정시 유저레벨, 커널레벨, IRQ레벨의 시간지연에 차이가좀 많았다. 유저레벨의 시간지연이 가장 크고 IRQ레벨이 가작 작았으나 3.10대 커널에서는 Xenomai 2.6대 패치를 사용하고 유저, 커널, IRQ레벨에서 시간지연이 이전 버전에 비해 골고루 비슷하게 나왔다. 최소, 최대간 편차도 많이 줄어 Xenomai 패치 버전이 올라가면서 실시간 안정성도 상당이 좋아졌다는 것을 느꼈다.
참 대단한 양반 들이다.
포팅 버전은 다음과 같다.
linux-3.10.18
xenomai-2.6.3
리눅스 계열 실시간 패치에 대해 잠깐 언급을 좀 하자면 실시간 패치에는 RTLinux, RTAI, Montavista, Xenomai등이 있으나 Xenomai 패치를 제외하고 나머지는 모두 상용 버전이다. 사용 할려면 수천만원씩 돈 주고 소스를 사야한다. 빌드된 커널 바이너리만 살경우 단가는 조금 낮다. 물론 돈주니까 기술 지원은 빵빵할거다.
RTLinux인지 RTAI인지, 아니면 둘다인지는 기억이 가물가물한데 무료 버전이 있으나 커널버전 2.4대이다. 아주 오래전에 포팅해본적이 있는데 어느놈이었는지 기억이 가물가물하다. RTLinux(RTAI인가? 아.. 치매끼)가 유료화 되면서 이에 반발하는 커널 패치 개발자 집단이 새로 만든게 Xenomai이다. 때문에 Native Skin의 API들을 보면 RTLinux(RTAI인가?)와 비슷하다.
리눅스 실시간 패치별로 실시간성 성능 측정을 한 논문을 찾아 본적이 있는데 각 패치별 실시간 성능은 비슷비슷하게 잘 나왔던걸로 기억한다.
Xenomai 패치 개발자들은 이렇게 좋은걸 만들어 놓고도 돈도 안받으면서 뭘로 먹고 사는지 모르겠다. 프로그래밍 좋아하는 재벌집 2세들인가?...
다시 본론으로...
사용한 보드는 국내 Falinux라는 회사에서 판매하는 제품이고 EZ-PXA270이라는 보드인데 여기에 포팅을 하였으며 이더넷 컨트롤러로 AX88796B가 사용되었다.
리눅스 커널에 포함된 AX88796 드라이버는 Normal Linux Kernel용 드라이버이므로 실시간 지원을 위해 Xenomai용 RTDM으로 새로 작성해야 한다. 아주 쉽다. 포팅도 정말 쉽다. 응?
툴체인은 crosstool-ng라는 툴을 사용해 만들어 썼다. 이쪽 분야에는 참 대단한 양반들이 넘쳐나는거 같다.
램디스크까지 포함해 포팅 완료된 리눅스 커널의 부팅 메시지는 아래와 같다.
[The Real-time OS is needed in my project.
I ported the embedded Linux-Xenomai on my PXA270 evaluation board.
I've used linux-3.10.18 and xenomai-2.6.3 for RTOS porting.
You should have to make(code) the Real-time Driver Module (RTDM) for Ethernet controller to use in the Xenomai.
In my PXA270 board, AX88796B Ethernet controller is attatched so I coded my real-time device driver for AX88796B which could be loaded at the Xenomai patched Linux kernel.
Bellow message is from my Xenomai patched PXA270 board with RAM-disk.]
-------------------------------------------------------------------------------
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 3.10.18-xenokang (root@localhost.localdomain) (gcc version 4.7.3 (crosstool-NG 1.19.0)38:29 KST 2014
CPU: XScale-PXA270 [69054117] revision 7 (ARMv5TE), cr=0000397f
CPU: VIVT data cache, VIVT instruction cache
Machine: Falinux EZ-PXA270 development board
Memory policy: ECC disabled, Data cache writeback
Run Mode clock: 208.00MHz (*16)
Turbo Mode clock: 520.00MHz (*2.5, active)
Memory clock: 104.00MHz (/2)
System bus clock: 104.00MHz
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
Kernel command line: console=ttyS2,115200 initrd=0xa2180000,3M ramdisk=8192 root=/dev/ram0
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 59512k/59512k available, 6024k reserved, 0K highmem
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
vmalloc : 0xc4800000 - 0xff000000 ( 936 MB)
lowmem : 0xc0000000 - 0xc4000000 ( 64 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.text : 0xc0008000 - 0xc01efecc (1952 kB)
.init : 0xc01f0000 - 0xc020817c ( 97 kB)
.data : 0xc020a000 - 0xc0223bc0 ( 103 kB)
.bss : 0xc0223bc0 - 0xc0249a6c ( 152 kB)
SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Preemptible hierarchical RCU implementation.
NR_IRQS:512 nr_irqs:289 289
sched_clock: 32 bits at 3250kHz, resolution 307ns, wraps every 1321528ms
I-pipe, 3.250 MHz clocksource
Interrupt pipeline (release #1)
Console: colour dummy device 80x30
Calibrating delay loop... 518.55 BogoMIPS (lpj=2592768)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
Setting up static identity map for 0xc018a0e8 - 0xc018a138
DMA: preallocated 256 KiB pool for atomic coherent allocations
bio: create slab at 0
Switching to clocksource ipipe_tsc
Trying to unpack rootfs image as initramfs...
rootfs image is not initramfs (no cpio magic); looks like an initrd
Freeing initrd memory: 3072K (c2180000 - c2480000)
I-pipe: head domain Xenomai registered.
Xenomai: hal/arm started.
Xenomai: scheduling class idle registered.
Xenomai: scheduling class rt registered.
Xenomai: real-time nucleus v2.6.3 (Lies and Truths) loaded.
Xenomai: starting native API services.
Xenomai: starting RTDM services.
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
pxa2xx-uart.0: ttyS0 at MMIO 0x40100000 (irq = 22) is a UART1
pxa2xx-uart.1: ttyS1 at MMIO 0x40200000 (irq = 21) is a UART2
pxa2xx-uart.2: ttyS2 at MMIO 0x40700000 (irq = 20) is a UART3
console [ttyS2] enabled
brd: module loaded
mousedev: PS/2 mouse device common for all mice
XScale iWMMXt coprocessor detected.
RAMDISK: gzip image found at block 0
VFS: Mounted root (ext2 filesystem) on device 1:0.
Freeing unused kernel memory: 96K (c01f0000 - c0208000)
init started: BusyBox v1.22.1 (2014-05-12 11:39:31 KST)
starting pid 20, tty '': '/etc/init.d/rcS'
Please press Enter to activate this console.
starting pid 27, tty '': '-/bin/sh'
[root@pxa270 /]#
-------------------------------------------------------------------------------
<> 노드 구성
우선 초기 시험용 노드는 윈도우의 MFC로 개발하였으며 이더넷 프레임 엑세스를 위해 WinCAP설치가 필요하다. 윈도우 OS는 비실시간 커널이므로 노드를 구성하기에 적합하지 않지만 일단 리소스가 좋으므로 빠르게 코딩하여 확인해 볼 수 있다.
실제 시나리오와 비슷한 상황을 만들기 위해 일전에 이더넷이 되는 ARM9 기반의 KS8695 임베디드 보드에 EtherCONN 노드 기능을 구현하여 시험을 진행 했다.
스위칭 허브는 ipTime의 H205를 사용해 구성 하였다.
모두 100Mbps에 Full Duplex로 일반 랜케이블 연결이다.
[For the fist test, I buildup the Node on the Windows PC with Microsoft MFC. It's just for code implementation test, so the finished code was ported into the ARM9 based KS8695 Ethernet application processor for the real-time response.]
<> 시험 결과
정말정말 궁금했다.
우선 노드를 Windows 7 (x64)과 Windows XP에서 소프트웨어로 구현해 호스트 읽기 패킷에 대한 응답의 시간 지연(latency)을 측정해 봤다.
<> 결론
Windows 7의 시스템 성능이 좋아서 인지 응답이 조금 빠르다. 응답이 빠르다고 해서 좋은게 아니고 일정한 값, 즉 예측이 가능해야 한다. 그러나 보면 알겠지만 지연시간이 들쭉날쭉하다. 더군다나 시간지연이 심하게 튀는 경우도 있다 (예측 불가 시스템, 즉 비실시간 OS라는 것을 반증한다).
만약 시험중 메모리 스와핑이 일어난다면 더 심할 수도 있을 것이다.
위 그래프에 나오지는 않지만 수십분이상 장시간 구동시 제어 시퀸스가 깨질정도로 지연이 발생 되었다.
Windows XP에서는 허브를 사용한것과 허브 없이 바로 연결해 허브에 의한 영향을 보았으나 Look-up Table에 의한 하드웨어 스위칭이므로 큰 영향은 없는 것으로 보인다.
내가 알고 싶은 데이터는 마지막 그래프이다. OSless로 돌아가는 KS8695 컨트롤러가 호스트(PXA270)의 요청에 의해 250[us]이내 응답을 보여 준다.
그리고 최소, 최대간 수치가 수십[us] 내에서 일정하고 예측가능해 보인다. 즉 실시간 응답이라는 뜻이다.
KS8659의 EtherCONN 응답처리는 인터럽트 기반으로 가장 빠르게 응답 할 수 있도록 구성했다.
물론 수십시간-수일-수년 구동시의 반복성과 노드의 숫자, 노드에 적용된 CPU 자체 부하량등 다른 요인에 의한 변동 가능성도 검증이 필요하지만 수십ms의 실시간 태스크를 이용한 제어 네트워크 구성에 이더넷은 큰 문제 없이 사용될 수 있을 것으로 보여진다.
시간이 된다면 RTOS끼리 EtherCONN 데이터를 주고 받는 같은 실험을 해봤으면 좋겠다.
[Last graph represent the propagation delay (Latency) measured in EtherCONN Host(PXA270).
The 100ms real-time task is running on Linux-Xenomai and sends the read request packet to the KS8695. The KS8695 processor sends back to the EtherCONN Host as soon as recognize the Host's read request packet at the interrupt level.
My Ethernet real-time driver measures time between sending and receive.
The experimental result shows that the response latencies are varied just in XX[us]. It's means that the propagation delay is predictable and can be apply to real-time control network.
Yeah it's needed more specific test, the propagation delay could be change with respect to the number of Nodes, Node CPU's load, operation time and so on.
But in my opinion with this experimental results, The Ethernet is good enough for building real-time control network with some conditions.]
이번 글 제목이 아주 거창하다.
한물간 PXA270 프로세서에 실시간 운영체제인 Linux-Xenomai를 포팅하고 거기에 실시간 Ethernet 디바이스 드라이버 (RTDM - Realtime Driver Model/Module)를 올려 Ethernet을 이용한 제어 네트워크를 구성해 보았다.
[Let me publish this thread in English also because I've gathered a lot of useful information from the English web pages.
Please be patient with my lack of English.
In this thread, I'll introduce the possibility of using Ethernet as control network. And a little experimental result will be shown at the end of this text.]
우선 RS-232/422/485 (흔히 UART)계열은 심플하지만 물리 레벨에서 에러에 대응하기가 힘들고 속도 또한 최대 수Mbps까지만 가능하다. 트랜시버 칩들 사양을 보면 수Mbps가 가능하지만 UART 제어기의 한계로 인해 보통 수백Kbps만 주로 사용된다.
구현이 간단하고 MODBUS등 상위 프로토콜 스택을 올려 몇몇 서보모터에 사용된다.
CAN통신은 제어 네트워크 구성에 최적화 되어있다.
이름도 Control Area Network다.
패킷자체가 물리레벨에서 노드들간에 중재(Arbitration)가 이루어 지도록 만들었다.
우선순위가 높은 ID를 갖는 패킷이 하드웨어단에서 가장 먼저 전송되도록 구성된다.
고안해낸 기술자들이 정말 대단하다는 말밖엔...
에러에 강인하고 통신거리가 길게는 수Km대나 된다.
왠만한 8/16/32bit 컨드롤러에 UART처럼 내장되어 싼값에 사용할 수 있는 장점이 있다.
다만 최대 전송 속도가 1Mbps라 많이 아쉽다.
서보모터 제어에 아주 많이 사용된다.
전송 속도 한계로 인해 보통 한개 버스에 6~12개 정도 서보모터만 연결해서 사용하므로 다축 제어 네트워크 구성시 채널 수를 늘릴 필요가 발생될 수 있다.
USB는 수십~수백byte의 데이터를 주로 사용하는 제어 네트워크 구성에 몇가지 애로사항이 있다.
우선 너무 복잡하다. 수많은 디스크립터들...
USB디바이스 드라이버나 USB클라이언트용 펌웨어를 코딩해보신 분이라면 잘 아실 것이다.
디스크립터만 보다 시간 다 보낸다...
디스크립터 찍어 볼려고 printk() 만 주구장창 토나오게 코딩했던 기억이 있다.
핸드 쉐이킹에 사용되는 패킷이 많아 제어용 네트워크 보다 대량의 데이터 전송에 적합하다.
또한 호스트용 제어기와 클라이언트용 제어기가 달라 부품수 한개, 펌웨어 코딩 종류 한개라도 줄이려는 개발자에겐 부담스럽다.
IEEE1394는 참 잘만들었다. 32bit 기반으로 설계되어 32bit 프로세서에 아주 좋다.
프로토콜 특성상 핸드쉐이킹 오버헤드가 적어 480Mbps의 USB2.0 보다 400Mbps의 IEEE1394a의 성능이 훨씬더 좋다.
USB와 라이벌(?) 관계였으나 어느순간 일반 시장에서 사라져 버렸다.
왜일까?
우선 개발자 입장에서 보면 1394관련 문서는 돈주고 사야된다.
무료로 배포되는 USB와 다르다.
IEEE1394 펌웨어 코딩하려고 자료들좀 뒤져볼라 치면 회원 가입해야 하고 돈 내라고 하고...
짜증이 몰려온다. 여간 불편한게 아니었다. 당연히 USB로 가는수 밖에...
1394 컨트롤러도 제한적이고 구하기 쉽지 않으며, 그러다 보니 단가가 쎄다.
군용 항공기 표준으로 사용되는듯 하다. 헝그리 개발자는 자료 구하기가 힘들다.
이밖에 1553B가 있으나 1Mbps가 최대이고 군용이라 제어기 구하기 쉽지않다.
제어기도 엄청 비싸고 크다. 군용 항공기에서 오랬동안 써왔기 때문에 검증됐다는거 말고는 별 매력이 없다.
라인 연결시에도 노드별 신호 분배기(Stub) 같은걸 계속 달아줘야 하는 참 거추장스러운 네트워크이다.
Ethernet 프레임을 이용한 EtherCAT이 있는데 호스트(Master)측은 일반 이더넷 컨트롤러를 사용해도 되지만 노드(Slave)측에는 별도의 전용 하드웨어 칩이 필요하다.
OS기반으로 돌아가는 서보모터에 일부 달려나온다.
[I've programming experience with some serial network, UART(RS-232/422/485), CAN, USB, IEEE1394, Ethernet at the firmware level for manipulation of the registers and raw packets.
So, I could make my own view to apply some well known serial network to the real-time control.
Advantages and disadvantages for using real-time control network
UART
- ADVT: simple, low cost
- DISA: rack of hardware error robustness, low speed (up to X[Mbps])
CAN
- ADVT: this was born for control network, low cost
- DISA: low speed (up to X[Mbps])
USB
- ADVT: abundant, high speed
- DISA: complex(so many descripters), seperated to host and client hardware chip, not suitable for control network because of lot of handshaking overheads
IEEE1384
- ADVT: high speed, well organized
- DISA: exclusive (you may pay some money just to read the protocol specification), expensive
EtherCAT
- ADVT: designed for control network, high speed
- DISA: special hardware chip for client device is needed
Ethernet (this is not mean the TCP/IP)
- ADVT: abundant, high speed, little simple, low cost
- DISA: not suitable for control network but can be overcome
And there are so many serial protocols such as 1553B, SPI, I2C, LIN and so on for local area networking.
But I choosed the Ethernet because of abundant, high speed, little simple and low cost.
The Ethernet is not desined for real-time control network.
Back pressure, PAUSE, Jamming packet generation features are crashing the predictive charater of the packet transmission.
But I think I can overcome in some condition.
- Use as full-duplex
- Host-Node organization (Only Host can arbitrating the whole the buses)
- Disable the auto generation of the Back-pressure, Jamming and PAUSE frame (This could be in Ethernet device driver by setting the control registers simply)
Ethernet is not Master-Slave network model. But I'll make the only one Ethernet node works as bus master (I'll call this is the Host).
And the others are just Nodes (Slaves). The Nodes are work as passive (send packet just when the Host's request).
In this condition, we could make the Ethernet as predictable.]
잘 아시다 시피 원래 Ethernet는 제어용으로 설계된 네트워크가 아니다.
그러나 우선, 아주 흔해 제어기 구하기가 쉽다. 종류와 벤더가 많으니 단가도 싸다.
Gbps까지 나오니 속도도 넘쳐난다. 고속 스위칭 허브도 싸게 구할 수 있다.
랜케이블... 쓰레기통에 버려야 할 많큼 많다.
헝그리 개발자에겐 아주 매력적이다.
다만 Ethernet을 제어용으로 쓰기 위해서는 다음 사항을 유의 해야 한다.
- Full Duplex 사용: Half Duplex 사용시 JAM신호와 같은 Bus Arbitration 패킷이 제어에 필수 요소인 예측 가능성을 없애 버린다. 그러나 걱정 할 필요 없다. 요즘 Half Duplex 구성은 구경하기 힘들다.
- 호스트-노드 (Master-Slave) 구성: Ethernet는 P2P 구성이 기본이다 (모두가 Master). 하지만 제어를 위해 한개 호스트를 지정해 그 호스트가 모든 버스를 제어하도록 한다. 보통 제어 네트워크를 구성하면 제어 알고리즘이 돌아가는 측에 Feedback 루프가 돌고 있으므로 어쩔 수 없이 한개 호스트는 반드시 존재 해야 한다.
- 호스트: 해당 노드들에 필요한 데이터를 요청하여 읽고 명령을 보낸다.
- 노드: 호스트의 데이터 요청이 있을때만 패킷을 전송하며 그 외에는 오직 수신만 한다. 명령이 수신되면 해당 명령을 수행한다.
- Ethernet 레지스터 설정시 Back Pressure나 JAM신호 발생, PAUSE 신호 발생 등 Bus Arbitration 기능은 모두 정지 시킨다.
서론이 참 많이 길었다.
이제 시작...
<> EtherCONN (Ethernet CONtrol Network)
이더넷을 이용한 제어 네트워크 구성 명칭을 나는 'EtherCONN (Ethernet CONtrol Network)' 이라고 부르려고 한다.
[I'll call my project as 'EtherCONN (Ethernet CONtrol Network) and the standard Ethernet frame is used as like bellow.]
[Standard and EtherCONN Frame]
이더넷 패킷은 잘 아시는것 처럼 맨 위와 같다.
이더넷 프레임의 데이터를 위 두번째 처럼 구성한다.
[Upper diagram is standard Ethernet frame and lower is my EtherCONN.
You can use your own value for 2byte EtherType/Length(TL) like 0x0601. I used this field as Length and this is IEEE 803.2 Ethernet frame.
The Ethernet's Data field is separated into 3 region. ADDR(4byte address), CTRL(4byte control) and DATA.]
Type/Length 부분은 본인 임의대로 정해 사용하면 된다. 길이를 지정해 IEEE 803.2프레임으로 사용해도 되고 0x0601과 같이 잘 사용되지 않는 Type을 적용해도 된다.
이더넷 프레임의 데이터 부분을 4바이트 주소와 4바이트 제어코드 그리고 128바이트의 데이터로 구분한다. 그러므로 EtherCONN 프레임은 최대 150바이트가 된다.
EtherCONN 노드들 중에는 메모리가 부족한 8bit 기반이 될 수도 있기에 데이터 크기를 128바이트로 제한 했다 (필요에 따라 그 이상 혹은 그 이하로 설정해 사용할 수도 있다).
주소는 가상의 주소로 해당 노드의 가상 주소에 호스트가 읽기 쓰기를 수행 한다.
호스트입장에서 노드는 마치 읽고 쓰기가 가능한 메모리 장치와 같다고 볼 수 있다.
호스트는 xx:xx:xx:xx:xx:xx 맥어드레스를 갖고 있는 노드의 메모리를 읽고 쓰는 것이다.
한번에 움직이는 데이터는 최대 128byte이므로 한개 노드가 호스트에 제공 가능한 가상 메모리 크기는 다음과 같다.
2^32(4G) x 128byte = 512GB
호스트가 노드의 메모리에 쓰기를 하는지 읽기를 하는지 알려줄 필요가 있으므로 4바이트 제어코드에 담는다. []안의 숫자는 비트 번호이다.
ctrl[31] : 0=write, 1=read
ctrl[30:16]: reserved
ctrl[15:0] : data length
즉, ctrl의 31비트를 0으로 해서 호스트가 노드에 전송 할경우 데이터 쓰기가 되고 1일 경우 읽기가 되며 이때 노드는 ADDR(4)에서 지정한 주소지의 데이터를 호스트에 보내야 한다.
128바이트 데이터를 모두다 사용 하지 않을 수도 있으므로 ctrl[15:0]에 데이터 크기를 지정하며 1바이트만 주고 받을 수도 있다.
아래 예시를 보면 이해가 좀 쉬울듯 하다.
[The EtherCONN Nodes are work as just like a memory device as seen in Host, so the Host's jobs are just reading and writing data from/to the Nodes.
The ADDR is 4-byte address for memory to access which is existed virtually in the EtherCONN Node.
The 4-byte CTRL has bit-mapped control to specify read or write cycle (packet). Simply, when the 31st bit is zero '0' the packet is write packet (Host->Node or Node->Host), so the receiver should store to his internal memory or perform the pre-promised action by the data in that packet.
When the 31st bit is one '1' in the CTRL the packet is read request. And the receiver of this packet should send a packet back with data specified at the read request packet's address.
Bit 15~0 of the CTRL represent the length of the DATA in byte to read or write.
I've limited the EhterCONN data up to 128-byte because of possibllity of low performance Node based on 8/16bit micro-processor but, you can change this limitation by your own way.
Check the EtherCONN packet example bellow, and you may easily understand.]
<> 제어 시나리오
간단한 제어 시나리오를 생각해 보자. 호스트는 주기 100ms로 제어 알고리즘을 돌리고 있는것으로 가정한다.
1. 0ms에는 센서 노드에 읽기 패킷을 보내고 구동 노드(모터,솔레노이드,LED,스피커,열선 등등)에는 초기값을 쓰기 패킷에 보낸다.
2. 다음 100ms에는 전에 보낸 읽기 패킷에 의한 센서노드의 응답이 FIFO(링버퍼)에 저장되어 있으므로 센서 값을 FIFO에서 읽어 제어 루틴을 1회 돌린다.
3. 제어 루틴에서 만들어진 출력 값은 구동 노드에 쓰기 패킷으로 보낸다. 동시에 센서 노드에도 읽기 패킷을 보낸다.
4. 2번으로 간다.
때에 따라 로봇이나 매니퓰레이터처럼 모든 구동 노드들의 동시구동(Sync/Trigger)이 필요 할 때가 있을 것이다. 이때는 브로드캐스팅 맥어드레스(FF:FF:FF:FF:FF:FF)를 사용하면 간편하게 해결된다.
위 제어 시나리오가 잘 돌기 위해서는 정확한 100ms 실시간 태스크를 돌려줄 OS가 필요하고 EtherCONN 노드는 읽기 패킷을 수신하자 마자 가장 빠르게 호스트에 응답해야 한다.
호스트에 대한 노드의 응답은 보통 OSless 펌웨어 기반으로 인터럽트에 의한 응답이므로 빠르다 (RTOS를 적용 할 경우 사용된 RTOS의 인터럽트 지연시간에 많이 의존할 것이다). 데이터 준비등이 필요하나 for() 루프에 의한 수백 바이트 데이터 복사는 수~수십[us]이내에 끝난다.
중요한것은 호스트의 읽기 패킷이 랜케이블을 타고 스위칭 허브를 지나 노드에 전달 되고 노드의 응답이 다시 랜케이블과 스위칭 허브를 지나 호스트까지 전달 되는 물리적인 시간 지연 (latency) 이다.
이더넷 프레임을 이 제어용으로 사용 했을 경우 그 시간 지연이 알고 싶었으며 그 수치가 충분히 제어 네트워크를 구성 할 만큼으로 나오는지가 참 궁금 했다.
<> Embedded Linux-Xenomai 포팅
우선 실시간 운영체제가 필요하므로 RTOS를 준비 한다.
예전에 작은 휴머노이드 로봇에 Embedded Linux-Xenomai를 포팅해 보행 알고즘을 RT-Task로 구동 시켰었는데 하루 종일 구동시켜도 아주 안정적으로 잘 되었었다. 당시에는 리눅스 커널 2.6대를 포팅해서 사용했었으나 이번에 3.10대 커널 버전으로 업그레이드 하여 포팅 하였다. Xenomai 패치 역시 그 상위 버전을 사용하였으며 2.6대 커널과 좀 달랐다.
우선 2.6대 커널에서는 Xenomai 2.3대 버전 패치를 사용했었으며 실시간 태스크 시간지연(latency) 측정시 유저레벨, 커널레벨, IRQ레벨의 시간지연에 차이가좀 많았다. 유저레벨의 시간지연이 가장 크고 IRQ레벨이 가작 작았으나 3.10대 커널에서는 Xenomai 2.6대 패치를 사용하고 유저, 커널, IRQ레벨에서 시간지연이 이전 버전에 비해 골고루 비슷하게 나왔다. 최소, 최대간 편차도 많이 줄어 Xenomai 패치 버전이 올라가면서 실시간 안정성도 상당이 좋아졌다는 것을 느꼈다.
참 대단한 양반 들이다.
포팅 버전은 다음과 같다.
linux-3.10.18
xenomai-2.6.3
리눅스 계열 실시간 패치에 대해 잠깐 언급을 좀 하자면 실시간 패치에는 RTLinux, RTAI, Montavista, Xenomai등이 있으나 Xenomai 패치를 제외하고 나머지는 모두 상용 버전이다. 사용 할려면 수천만원씩 돈 주고 소스를 사야한다. 빌드된 커널 바이너리만 살경우 단가는 조금 낮다. 물론 돈주니까 기술 지원은 빵빵할거다.
RTLinux인지 RTAI인지, 아니면 둘다인지는 기억이 가물가물한데 무료 버전이 있으나 커널버전 2.4대이다. 아주 오래전에 포팅해본적이 있는데 어느놈이었는지 기억이 가물가물하다. RTLinux(RTAI인가? 아.. 치매끼)가 유료화 되면서 이에 반발하는 커널 패치 개발자 집단이 새로 만든게 Xenomai이다. 때문에 Native Skin의 API들을 보면 RTLinux(RTAI인가?)와 비슷하다.
리눅스 실시간 패치별로 실시간성 성능 측정을 한 논문을 찾아 본적이 있는데 각 패치별 실시간 성능은 비슷비슷하게 잘 나왔던걸로 기억한다.
Xenomai 패치 개발자들은 이렇게 좋은걸 만들어 놓고도 돈도 안받으면서 뭘로 먹고 사는지 모르겠다. 프로그래밍 좋아하는 재벌집 2세들인가?...
다시 본론으로...
사용한 보드는 국내 Falinux라는 회사에서 판매하는 제품이고 EZ-PXA270이라는 보드인데 여기에 포팅을 하였으며 이더넷 컨트롤러로 AX88796B가 사용되었다.
리눅스 커널에 포함된 AX88796 드라이버는 Normal Linux Kernel용 드라이버이므로 실시간 지원을 위해 Xenomai용 RTDM으로 새로 작성해야 한다. 아주 쉽다. 포팅도 정말 쉽다. 응?
툴체인은 crosstool-ng라는 툴을 사용해 만들어 썼다. 이쪽 분야에는 참 대단한 양반들이 넘쳐나는거 같다.
램디스크까지 포함해 포팅 완료된 리눅스 커널의 부팅 메시지는 아래와 같다.
[The Real-time OS is needed in my project.
I ported the embedded Linux-Xenomai on my PXA270 evaluation board.
I've used linux-3.10.18 and xenomai-2.6.3 for RTOS porting.
You should have to make(code) the Real-time Driver Module (RTDM) for Ethernet controller to use in the Xenomai.
In my PXA270 board, AX88796B Ethernet controller is attatched so I coded my real-time device driver for AX88796B which could be loaded at the Xenomai patched Linux kernel.
Bellow message is from my Xenomai patched PXA270 board with RAM-disk.]
-------------------------------------------------------------------------------
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 3.10.18-xenokang (root@localhost.localdomain) (gcc version 4.7.3 (crosstool-NG 1.19.0)38:29 KST 2014
CPU: XScale-PXA270 [69054117] revision 7 (ARMv5TE), cr=0000397f
CPU: VIVT data cache, VIVT instruction cache
Machine: Falinux EZ-PXA270 development board
Memory policy: ECC disabled, Data cache writeback
Run Mode clock: 208.00MHz (*16)
Turbo Mode clock: 520.00MHz (*2.5, active)
Memory clock: 104.00MHz (/2)
System bus clock: 104.00MHz
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
Kernel command line: console=ttyS2,115200 initrd=0xa2180000,3M ramdisk=8192 root=/dev/ram0
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 59512k/59512k available, 6024k reserved, 0K highmem
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
vmalloc : 0xc4800000 - 0xff000000 ( 936 MB)
lowmem : 0xc0000000 - 0xc4000000 ( 64 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.text : 0xc0008000 - 0xc01efecc (1952 kB)
.init : 0xc01f0000 - 0xc020817c ( 97 kB)
.data : 0xc020a000 - 0xc0223bc0 ( 103 kB)
.bss : 0xc0223bc0 - 0xc0249a6c ( 152 kB)
SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Preemptible hierarchical RCU implementation.
NR_IRQS:512 nr_irqs:289 289
sched_clock: 32 bits at 3250kHz, resolution 307ns, wraps every 1321528ms
I-pipe, 3.250 MHz clocksource
Interrupt pipeline (release #1)
Console: colour dummy device 80x30
Calibrating delay loop... 518.55 BogoMIPS (lpj=2592768)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
Setting up static identity map for 0xc018a0e8 - 0xc018a138
DMA: preallocated 256 KiB pool for atomic coherent allocations
bio: create slab
Switching to clocksource ipipe_tsc
Trying to unpack rootfs image as initramfs...
rootfs image is not initramfs (no cpio magic); looks like an initrd
Freeing initrd memory: 3072K (c2180000 - c2480000)
I-pipe: head domain Xenomai registered.
Xenomai: hal/arm started.
Xenomai: scheduling class idle registered.
Xenomai: scheduling class rt registered.
Xenomai: real-time nucleus v2.6.3 (Lies and Truths) loaded.
Xenomai: starting native API services.
Xenomai: starting RTDM services.
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
pxa2xx-uart.0: ttyS0 at MMIO 0x40100000 (irq = 22) is a UART1
pxa2xx-uart.1: ttyS1 at MMIO 0x40200000 (irq = 21) is a UART2
pxa2xx-uart.2: ttyS2 at MMIO 0x40700000 (irq = 20) is a UART3
console [ttyS2] enabled
brd: module loaded
mousedev: PS/2 mouse device common for all mice
XScale iWMMXt coprocessor detected.
RAMDISK: gzip image found at block 0
VFS: Mounted root (ext2 filesystem) on device 1:0.
Freeing unused kernel memory: 96K (c01f0000 - c0208000)
init started: BusyBox v1.22.1 (2014-05-12 11:39:31 KST)
starting pid 20, tty '': '/etc/init.d/rcS'
Please press Enter to activate this console.
starting pid 27, tty '': '-/bin/sh'
[root@pxa270 /]#
-------------------------------------------------------------------------------
<> 노드 구성
우선 초기 시험용 노드는 윈도우의 MFC로 개발하였으며 이더넷 프레임 엑세스를 위해 WinCAP설치가 필요하다. 윈도우 OS는 비실시간 커널이므로 노드를 구성하기에 적합하지 않지만 일단 리소스가 좋으므로 빠르게 코딩하여 확인해 볼 수 있다.
실제 시나리오와 비슷한 상황을 만들기 위해 일전에 이더넷이 되는 ARM9 기반의 KS8695 임베디드 보드에 EtherCONN 노드 기능을 구현하여 시험을 진행 했다.
스위칭 허브는 ipTime의 H205를 사용해 구성 하였다.
모두 100Mbps에 Full Duplex로 일반 랜케이블 연결이다.
[PXA270 Host, Switching HUB, KS8695 Node]
[Connection Diagram]
[For the fist test, I buildup the Node on the Windows PC with Microsoft MFC. It's just for code implementation test, so the finished code was ported into the ARM9 based KS8695 Ethernet application processor for the real-time response.]
<> 시험 결과
정말정말 궁금했다.
우선 노드를 Windows 7 (x64)과 Windows XP에서 소프트웨어로 구현해 호스트 읽기 패킷에 대한 응답의 시간 지연(latency)을 측정해 봤다.
[Packet Latency with Node on Win7 x64 with Intel Xeon]
[Packet Latency with Node on WinXP with Intel i5]
[Packet Latency with Node on WinXP - without HUB]
[Packet Latency with Node on KS8695 OSless Firmware]
<> 결론
Windows 7의 시스템 성능이 좋아서 인지 응답이 조금 빠르다. 응답이 빠르다고 해서 좋은게 아니고 일정한 값, 즉 예측이 가능해야 한다. 그러나 보면 알겠지만 지연시간이 들쭉날쭉하다. 더군다나 시간지연이 심하게 튀는 경우도 있다 (예측 불가 시스템, 즉 비실시간 OS라는 것을 반증한다).
만약 시험중 메모리 스와핑이 일어난다면 더 심할 수도 있을 것이다.
위 그래프에 나오지는 않지만 수십분이상 장시간 구동시 제어 시퀸스가 깨질정도로 지연이 발생 되었다.
Windows XP에서는 허브를 사용한것과 허브 없이 바로 연결해 허브에 의한 영향을 보았으나 Look-up Table에 의한 하드웨어 스위칭이므로 큰 영향은 없는 것으로 보인다.
내가 알고 싶은 데이터는 마지막 그래프이다. OSless로 돌아가는 KS8695 컨트롤러가 호스트(PXA270)의 요청에 의해 250[us]이내 응답을 보여 준다.
그리고 최소, 최대간 수치가 수십[us] 내에서 일정하고 예측가능해 보인다. 즉 실시간 응답이라는 뜻이다.
KS8659의 EtherCONN 응답처리는 인터럽트 기반으로 가장 빠르게 응답 할 수 있도록 구성했다.
물론 수십시간-수일-수년 구동시의 반복성과 노드의 숫자, 노드에 적용된 CPU 자체 부하량등 다른 요인에 의한 변동 가능성도 검증이 필요하지만 수십ms의 실시간 태스크를 이용한 제어 네트워크 구성에 이더넷은 큰 문제 없이 사용될 수 있을 것으로 보여진다.
시간이 된다면 RTOS끼리 EtherCONN 데이터를 주고 받는 같은 실험을 해봤으면 좋겠다.
[Last graph represent the propagation delay (Latency) measured in EtherCONN Host(PXA270).
The 100ms real-time task is running on Linux-Xenomai and sends the read request packet to the KS8695. The KS8695 processor sends back to the EtherCONN Host as soon as recognize the Host's read request packet at the interrupt level.
My Ethernet real-time driver measures time between sending and receive.
The experimental result shows that the response latencies are varied just in XX[us]. It's means that the propagation delay is predictable and can be apply to real-time control network.
Yeah it's needed more specific test, the propagation delay could be change with respect to the number of Nodes, Node CPU's load, operation time and so on.
But in my opinion with this experimental results, The Ethernet is good enough for building real-time control network with some conditions.]
피드 구독하기:
글 (Atom)