레이블이 ABI인 게시물을 표시합니다. 모든 게시물 표시
레이블이 ABI인 게시물을 표시합니다. 모든 게시물 표시

1/10/2023

RS485 Modbus 와 SCADA 시스템2

1. ESP32 회로구성 

이전에 ESP32 Modbus 관련하여 정리한 것이 그림 때문에 너무 긴거 같아, 다시 두개로 나누어 정리한다. 
더불어,RS485 와 Modbus를 분리하여, 잘못 안 부분이 있다면, 수정하도록 하겠다. 

RS232 와 RS485 회로구성 (ESP32 회로도 참조)


1.1 RS232 와 RS485 회로구성 

ESP32는 RS232만 지원가능하며, RS232는 Full Duplex이며, RS485는 Half Duplex 이다. 
Modbus를 구성하려면 두가지 방법이 있는데, ESP32에서만 제공하는 회로도만 보고, 이해했다가, 
현재 사용하고 USB제품을 통해 Echo/Non Echo 모드를 알게되었다. 


  • RS485 Mod 구성 (회로도)
  1. Echo Mode: 이전 ESP32 Sample 회로도 with CD(Collision Detection)기능 
  2. Non-Echo Mode: 이전 ESP32 Sample 회로도  without CD(Collision Detection) 기능 

Echo/Non-Echo Mode 관련내용 

문제는 CD(Collision Detection)기능이 있는 Echo Mode를 ESP32에서 완전히 제공하고 있지 않으므로, 주의해햐한다.
동작은 되지만, 멈추는 현상이 발생하며, ESP-IDF를 업그레이드 하면 추후에 제공될 것이겠지만, 현재 내 버전은 그렇지 않다. 


1.2 RS485 Bus 와 다른 Bus 구성 비교  

  • RS485의 Tranceiver 간의 비교 
RS485 Tranceiver VCC마다 다 다를수 있으며, VCC의 Range 정해져 있지, 동일한 Volatage로 사용여부는 정해져 있지 않다. 
이는 아래의 CSMA/CD에서 CD부분에서 자세히 설명하겠다. 

  • Ethernet 와 RS485 Tranceiver 비교  
Etherent과 비교하면, 구성면에서 있어서 비슷한 구성, VCC가 다 동일하며, Volatage 기반으로 Collision Detection이 가능하다  

  • USB 와 RS485 Tranceiver 비교  
USB과 비교하면, USB Master에서 VCC/VDD 나오며 전력도 제어하는 구조로 상위와 완전다르다. 
USB는 Power만 가지고도, 끝도 없이 이야기 할수 있으므로, USB 세부사항들은 아래참고 


1.3 RS485 의 CD(Collision Detection) 기능 

CSMA/CD or CSMA/CA는 대부분 Bus의 Layer 2에서 제공을 해주는 기능이며, 공용 Bus를 같이 사용하기 위해서 사용되는 기술이다.
간단하게 말해, 공용 Bus에서 TX를 하기전에, CS(Carrier Sense) 즉, Bus 이용중인지 확인하고, TX를 하고, 
Collision을 어떻게 감지(Detection)하는지 혹은 피하는 기능(Avoid)이며, 이로 인하여, 여러 Device들이 MA(Multiple Access)하여 같이 통신하는 것이다. 


Layer 2의 CSMA/CD(유선) 와 CSMA/CA(무선) 차이
CSMA/CD(유선): 대표적인 것이 Ehternet 
CSMA/CA(무선):  대표적인 것이 WIFI 

Ethernet과 비교하면, 예전의 Dummy Hub를 사용할때의 구성과 현재 RS485 구성 얼추 비슷하게 보인다. 
RS485는 CSMA/CD를  Layer2 즉, RS485 Tranceiver에서 처리못하고, 이를 RS232를 걸쳐 SW로 처리 해야한다. 

  • Ethernet의 CD(Collision Detection)
Ethernet의 경우, 예전에 Dummy Hub에 Station을 연결하면 할 수록 속도는 떨어진다.
이유는 Station들간에  충돌나면, Volatage 변경되어 CD(Collision Detection)발생하고, 이 때문에, 
JAM 신호를 보내어 모든 Device를 멈추게 한다. 
그리고, 이런일이 반복되어지면, Backoff Time이 더 늘어난다.  
결론적으로 Station을 추가하면 추가할수록 Bus 속도는 기하급수적으로 늦어진다. 

  • RS485의 CD(Collision Detection) 다른이유 
RS485와 Ethernet 의 비슷하지만, Voltage기반으로는 Collision Detection을 하기가 힘들다 .(이유는 간단하다.)
RS485 Tranceiver Differential Range가 넓어서, Bus에서 각 Device 의 RS485 Tranceiver 마다 구동되는 VCC가 다를수 있다.
예를들면, 같은 RS485 Bus 내에서도, 어떤 Device는 Voltage 3.3v 사용하고, 어떤 Device Voltage 5v를 사용가능하다.
이를 특정 Voltage Thrshold Level 정해서 Collision Detection으로 하기가 힘든 구조이다. 
(물론 HW 보완해서 하면 얼마든지 가능하다)

  • RS485 와 Volatage Range(-12v/+12V)
RS485의 Differential Voltage Range가 넓은 이유는 거리때문일 것이라고 생각한다.
간단히 생각해보면, 거리가 길어질 수록 선로는 길어지며, 선로 저항값이 점점 늘어난다. 


2. ESP32 Modbus 구성 

  • Modbus 협회 사이트 
Modbus Main 협회사이트인 것 같은데, 주요 볼 것은 검색해서 나오는 링크일 것 같으며, Member로는 등록을 안했다. 
 
  • ESP32의 Modbus 관련정보 
ESP32의 Modbus 지원내용과 API 관련내용을 자세히 설명 


2.1  Modbus의 기본구성 

Modbus를 검색만 해도 너무 많은 자료가 나오는데, 검색된 블로그 들어가서 글을 읽으면, 
아래내용과 틀린부분이 있어, 아래의 2개의 링크를 추천 

  • Modbus의 Protocol 관련 링크 
Modbus의 Protocol 설명과 실제 예제 및 분석과 비교 까지 해주어서 괜찮음 

Modbus 기본적인 설명이 잘 정리되어있으나, 상위와 용어가 조금씩 다름 주의 


  • Modbus의 Object(Data) Types
Modbus는 아래의 4가지 Type으로 Data접근가능.
2byte 전송형태와 1bit 전송형태 구분
이는 Read Only 와 Read Write 로 나뉨
Object typeAccessSizeAddress Space
CoilRead-write1 bit0x0000 – 0xFFFF
Discrete inputRead-only1 bit0x0000 – 0xFFFF
Input registerRead-only16 bits0x0000 – 0xFFFF
Holding registerRead-write16 bits0x0000 – 0xFFFF

Modbus를 하기위해서는 상위 각 Object Type Address Map을 정의해야하며, 이기반으로 통신 
Modbus RTU/ASCII 이건 둘 다 Function Code 기본으로 상위 Read/Write  넣음 

Input register/ Holding Register Map 구현예제 


  • Modbus Frame Format
Modbus Frame은 아래 ADU(Application Data Unit)로 구성되며, 다시 PDU(Protocol Data Unit)구성형태이다.
  1. ADU = Address + PDU + Error check
  2. PDU = Function code + Data

2.2 Modbus Frame 종류

Modbus Frame 종류와 각 Physical Interface 관계는 아래와 같으며, 이를 기반으로 연결되어 통신을 한다.
주로 가장 많이 사용되어지는 것이 Modbus RTU 와 Modbus TCP 인 것으로 보이며, 
이 두 개를 연결 Mapping하여 Serial <-> Ethernet에서도 Control 할 수 있는 구조로 확장해서 사용하기도 한다. 

  • Modbus Frame 종류
  1. Modbus RTU : Serial (RS232/RS485) Binary 목적으로 개발 
  2. Modbus ASCII : Serial (RS232/RS485) ASCII 을 이용  
  3. Modbus TCP:  TCP Protocol이 지원되며, 이는 Modbus RTU와 연결도 가능 

상위 내용을 보면, Modbus ASCII 보다는 RTU가 더 효율적으로 보이며, Modbus TCP 호환으로 보아도 
Modbus RTU를 사용해야 할 것 같다. 
** 상위 링크에서 Modbus RTU 와 ASCII를 비교가능 



Modbus RTU와 구조는 유사하지만, Binary용 전송이아니라, 세부사항들이 조금씩 다르며, DATA 기본단위도 2byte단위
  1. Start는 0x3A End는 0x0D,0x0A 로 감지목적사용 
  2. Address는 Station Address로 2byte 사용하여 총 247까지 사용가능
  3. Function는  2byte Object Type 방식을 선택되어지는 것으로 각 Function에 따라 동작 
  4. 상위 Object Type 방식에 Address Space는 DATA에 포함되며 세부사항은 Format 참조

주의: Modbus RTU 와 동일한 Data를 전송할 경우, 항상 2배의 Data 량을 소비

Unit Address (PLC Address): 2byte
  1. Address: 0  Broadcast 목적
  2. Address: 1 ~247, 각 Station의 Address로 이며 Unit Address 이라고도 함  (1byte)
Modbus PDUMax 253x2 = 506bytes
  1. Function:  아래 Wiki 참조 
  2. Data: Function에서 결정되며, 2byte 단위로 Encode 되어진다고 한다.
LRC: 2byte Checksum 이며, CRC가 아님 

NameLength (bytes)Function
Start1Starts with colon : (ASCII hex value is 3A)
Address2Station address
Function2Indicates the function codes like read coils / inputs
Datan × 2Data + length will be filled depending on the message type
LRC2Checksum (Longitudinal redundancy check)
End2Carriage return – line feed (CR/LF) pair (ASCII values of 0D0A


  1. Start/End는 0으로 RTU Packet의 감지목적으로 사용 
  2. Address는 Modbus RTU Slave의 Station Address로 1byte허용하여 총 247까지 사용가능
  3. Function는 상위 Object Type 방식을 선택되어지는 것으로 각 Function에 따라 동작 
  4. 상위 Object Type 방식에 Address Space는 DATA에 포함되며 세부사항은 Format 참조

Unit Address (PLC Address): 1byte
  1. Address: 0  Broadcast 목적
  2. Address: 1 ~247, 각 Station의 Address로 이며 Unit Address 이라고도 함  (1byte)
Modbus PDUMax 253 bytes
  1. Function:  아래 Wiki 참조 
  2. Data: Function에서 결정
CRC: 2bytes

총 256 Bytes

NameLength (bits)Function
Start28[citation needed]At least 3½ character times of silence (mark condition)
Address8Station address
Function8Indicates the function code; e.g., read coils/holding registers
Datan × 8Data + length will be filled depending on the message type
CRC16Cyclic redundancy check
End28[citation needed]At least 3½ character times of silence between frames

** 주의 : 상위 Length는 Bits 단위


상위 Frame과 호환성을 가지기 위해서 Function code와 Unit Identifier로 구성되며, 이는 Modbus RTU와 쉽게 호환 
  1. Transaction ID는 상위 Start/End 목적처럼 Sync를 위한 감지목적 
  2. Protocol ID는 Modbus TCP는 0 
  3. Unit ID는 기존의 Stations Adddress
  4. Function는 상위 Object Type 방식을 선택되어지는 것으로 각 Function에 따라 동작 
  5. 상위 Object Type 방식에 Address Space는 DATA에 포함되며 세부사항은 Format 참조
  6. Modbus RTU over TCP의 경우, 아래의 CRC가 추가. 

Unit Identifier (PLC Address): 1byte
  1. Address: 0  Broadcast 목적
  2. Address: 1 ~247, 각 Station의 Address로 이며 Unit Address 이라고도 함  (1byte)
Modbus PDUMax 253 bytes
  1. Function:  아래 Wiki 참조 
  2. Data: Function에서 결정
CRC:  Modbus RTU over TCP에서 사용 

NameLength (bytes)Function
Transaction identifier2For synchronization between messages of server and client
Protocol identifier20 for Modbus/TCP
Length field2Number of remaining bytes in this frame
Unit identifier1Server address (255 if not used)
Function code1Function codes as in other variants
Data bytesnData as response or commands

* Modbus RTU over TCP의 경우 상위 끝에 CRC추가되어 Modbus RTU와 호환가능 

  • 상위 모든 정보는 Wiki기반으로 가져온것이며 세부내용은 아래 참조 
세부내용은 특히 Function 및 동작순서는 아래 Wiki에 너무 자세히 잘 나옴 


2.3 Modbus Request /Response  분석 

아래는 동일한 Station Address / Function / Data 이용하여 각 Frame 마다 전송비교 분석이며, 이를 쉽게 이해 할 수 있다. 

  • Read Input Register 예제 분석 
1. Request: Address 200 의 Size 2개의 Data 요청
2. Response : Size:4 byte 와 Data 2개 (0x2710, 0xC350) 

-------------------------------------------------------------------------------------------------------------------------------------
                Request	                                              |  Response
-------------------------------------------------------------------------------------------------------------------------------------                 
Modbus ASCII    3A                                                    | 3A                                                             // MODBUS ASCII START
                30 31                                                 | 30 31                         (ASCII:01)                      // Station Address 0 1 
                30 34                                                 | 30 34                         (ASCII:04)                      // Function  0 4  
                30 30 43 38 30 30 30 32 (ASCII:00C80002)              | 30 34 32 37 31 30 43 33 35 30 (ASCII:04 27 10 C3 50 )       // Data x 2byte 
                33 31                                                 | 41 44                                                          // LRC (Checksum)
                0D 0A	                                              | 0D 0A                                                          // END (CR/LF)
--------------------------------------------------------------------------------------------------------------------------------------
Modbus RTU	01 	                                              | 01                                                             // MODBUS RTU: Station Address(Unit) 1 
                04                  	                              | 04                                                             // Function 4 Read Input Register 
        	00 C8 00 02        Address: 200  Size:2x2             | 04 27 10 C3 50           (Byte:4, Data:2 words)                // Data x 1byte  (Size, Data 2 Words)
        	F0 35	                                              | A0 39                                                          // CRC
--------------------------------------------------------------------------------------------------------------------------------------
Modbus TCP	00 14                                                 | 00 14                                                          // MODBUS TCP: Transaction ID 2byte
          	00 00                                                 | 00 00                                                          // Protocol ID 2byte 
          	00 06                                                 | 00 07                                                          // Length  2byte 
                01                                                    | 01                                                             // Station Address(Unit) 1
                04          	                                      | 04                                                             // Function 4
                00 C8 00 02	   Address: 200  Size:2x2             | 04 27 10 C3 50                                                 // Data x 1 byte
---------------------------------------------------------------------------------------------------------------------------------------

상위예제는 Station(Unit) 1 주소로 Function 4의 Request/Resonse 구조로 보내는 Data는 동일하다. 
간단히 보면, ASCII로 보낼 경우, Packet Size가 두 배가 되어진다. 
Protocol을 보면, RTU 와 TCP는 쉽게 호환되어지는 구조이다. 


  • Modbus-RTU Write 와 Exception 확인
상위와 동일하게 아래를 참조하여 분석하면 된다.
Slave에서 에러가 발생하면, Response에서 Function Code 90h 과 함께 Exception Code가 별도로 존재 


3. Modbus TEST 방법 

다양한 Tool이 존재하지만 유료도 존재하여 나의 경우 Python 기반으로 테스트를 진행하였다.
  • libmodbus 와 PyModbus 이용


3.1 Python 기반의 Pymodbus TEST 방법 및 분석  

Python Pymodbus Manual
현재 나도 이기반으로 TEST Program들을 작성했으며, 다양한 예제가 있어 편하다.

  • PC에서 ModbusTCP/RTU/ASCII Slave 테스트
PC가 Modbus Master가 되어 IOT (Modbus Slave) 테스트 할 경우 소스이며 각 Function에 관련된 함수에 따라 각각의 테스트 가능 
  1. 상위 read/write coill 및 read only discreate input 테스트 가능 (1bit)
  2. 상위 read/write holding register 및 read only input register 테스트 가능 (2byte)

보통의 경우, sync용 예제를 봐야하며, async의 경우는 빠르게 보내는 경우에 사용되어진다고 보면될꺼 같다.
내 생각으로는 sync 와 async의 차이는 아래라고 하는데 추후 다시 확인해야하겠지만, blocking 과  non-blocking 의 차이라고 생각되어짐 
기본적으로 Unix System programing or network programing 알면 대충 이해가 되실듯함 
  1. sync : request 와 responce를  각 확인 인 되어 동작 (blocking mode) 일 것 같음 
  2. async: request하고 response는  그냥 blocking 없이 동작 (non blocking mode) 일 것 같음 

# 간단하게 이런식으로 연결후 원하는 정보를 읽어서 확인하면 된다 
# pip install pymodbus 

from pymodbus.client.sync import ModbusSerialClient

def run_sync_client():
    
    client = ModbusSerialClient(
        method='rtu',
        port=Port,
        baudrate=Baud,
        timeout=3,
        parity='N',
        stopbits=1,
        bytesize=8
    )
    if client.connect(): 
        print('connected to Modbus Slave UNIT=',UNIT)
    else:
        print('failed to connect to the Modbus Slave UNIT=',UNIT)
    


  • PC의 PayloadBuilder 와 PayloadDecoder 사용 및 확인이유  
Holding Register와 Input Register는 기본적으로 2byte 통신이므로 Byte Order과 Word Order가 따라 결과 값이 달라질 수 있다. 
  1. Byte Order: BigEndian/ Little Endian : CPU에 종속됨 (Word의 저장되는 순서)
  2. Word Order: Big Endian / Little Endian:  소스에서 확인해봐야함
PayloadBuild의 경우 Slave도 Write를 할 경우가 발생하는데, 이때 Holding Register를 이용하여 Write할 때 필요 
PayloadDecoder의 경우 이를 다시 Decode를 할 경우 사용 

PayloadBuilder 예제 (주로 write시 사용)
2byte단위 통신이므로 다양한 포맷으로 변경 및 추가하여 이를 Packet 생성 

PayloadDecoder 예제 (주로 read시 사용)
2byte 단위 통신이므로 다른 포맷으로 변환시 사용 


ESP32의 내부 Ordering 확인사항 
사실 Word Order는 u16을 u32로 확장할 경우, 문제가 발생하는 것으로 보인다. (기본 32bit CPU의 word는 4byte)
예를들면 struct로 u16로 두개로 잡은 후에 이를 u16 pointer에서 u32로 변경할 경우 u16의 두개가 위치, 즉 address를  확인해야함
modbus 내부 api에서 변경할 가능성도 있으므로 이는 상위 wiki 세부확인

ESP32의 경우 내부적으로 분석해보면, ESP32의 경우 Bigendian 혹 정확히 말하며 Binary로 보내는게 맞다.   
이는 아래와 같이 Data 영역에 Byte Align으로 Data를 저장하여 이를 Memory 접근한다.

Byte Align 방법 
아래의 preprocessor로 1 byte align을 하여 byte ordering에 상관없이 사용하고 있다. 
#pragma pack(push, 1)
typedef struct
{
...
}...
#pragma pack(pop)

  • PC의 PayloadDecoder 결론사항 
PyModbus에서 입장에서 Byte OderBigEndian Word OrderLittel Endian으로 해야 Float32가 제대로 보인다 
개인생각으로는 PyModbus가 받은 Data를 함수내에 Stack영역에 저장하여 발생되어지는 문제로 생각되어진다.
u16->f32을 확장할 경우 PC(Program Counter) 의 Address 가 위로 증가 할지, 아래로 증가할지는 각 영역(Stack/BSS/Init)에 따라 달라진다 

현재 이 부분은 현재 PyModbus가 Data 저장을 Stack영역에 저장하여 상위와 같은 현상이 발생되어지는 것으로 생각되어진다. 


TEST Program 확인사항
상위를 먼저확인 후 Builder를 이용하여 u32으로 register를 write 한 후 decoder로 이를 재확인필요


ESP32의 Core Cadence의 Tensilica (Xtensa LX6) 


Xtensa 의 ABI (너무 간단하게만 나오며, 함수와 ELF 관련내용)
혹시 몰라 Xtensa의 ABI도 링크함, 
ARM이나, Power PC에 비해 너무 간단하게 나오며, 아마 다른문서가 있을 거라고 생각됨
일단, 간단하게만 알고나 있도록하자.  

10/05/2018

Prebuilt Toolchain Download

1. Prebuilt Toolchain

Cross Compiler를 Prebuilt toolchains에서 배포하는 곳은 많으며, 대체적으로  BSP에서 제공해주는 것에  맞추어서 설치하면된다.
오래전 같으면 Cross Compiler를 직접빌드해서 사용했지만, 지금은 설치만 하면되니까,
그래도 직접 빌드는 안하지만 개념은 까먹지 않아야 할꺼 같아 정리한다.


  GCC (GNU Compiler)
  https://www.gnu.org/software/gcc/

일단 GCC의 동작 및 기본구성원리를 들을 알아보자.

1.1 GCC의 구성 및 동작 

GCC의 C Compiler만을 의미하는 것이 아니며, C, C++, Objective-C, Fortran, Ada, and Go 다양한 언어를 제공해주는 GNU의 Compiler이다


  • GCC의 구성도 
  1. Front End (각 언어에 (C/C++/Fortran) 맞게 Parsing 및 구조화 ) 
  2. Middle End ( Front End에서 생긴 것을 최적화) 
  3. Back End ( 각 Architecture에 맞게 PowerPC/ARM/X86  Machine Code 생성)


상위 그림은 LLVM에서 가져온것이지만 GCC도 거의 동일하다.

각 프로그래밍 언어는 Frontend에서 담당을 하므로, GCC에 추가한다면 Front End이다.
그래서 GCC C/C++만을 위한 것이 아니며, 다양한 언어를 지원한다.

  http://www.aosabook.org/en/llvm.html
  https://www.gnu.org/software/gcc/frontends.html

  • LLVM 
LLVM의 경우는 빌드성능이 좋다고는 하는데, 아직 사용해본 경험이 없으며, TI Compiler or 다른 컴파일러 사용해본 경험밖에 없어 뭐라고 하기가 그렇다.

  http://releases.llvm.org/

  • GCC Manual 
GCC를 이용할 경우 제공되어지는 옵션을 확인이 가능하며, Architecture별 옵션을 확인가능하다

GCC-4.8.5 전체 Manual
  https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/


  • Preprocessor 사용되는 Command 및 Manual 보는법 
GCC 과 다른 Compiler를 보면 Preprocessor 를 사용하는 방법이 다소 다를때가 많으며, 이는 어쩔수 없이 봐야할 부분인 것 같다.
많이 사용되는 곳이 Kernel 과 초기화 코드 및 관련부분이며, 일반 Application에서는 사실 거의 사용하지 않을 것이다.

아래와 같이 상위 Manual을 보면될 것이며, 자료가 방대하다보니 목록을 반드시 확인하고 보자.

#pragma
  https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Pragmas.html#Pragmas
  https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Function-Specific-Option-Pragmas.html#Function-Specific-Option-Pragmas

__attribute__ (함수/변수 시)
  https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Function-Attributes.html#Function-Attributes
  https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Variable-Attributes.html#Variable-Attributes


1.2 How To Build Cross Compiler 

아래의 사이트에서 크로스 컴파일러가 어떻게 만들어지는 간단하게 알아보자.

  https://rtime.felk.cvut.cz/hw/index.php/How_to_build_GNU_cross-compilers
  https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/
  https://wiki.osdev.org/GCC_Cross-Compiler

  • C만 지원하는 일반적 GCC 필요구성 
  1. binutils (linker 및 assember 포함) 
  2. gcc 
  3. glibc/uclibc/musl/newlib  (C library 의 종류)
  4. linux header  ( kernel 정보)

1.3 일반적인 GCC의 필요사항 

일반적인 GCC라면, C만 지원이 되는 glibc를 말할 것이며, 구성요소는 다음과 같다.

  • Linux Kernel header
  https://www.kernel.org/

  • GNU Binutils
  GCC에서 필요한 부분이며, Assembler 및 Linker / readelf/ objdump 및 각 필요한 tool
  https://www.gnu.org/software/binutils/

  • GNU GCC 
  https://gcc.gnu.org/releases.html

  • GNU C Library (다른 Library 생략)
  https://www.gnu.org/software/libc/
  https://en.wikipedia.org/wiki/Newlib


1.4. ABI 관련사항 

ABI(Application Binary Interface)는 CPU Architecture에서 어떻게 Register를 사용 및 할당할 것이지,
그리고CPU 입장에서 함수에 어떻게 변수를 전달할 것인지, 모든 규칙을 정의해놓은 Interface 규격이다.

예를들면, ARM의 PCS(Procedure Call Standard)를 보면, 함수를 호출시  Register로 어떻게 변수를 전달 할 것인지를 설명해준다.
이는 ARM만이 아니라 PowerPC/MIPS 다 존재하며 CPU의 Register 구조가 다르기 때문에 개별 ABI 가 필요하다. (이전 PowerPC는 GP Register 32개)
좀더 들어가면, Data Type , File Format, Stack 의 구조사용법 및  ELF의 동적링크 부분도 다 이 문서에 포함이 되어있다.


  • ABI의 관련사항 
  https://en.wikipedia.org/wiki/Application_binary_interface

  • ARM ABI 관련문서 
  http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html

  • MIPS ABI 관련문서 
  http://www.cygwin.com/ml/binutils/2003-06/msg00436.html


1.4.1 EABI와 OABI

EABI(embedded-application binary interface) 는 embedded system에서 최적화하기 위해서 만들어졌다고 한다.
더 자세히 말하면 ARM의 EABI는 ARM의 ABI의 일부사양일 뿐이라고 한다.
그리고, 기존의 ABI는 OABI(Old-ABI)로 불린다고 한다.
그러므로, 만약 설정할 일이 있다면, 설정추가를 하는것이지 설정을 변경할일은 아니다.

  • ARM EABI의 탄생배경
기존의 OABI는 FPU를 사용한다고 가정하 만들었기에 FPU와 통신을 해서 문제가 발생한다고 한다 ARM은 FPU가 있는 버전과 없는 버전이 존재한다.
그리고 이를 FPU관련 부분을 효율적으로 사용하기위해서 EABI가 나왔다고 한다.

Debian에서는 ToolChain도 ABI에 따라 3가지 Version으로 구분되어 나온다고 한다.

Architecture ABI FPU Releases
ARM OABI Not required, but very slow without All debian releases upto and including Lenny were OABI. It has since been deprecated.
ARMEL EABI Does not make use of FPU Lenny and beyond
ARMHF EABI FPU required. Specifically benefits from NEON architecture and VFP. Wheezy and beyond

참고로, 상위 Lenny, Wheezy는 Version의 이름이다.

  https://wiki.embeddedarm.com/wiki/EABI_vs_OABI


  • ARM EABI 관련내용 
  https://wiki.debian.org/ArmEabiPort

  • EABI 관련장점 정리사항  
  1. Floating point performance, with or without an FPU is fast and mixing soft and hardfloat code is possible
  2. Structure packing is not as painful as it used to be 
  3. More compatibility with various tools (in future - currently linux-elf is well supported)
  4. A more efficient syscall convention 

  • EABI의 관련장점 설명  
  1. 1번은 상위에서 설명했듯이 EABI의 탄생배경이며 근본적인 문제해결인 것 같다. 
  2. 2번의 경우 구조체의 packed의 문제가 뭔지 모르겠다. e.g.  __attribute__((packed, aligned(4)))
  3. 3번의 경우 binutil과 gcc에서 호환성을 의미하는 것 같다. 
  4. 4번의 syscall convention 변화 (syscall 의 규칙)
  http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=3105/4

  • ARM EABI와 OABI 비교사항 
  http://jake.dothome.co.kr/abi/


  • Android ABI(EABI) 관련내용 
Android에서 EABI를 사용한다고 하면 Kernel Config에서 다음을 설정한다고 한다.
  1. CONFIG_AEABI
  2. CONFIG_OABI_COMPAT
  https://developer.android.com/ndk/guides/abis?hl=ko
  https://wiki.kldp.org/wiki.php/AndroidPortingOnRealTarget/ko


2. 많이 이용되어지는 Prebuilt Toolchain for Linux 

  1. CodeSourcery  (SoC의 BSP/SDK와 함께 배포)
  2. Free Electrons (최근 bootlin 변경됨)
  3. Linaro (ARM) 

SoC와 함께 많이 제공해주던 곳이 CodeSourcery 이며, 이전에 OdroidX2를 가지고 놀때, Linaro도 같이 이용을 했지만 Linaro Version을 좀더 자세히 알고자 한다.

참고자료 및 경험
  https://elinux.org/Toolchains
  https://gcc.gnu.org/install/binaries.html


2.1 Free Electrons (Bootlin)

리눅스 관련된 최신문서가 잘 정리된 사이트이며, Tool chain도 Architecture 및 Library에 별로 다양하게 제공을 할 뿐더러
본인이 원하는 GCC의 내부구성 정보도 잘 보여준다.

uclibc의 경우는 오래전에 uclinux (ARM7, PowerPC) 할때 빼고는 거의 사용한 기억이없는것 같다.
uclibc를 가지고 opensource를 porting할 때마다 제한적이어서 고생한 기억만 나서 그런지,
참고로 uclinux의 경우 오랜전에 MMU가  없이도 가능 부팅이 가능(ARM7)하며, Power PC인 경우는 linux를 최적화하기위해서 사용했었다.

  • GNU Toolchain Download 
  https://toolchains.free-electrons.com
  https://toolchains.bootlin.com/


2.2 Mentor (CodeSourcery)

SoC와 같이 대부분 오래전부터 배포진행했으며, mentor사가 인수하여 지속적으로 배포를 하고 있다.
이전에는 montavista에서도 제공을 했던거 사용했는데 요즘은 어떻게 되었는지 잘모르겠다.

이전에 사용한 version
  https://ahyuo.blogspot.com/2015/11/arm-tool-chain.html 

각 기본정보를 확인
  https://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/

  • GNU Toolchain Download (정보 확인가능)
  https://sourcery.mentor.com/GNUToolchain/release1294
  https://sourcery.mentor.com/GNUToolchain/release2635
  https://sourcery.mentor.com/GNUToolchain/release2032

Mentor(CodeSourcery) 역시 보면 아래의 Linaro Version 처럼 EABI로 인해 나누어져 배포한다.

2.3 Linaro 

Linaro도 SoC와 함께 배포되어 Download하기가 쉽고 Ubuntu에서 설치가 쉬워서 요즘 많이 이용되어지는 것 같다.

  • Linaro 회사정보
  https://ko.wikipedia.org/wiki/%EB%A6%AC%EB%82%98%EB%A1%9C


  • GNU ToolChain Download
  https://www.linaro.org/downloads/
  https://releases.linaro.org/components/toolchain/
  https://releases.linaro.org/components/toolchain/binaries/latest-5/
  https://releases.linaro.org/components/toolchain/binaries/5.2-2015.11-2/


  • linaro 전체 release site 및 Git 
  http://releases.linaro.org/
  https://web.archive.org/web/20121031094507/http://git.linaro.org/gitweb


  • Tool Chain 관련전체문의  (컴파일러 옵션설명)
  https://wiki.linaro.org/WorkingGroups/ToolChain/FAQ

  • 컴파일러 Prefix의 의미 ( A-B-C)
A 는 target architecture 의미한다고 한다. 
(e.g. arm for AArch32 little-endian, aarch64 for AArch64 little-endian)

B 는 vendor 의미이며, 사용여부는 옵션 (배포한 Vendor) (none or unknown for generic)
일반적으로는 거의 사용하지 않는다고 하며, 아래에도 사용하지 않음 (e.g  not present in arm-linux-gnueabihf)

C 는 사용중인 ABI 의미를 말하며 관련 system(OS)도 기술한다.   
(e.g linux-gnu* for Linux, linux-android* for Android, elf or eabi for ELF based bare-metal).

Bare Metal ABI는 New Lib를 사용하고 NonOS용으로 사용한다고 한다   

  • 컴파일러 기능요약
본인이 Download or 설치한 컴파일러의 옵션의 지원여부를 정확히 알자. 
  1. hw fpu 지원/미지원
  2. little / big endian 
  3. glibc / newlib 사용 ( bare-metal : newlib 사용 (NonOS용) or glibc 이용)


e.g
arm-linux-gnueabihf -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=vfpv4
-mcpu=cortex-a7 -mfpu=vfpv4 -mfloat-abi=softfp|hard
-mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=softfp|hard


  • ARMv7
arm-linux-gnueabihf
 Toolchains for little-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems

arm-linux-gnueabi
Toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems

arm-none-eabi
Toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for bare-metal systems

armv8l-linux-gnueabihf
Toolchains for little-endian, 32-bit ARMv8 for GNU/Linux systems


  • ARMv8
aarch64-linux-gnu
Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems

aarch64-none-elf
Toolchains for little-endian, 64-bit ARMv8 for bare-metal systems

aarch64_be-linux-gnu
Toolchains for big-endian, 64-bit ARMv8 for GNU/Linux systems

aarch64_be-none-elf
Toolchains for big-endian, 64-bit ARMv8 for bare-metal systems



2.3.1. Linaro의 Ubuntu Package 지원

상위에서 linaro version에 대해 알았으니, Ubuntu에서 쉽게 설치하는 법을 알아보자

  • Ubuntu APT Package 사용법
  https://ahyuo.blogspot.com/2015/07/ubuntu.html


  • Ubuntu Toolchain 지원확인  
본인의 Ubuntu에서 지원되는 Toolchain을 찾아보자

$ sudo apt-cache search gcc-arm*  //현재 지원되는 Package를 찾아보자 
gcc-arm-linux-gnueabihf - The GNU C compiler for armhf architecture
gcc-arm-linux-androideabi - cross toolchain and binutils for Android/Bionic on ARM
gcc-arm-none-eabi - GCC cross compiler for ARM Cortex-A/R/M processors
gcc-arm-linux-gnueabi - The GNU C compiler for armel architecture

  • Ubuntu Toolchain 설치 
나의 선택은 당연히 hw float point가 지원되는 기능으로 선택했지만, androideabi와 차이는 아직 잘모르겠다.

$ sudo apt-get install gcc-arm-linux-gnueabihf
$ sudo find / -name arm-linux-gnueabihf* 
/usr/bin/xxxx //binutils , gprof gcov, gcc 설치 
/usr/share/man/man1/xxx
/usr/lib/gcc-cross/arm-linux-gnueabihf 
/usr/arm-linux-gnueabihf
/usr/x86_64-linux-gnu/arm-linux-gnueabihf
...  
 

기존의 TI의 am335x/am437x bsp에도 이미 동일한 이름으로 이미 설치가 되어있네요(arago project)
다음부터 가급적 Download해서 사용하고 PATH를 정하고 사용해야겠네요.

  https://blog.thinkbee.kr/linux/crosscompile-arm/
  https://blog.thinkbee.kr/linux/linux-update-alternatives/


3. Prebuilt Toolchain for Window

오래전에, Cygwin용을 자주 사용했는데, 개발환경의 제약으로 인해 점점 사용하지 않게되었다.
다시 사용할 일이 있다면 다음아래의 사이트에서 Download하자

Cygwin용
  http://cygwin.com/

Mingw 용
  https://mingw-w64.org/doku.php


4. Eclipse GCC 사용 

아직 적용을 해보지 못했으며, 궁극적으로 모든것을 Eclipse 기반으로 하고 싶은 생각을 가지고 있다.
매번 Terminal에서 make와 shell script를 이용하여 하고 싶지 않으며, 이용하더라도 Eclipse에서 편하게 사용하는 방법을 찾고자 한다.

Eclipse와 함께사용
  https://www.codeguru.com/cpp/cpp/getting-started-with-c-for-eclipse.html