Serial 통신
하나의 통신선에서 한 번에 하나의 데이터 신호 연속적 전송
데이터가 계속되어 전송되면 각 비트를 구별할 방법이 필요
클럭 신호 사용 유무에 따라 동기/비동기 전송 방식
Serial 통신 ex)
UART, USART, I2C, Ethernet, CAN 등

병렬(Pareallel) 통신
여러 개 통신선에서 "동시" 여러 데이터 신호를 보냄
데이터 신호를 전송하기 위해 "여러 통신선"이 필요함
병렬통신 ex)
SCSI, PCI, IEEE-1284 등

동기 전송
동기 펄스를 사용해 송신자와 수신자의 "비트 타이밍"을 맞추는방식
데이터 통신선외 공통 클럭펄스를 사용해 데이터의 시작을 식별함
데이터는 Block 또는 Frame단위로 전송
데이터블록의 전/후에 특정 제어 정보 삽입
동기 전송 ex)
I2C, USART, SPI, JTAG 등
SPI 통신 시작 방법 :
1️⃣ MISO(Master In Slave Out) :
Master의 MISO pin은 Slave의 MISO pin과 연결되어야 함.
MSB먼저 8-bit Serial Data가 전송 됨.
2️⃣ MOSI(Master Out Slave In) :
Master의 MOSI pin은 Slave의 MOSI pin과 연결되어야 함.
MSB먼저 8-bit Serial Data가 전송 됨.
3️⃣ SCLK(Serial Clock) pin : Master 입장에서 출력
Master가 제공하는 SCLK는 관련 register에 의해 clock의 초기 [V] level을
High/Low중에서 선택할 수 있고, 위치도 조정 가능하다.
전송율(bit-rate)도 지정가능하다.
Slave와 정확히 통신하기 위해 clock 설정이 상호 동일해야 한다.
4️⃣ CS(Chip Select) pin : Master 입장에서 출력
SPI slave mode 입장에서, 전송은 "CS pin"이 "LOW level"이 될 때
"CS pin"이 "HIGH"가 될 때, 종료됨.
clock과 마찬가지로 Master가 CS를 발생시킴.


CPHA=0이면 !SS(!CS)일때 송/수신을 시작하는 것이고
CPHA=1이면 SCLK edge에 맞춰 송/수신을 시작하는 것이다.
그림상 CPHA=0 일때 파란선이 첫번째 빨간선 앞에 하나 더 있어야 하는데
그림에는 그게 빠져있다.
비동기 전송
일정한 크기의 데이터에
start bit와 stop bit를 넣어서 구분하여 전송
수신측은 통신선에 시작비트를 감지 -> 데이터 수신을 시작
비동기 전송 ex)
UART, CAN 등

CAN 송/수신 방법:
CAN bus가 idle 상태이고,
송신 노드가 CAN 프레임을전송
수신 노드는 CAN 프레임의 시작비트(SoF)를 수신하면
데이터를 수신하기 시작
종료비트(EoF)가 들어오면 수신종료

UART는 위 3가지 통신방식 모두지원


Start Bit :
통신의 시작을 의미, 한비트 "시간길이"만큼 유지
Data Bit :
최대 8비트의 데이터 전송이 가능,
몇 비트 사용할것인지는 해당 레지스터 설정에 따라 결정
Parity Bit :
수신측에서 전송 받은 데이터에 오류 발생했는지 검증하는데 사용됨
고치지지는 못함(송신측에서 포함해 전송)
3-1. 홀수 Parity : Parity포함해 1의 개수가 홀수면 제대로 받았다 판단
3-2. 짝수 Parity : Parity포함해 1의 개수가 짝수면 제대로 받았다 판단
단점으론, 모든 오류 검출도 불가능할 뿐더러 , 오류 비트의 정확한 위치도 알 수 없고 복구도 못함. TCP처럼 제어를 할 수가 없음.
Stop Bit :
통신의 종료를 알림
Bit Rate, bps :
1초당 전송되는 비트의 개수
Baud Rate :
1초당 전송되는 데이터묶음(심볼)의 개수
UART의 데이터묶음은1bit, baud rate = bps
송/수신 장치는 Baud Rate를 일치시켜야함.
속도가 다르면, 다른 값이 읽히게 됨.(Bit Timing Error)
표준속도: 4800, 9600, 19200, 38400, 57600, 115200 …
원래는
×Bits per Symbol (하나의심볼이담고있는비트수)를 하여 bps를 구한다.
ASCLIN(Async/Synchronous Interface) :

CLC는 SPB와 같은 Clock을 받는다
Interrupt Router도 확인할 수가 있다.

ASCLIN0은 5pin연결로 UART Serial 통신에 쓸 수 있다.
Clock
디지털회로가 동작하기 위한 가장 기본적인 신호
항상 있어야 함.
크리스탈
Clock을 발생시키는 부품소자
MCU에 정현파(sin)를전달
MCU는 정현파를 이산화하여 1과0의 사각파로받음
MCU는 클럭을 이용하여 명령어를 수행함
Clock은 MCU 또는
주변기기(peripheral)가
동작을 수행할 수 있게 하는 전기적신호
⚙️ 크리스털(Crystal)
진동자의 역할만 하는 수동 부품.
일반적으로 쿼츠(quartz)라는 물질을 이용한 공진기.
외부에 전자회로가 제공되면, 정해진 주파수로 진동함.
(ex: 8MHz, 16MHz 등)
혼자선 클럭 생성 불가 → 반드시 외부에 오실레이터 회로가 필요함.
✔ ex :
STM32 + 8MHz 크리스털 → 내부에 있는 오실레이터 회로가 크리스털을 진동시켜 클럭 생성
⚙️ 오실레이터(Oscillator)
크리스털 + 오실레이터 회로가 하나의 모듈로 패키징된 부품
전원(VCC)만 공급하면 자동으로 클럭 신호를 출력함
(ex. 3.3V 입력 → 16MHz 클럭 출력)
내부에 이미 크리스털 + 증폭 회로 포함되어 있음
보다 정밀하고 안정적인 클럭이 필요할 때 사용
✔ ex :
16MHz 오실레이터 모듈 → 4핀 패키지 (VCC, GND, OUTPUT, NC or ENABLE 등)
여하튼, 20MHz의 외부 Crystal이 있기 때문에 공급 받는다.
아키텍처에 따라 이를 어떻게 쓸 지는 상이한데
STM32에서는 PLL회로로 배수화 시켜서 Clock을 제공하는걸로 기억함.
모듈의 통신속도를 설정
Clock Source: f_A(CSR.CLKSEL에 의해 다음중 하나로 설정)
f_ASCLINF : f_source2(PLL2=200MHz)/ASCLINF DIV(분주)
f_ASCLINS : f_source1(PLL1=320MHz)/ASCLINS DIV(분주)


여기도 PLL회로 쓰는걸 볼 수 있음
Shift Engine :
Port를 통해 실제 데이터 전송
LIN Engine
LIN 통신을 사용할 경우 데이터 전송
Clock Source:
f_CLC(f_SPB와 동일)
f_SPB : System Peripheral Bus, 기본 클럭 100Mhz 사용

FIFO는 MCU 내부버스와 외부 송수신 데이터를 연결해주는 인터페이스 역할
FIFO에 I/O하는 데이터 크기는 8/16/32-bit 중 선택 가능

동작 Mode에 따라 사용하는 Pin이 다름
실습에서는 Standard ASC (Asynchronous Communication)를
사용하므로 ARX/ATX Pin 사용

여러 동작 Mode가 존재함을 알 수 있다.
당연히 Port 뒤는 MCU고

그래서 전체를 보면 이렇게 연결되는 구조를 갖고 있다.
외부 I/O Port :
동작 Mode에따라 사용되는 Pin의 I/O를설정
ASCLIN0 기준으로 보면,

Input과 Output을 볼 수 있다.
참고로 지원하는 Interrupt는
Tx/RxFIFO는 최대 16Byte 저장가능


TxData에 FIFO의 LSB를 LSB에 담고 있음

RxData에 FIFO의 LSB를 LSB에 먼저 담고 있음.
전체적인 아키텍처 View를 보면

ASCLIN Module Register 구성

주요 레지스터들만 살펴보자.

ASCLIN Module Active/Inactive Control Register
Reset시 Default로 3이 들어가서
Disable, Disable 상태로 설정된다.

Port Module의 IOCR Register와 다르기 때문에 헷갈리면 안된다.
ASCLIN Module의 RX, TX 신호 관련 설정 레지스터
단, TX Pin 출력 설정은 Port 모듈의 IOCR 레지스터에서 설정

RX 핀입력설정은 ALTI 필드를통해설정가능
ALTI :
Alternate Input Select


전체적으로 이런 레지스터들이 있다.

ASCLIN Module의 Clock Source를 설정하는 레지스터
Reset Value = 0x00
Clock Flag
IOCR, BITCON, FREAMECON 등등 많은 레지스터의 헤더들을 보면 이게 0일때 쓰여질 수 있다.
왜 그러냐면, Init할 때 공급자체를 막아놓고 설정하는게 당연하니까
Usecase에 적혀있다고 하더라.
0 : Clock is off
1 : Clock is on
위 그림에서 보면 Source를 선택할 수가 있었다. 그것을 선택하는 레지스터.
Baudrate 관련 설정 레지스터


The BITCON Register defines the integer timer parameters
in the baud rate generation block.
Note: The register is only writable, if CSR.CLKSEL=0.
(Line 5) The clk source gets set in the clock selection register CSR (Clock Selection Register). Before setting a
source, no clk supply (CSR(4:0)=0) must be set. Final clk selection in Line 20.
SM[31]: 비트당샘플개수설정
0: 1
1: 3
SAMPLEPOINT[27:24]: Sample Point 위치 설정
0: 0,(X)
1: 1,(X)
…,
FH: 15
OVERSAMPLING[19:16]: Oversampling 설정
0: 1,
1: 2,
…,
FH: 16
PRESCALER[11:0]: Prescaler 설정 (0~4095)

Baud Rate 계산을 위한 Numerator, Denominator 설정 레지스터
NUMERATOR[27:16] : 0 ~ 4095
DENOMINATOR[11:0] : 0 ~ 4095
범위에 주의하여 Baud Rate를 정하도록 감안해야 함.


BRD는 모듈이 LIN 슬레이브로 동작할 때 자동 Baud Rate 감지를 위한 특정 속성들을 정의한다.
Note: The register is only writable, if CSR.CLKSEL=0.
역시나 속성은 Clock 끊고 하라.

사실 LIN은 탈피하고 있으니 이정도로만..

reset : 0x00
UART 통신 Frame 설정 register



PEN[30] : Parity Enable
0(Disabled) / 1(Enabled)
MODE[17:16] : Mode Selection
01 : ASC Mode
STOP[11:9] : Number of Stop Bits
001 : 1, ..., 111 : 7
보면 MSB Shift Direction도 변경할 수 있다.

reset : 0x00
데이터 한 개의 비트 길이를 설정하는 레지스터
DATLEN[3:0]: Data Length
0H: 1,
… ,
FH: 16
HO[13] : Header Only
LIN frame이 헤더 ONLY인지 Response 포함인지를 설정
0 : Header and response expected
1 : Header only expected, response ignored
RM[14] : Response Mode
RESPONSE 필드가 어떤 기준으로 동작할지를 결정
0 : Frame(Header + Response 전체에 대한 시간 제한)
1 : Response(Slave로부터의 응답 데이터 전송 부분만 시간 제한)
CSM[15] : Checksum Mode
클래식/강화 버전 Checksum 적용 선택
0 : Classic
1 : Enhanced
RESPONSE[23:16]
Response Timeout 한계값 1 to 256 bit times 범위 내 설정.
2~5(4제외)는 LIN 통신에 관한 내용이다.
Reset : 0x00

TX FIFO 설정레지스터
INW[7:6]: Transmit FIFO Inlet Width
즉, 1개의 FPI Bus로 송신 FIFO에 TX할(W) Byte 수를 정하는 것
00: 0
01: 1
10: 2
11: 4
ENO[1]: Transmit FIFO Outlet Enable
출구 활성화로, 송신하고 싶으면 반드시 1로 설정해야함.
0: Disabled,
1: Enabled
FLUSH[0]: Flush the transmit FIFO
전송 오류나 초기에 비우고 보낼 때 쓰면 되겠다.
Buffer Flush 역할
0: No effect,
1: Empty the Tx FIFO
RXFIFOCON (RX FIFO CONfiguration register)
Reset : 0x00

RXFIFO 설정 레지스터
BUF[31]: Receive Buffer Mode
0이면 그냥 RXFIFO처럼 동작하고,
1이면 32bit를 덮어 쓰는 단일 버퍼로 동작함.
받은 bit는 LSB부터 채워지고 남는 곳은 Zero-Padding 수행
어떤 의미가 있는지는 잘 모르겠다
0: RXFIFO
1: Single Stage RX Buffer
OUTW[7:6]: Receive FIFO Outlet Width
마찬가지로, RX할(R) Byte 수(word 단위)
00: 0
01: 1
10: 2
11: 4
ENI[1]: Receive FIFO Inlet Enable
마찬가지로 출구 허용, 당연히 수신하려면 1로 열어줘야 함.
0: Disabled
1: Enabled
FLUSH[0]: Flush the receive FIFO
마찬가지로 Flush 용도
0: No effect,
1: Empty the Rx FIFO
Reset : 0x00

TX/RX Data가 실제로 저장되는 Register
위 Register들은 설정이고, 실제 Data는 여기에 담긴다.
이게 FIFO로 간다.
보면 1word 구성인데 위에서
설정에 따라 병렬적으로 4word를 받는다고 하니까,
4word라면 FIFO에 4번 R/W를 하여 보내지 않을까 싶음.
CLC(CLock Control register)값을 변경하려면,
WDT(Watch Dog Rimer)의 ENDINIT을 0으로 변경해야 함.
ENDINIT: 의도치 않은수정을방지하기위해사용되는쓰기보호체계
Clock을 설정할 때, 해줘야 한다.
TC375는 보안성이 좋아서 그런듯
BSW/Driver/asclin.c
void Asclin0_InitUart(void)
{
…중략…
/* Enable ASCn */
IfxScuWdt_clearCpuEndinit(IfxScuWdt_getGlobalEndinitPassword());
MODULE_ASCLIN0.CLC.U = 0;
IfxScuWdt_setCpuEndinit(IfxScuWdt_getGlobalEndinitPassword());
…중략…
}
참고로, WDT는 전원 감시 뿐만 아니라, 시스템 다운(무한 loop) 등 기타 안 좋은 상태를 감시하다가 문제 생기면 시스템을 Reset해주는 것으로 알고 있다. 또 보안 문제시 reset이나 안전기능(ISO26262 ASIL 상태 트리거용 등) 역할을 수행해 준다.
강사님께서 OTA를 통해 Flash에 접근하시다가
MCU가 잠겨서 못쓰게 되어버렸다는데
아마 얘가 감지하고 시스템을 잠궈버리는거 아닌가 싶음.
Datasheet를 참고하면, 5pin USB로 PC와 Serial 통신이 가능한데
기본적으로
P14.0 : ASCLIN0 TX
P14.1 : ASCLIN0 RX(Alternate Input A)
로 연결 되어있다.
ASCLIN4로도 이 곳을 쓸 수 있는데 이 경우엔 P14.0/P14.1이 설정되지 않도록 확실히 하라고 쓰여있다.

Datasheet대로 TX는 Port의 IOCR에서 설정을 해야할거고,
RX는 ASCLIN Module의 IOCR에서 설정을 해야할 것.
RX인 P14.1은 (ARXA)
ALTI[2:0]에서 Alternate Input A selected인 000을 골라준다.
TX인 P14.0은 (ATX)
GPIO설정처럼 출력 설정을 해준다.
void Asclin0_InitUart(void)
{
…중략…
/* Set TX/P14.0 to "output" and "high" */
MODULE_P14.IOCR0.B.PC0 = 0x12;
MODULE_P14.OUT.B.P0 = 1;
…중략…
/* select RX as input pin */
MODULE_ASCLIN0.IOCR.B.ALTI = 0; // Select Alternate Input A
…중략…
}
보면 Port에서 설정하니까 P14.0은 GPIO때처럼 설정을 하고 있다.
P14.1은 MODULE_ASCLIN0 구조체의 IOCR을 건드려 설정하고 있다.

Push Pull = Out pin이 High일때, VCC를 연결해 Out하고, Low일 때, GND를 연결해 출력하는 일반적인 방식이다. LED 점등 등에 쓰이며, VCC와 GND를 직접 연결한다.
Open Drain = Low일때 핀을 GND에 연결하고, High일때 Floating(신호가 애매한 상태)상태가 된다. 이때 외부에 Pull-up 저항을 연결해 High상태를 보장해 주어야 한다.
주로 I2C통신 같이, 여러 장치가 동일한 bus를 공유하는 경우에 사용하며, Pull-up 저항에 따라 갖는 값들이 변하게 된다.
GPIO Pull-up/Pull-down
:GPIO에서 Floating 상태 방지를 위해 쓰는 저항 기법
Pull-up = 내부 저항을 통해, pin을 VCC로 방향으로 당김.
기본 High상태에서 button같이 특정 신호가 입력된다면, GND 방향으로 당겨 Low상태로 바뀜.
Pull-down = Pull-up의 반대 개념. 기본이 Low상태, Input시 High로
No pull-up and no pull-down = 별도 풀업, 풀다운 저항 사용하지 않음. Floating에 주의해야 함.
BRG 레지스터의 분모(Denominator), 분자(Numerator) 설정

일반적으로 Sample Point는 60%인 지점을 채택한다고 한다.

STM에서 Prescaler과 Auto-Reload Register 값을 설정할 때,
Prescaler는 낮게 ARR은 높게 설정해 정확도를 높였던 것 처럼
여기도 정확도를 높이기 위해 Oversampling값을 높게 채택한다.
그럼에도 불구하고 Putty를 통해 보면 가끔씩 이상한 값이 나온다.
빠르면 빠를수록 더 그렇다.
일단, 설정을 안해서 100MHz가 들어오기 때문에 그것을 바탕으로 계산해보면

이렇게 분모와 분자를 구할 수가 있다.
부정방정식을 통하여, 다른 통신속도에 대해서도 구할 수가 있다.
이제 이걸 BRG에 넣어주면 된다.
void Asclin0_InitUart(void)
{
…중략…
/* set baudrate value */
MODULE_ASCLIN0.BRG.U = (denominator << 0) /* DENOMINATOR */
| (numerator << 16); /* NUMERATOR */
…중략…
}
iLLD 제공은 Union Type이라 Bit field가 아닌 U를 통해 Shift하여 넣어주자.
(계산하기 힘드니까)
MODULE_ASCLIN0.BITCON.U = ( 9 << 0) /* PRESCALER: 10 */
| (15 << 16) /* OVERSAMPLING: 16 */
| ( 9 << 24) /* SAMPLEPOINT: position 7,8,9 */
| (1u << 31); /* SM: 3 samples per bit */
/* configure TX and RX FIFOs */
MODULE_ASCLIN0.TXFIFOCON.U = (1 << 6) // INW:1 byte
| (1 << 1) /* ENO */
| (1 << 0); /* FLUSH */
/* configure TX and RX FIFOs */
MODULE_ASCLIN0.RXFIFOCON.U = (1 << 31)
| (1 << 6)
| (1 << 1)
| (1 << 0);
void Asclin0_InitUart(void) :
1. Asclin0 초기화 함수, 115200 bps로 설정됨
2. Micro 5pin USB와 연결되어 있음
3. SYSTEM_Init() 함수에서 호출됨
void Asclin0_InitUart(void)
{
/* set numerator and denominator for 115200 baudrate */
unsigned int numerator = 576;
unsigned int denominator = 3125;
/* RXA/P14.1, TX/P14.0 */
/* Set TX/P14.0 to "output" and "high" */
MODULE_P14.IOCR0.B.PC0 = 0x12;
MODULE_P14.OUT.B.P0 = 1;
/* Enable ASCn */
IfxScuWdt_clearCpuEndinit(IfxScuWdt_getGlobalEndinitPassword());
MODULE_ASCLIN0.CLC.U = 0;
IfxScuWdt_setCpuEndinit(IfxScuWdt_getGlobalEndinitPassword());
/* read back for activating module */
(void)MODULE_ASCLIN0.CLC.U;
/* select RX as input pin */
MODULE_ASCLIN0.IOCR.B.ALTI = 0; // Select Alternate Input A
/* Program ASC0 */
MODULE_ASCLIN0.CSR.U = 0;
/* configure TX and RX FIFOs */
MODULE_ASCLIN0.TXFIFOCON.U = (1 << 6) /* INW: (1 == 1 byte) */
| (1 << 1) /* ENO */
| (1 << 0); /* FLUSH */
MODULE_ASCLIN0.RXFIFOCON.U = (1 << 31) /* BUF: (1 == Single Stage RX Buffer) */
| (1 << 6) /* OUTW: (1 == 1 byte) */
| (1 << 1) /* ENI */
| (1 << 0); /* FLUSH */
/* 115200 */
MODULE_ASCLIN0.BITCON.U = ( 9 << 0) /* PRESCALER: 10 */
| (15 << 16) /* OVERSAMPLING: 16 */
| ( 9 << 24) /* SAMPLEPOINT: position 7,8,9 */
| (1u << 31); /* SM: 3 samples per bit */
/* data format: 8N1 */
MODULE_ASCLIN0.FRAMECON.U = (1 << 9) /* STOP: 1 bit */
| (0 << 16) /* MODE: Init */
| (0 << 30); /* PEN: no parity */
MODULE_ASCLIN0.DATCON.U = (7 << 0); /* DATLEN: 8 bit */
/* set baudrate value */
MODULE_ASCLIN0.BRG.U = (denominator << 0) /* DENOMINATOR */
| (numerator << 16); /* NUMERATOR */
MODULE_ASCLIN0.FRAMECON.B.MODE = 1; /* ASC mode */
MODULE_ASCLIN0.CSR.U = 1; /* select CLC as clock source */
MODULE_ASCLIN0.FLAGSSET.U = (IFX_ASCLIN_FLAGSSET_TFLS_MSK << IFX_ASCLIN_FLAGSSET_TFLS_OFF);
/* Initialize ASCLIN0 RX interrupt */
// volatile Ifx_SRC_SRCR *src;
// src = (volatile Ifx_SRC_SRCR *)(&MODULE_SRC.ASCLIN.ASCLIN[0].RX);
// src->B.SRPN = ISR_PRIORITY_ASCLIN0_RX;
// src->B.TOS = 0;
// src->B.CLRR = 1; /* clear request */
// MODULE_ASCLIN0.FLAGSENABLE.B.RFLE = 1; /* enable rx fifo fill level flag */
// src->B.SRE = 1; /* interrupt enable */
}
주석처리는 Interrupt를 위한 register 설정들
MISRA-C에 의거해 매직 넘버를 피하기 위해
Define으로 전처리 기능을 사용하여 사용한다.
당연히 분리해서 Include해줘야 함.
int Asclin0_PollUart(unsigned char) :
Polling방식, 수신 성공시 1, 실패시 0 return
int Asclin0_PollUart(unsigned char *chr)
{
unsigned char ret;
int res = 0;
if (MODULE_ASCLIN0.FLAGS.B.RFL != 0) /* If RX Ready */
{
ret = (unsigned char)MODULE_ASCLIN0.RXDATA.U;
/* acknowledge receive */
MODULE_ASCLIN0.FLAGSCLEAR.U = (IFX_ASCLIN_FLAGSCLEAR_RFLC_MSK << IFX_ASCLIN_FLAGSCLEAR_RFLC_OFF); // RX Clear
/* check for error condition */
if ((MODULE_ASCLIN0.FLAGS.U) & ((IFX_ASCLIN_FLAGS_PE_MSK << IFX_ASCLIN_FLAGS_PE_OFF) | \
(IFX_ASCLIN_FLAGS_FE_MSK << IFX_ASCLIN_FLAGS_FE_OFF) | \
(IFX_ASCLIN_FLAGS_RFO_MSK << IFX_ASCLIN_FLAGS_RFO_OFF)))
{
/* reset error flags */
MODULE_ASCLIN0.FLAGSCLEAR.U = ((IFX_ASCLIN_FLAGSCLEAR_PEC_MSK << IFX_ASCLIN_FLAGSCLEAR_PEC_OFF) | \
(IFX_ASCLIN_FLAGSCLEAR_FEC_MSK << IFX_ASCLIN_FLAGSCLEAR_FEC_OFF) | \
(IFX_ASCLIN_FLAGSCLEAR_RFOC_MSK << IFX_ASCLIN_FLAGSCLEAR_RFOC_OFF));
/* Buffer clear, reset module */
}
else
{
/* this is a valid character */
*chr = ret;
res = 1;
}
}
return res;
}
unsigned char Asclin0_InUart(void) :
1 Byte 수신 함수, Blocking 방식 (1 Byte 입력 될 때까지 대기)
unsigned char Asclin0_InUart(void)
{
unsigned char ch;
/* wait for a new character */
while (Asclin0_PollUart(&ch) == 0);
return ch;
}
while문에서 PollUart로 받아질 때 까지 Blocking중
char Asclin0_InUartNonBlock(void) :
1 Byte 수신 함수, Non-Blocking 방식
(함수 호출 시점에 입력이 없으면 다른 값 반환)
char Asclin0_InUartNonBlock(void)
{
unsigned char ch = 0;
int res = Asclin0_PollUart(&ch);
return res == 1 ? ch : -1;
}
입력 없으면 걍 -1 대입해 반환해버림
void Asclin0_OutUart(const unsigned char chr) :
1 Byte 송신 함수, Blocking 방식
void Asclin0_OutUart(const unsigned char chr)
{
/* wait until space is available in the FIFO */
while (!(MODULE_ASCLIN0.FLAGS.B.TFL != 0));
/* TX Clear */
MODULE_ASCLIN0.FLAGSCLEAR.U = (IFX_ASCLIN_FLAGSCLEAR_TFLC_MSK << IFX_ASCLIN_FLAGSCLEAR_TFLC_OFF);
/* send the character */
MODULE_ASCLIN0.TXDATA.U = chr;
}
참고로 Flag관련하여 iLLD는 이렇게 되어있음.

자세한 내용은 Datasheet의
1. FLAGS
2. FLAGSSET
3. FLAGSCLEAR
4. FLAGSENABLE




레지스터 항목을 참조
사실은 FLAGS만 잘 보면 된다 SET/CLEAR/ENABLE이기 때문에
어쨋든 FLAGS 레지스터들을 보면
TH[0] : Transmit Header End Flag
Signals the HEADER_TX_END event. Set by hardware, clear by software.
If enabled, a transmit interrupt is triggered.
0 : No HEADER_TX_END event since the last clear by software
1 : New HEADER_TX_END event since the last clear by software
TR[1] : Transmit Response End Flag
Signals that RESPONSE_TX_END event. Set by hardware, clear by
software.
If enabled, a transmit interrupt is triggered.
0 : No RESPONSE_TX_END event since the last clear by software
1 : New RESPONSE_TX_END event since the last clear by software
RH[2] : Receive Header End Flag
Signals that HEADER_RX_END event. Set by hardware, clear by software.
If enabled, a receive interrupt is triggered.
0 : No HEADER_RX_END event since the last clear by software
1 : New HEADER_RX_END event since the last clear by software
RR[3] : Receive Response End Flag
Signals that RESPONSE_RX_END event. Set by hardware, clear by
software.
If enabled, a receive interrupt is triggered.
0 : No RESPONSE_RX_END event since the last clear by software
1 : New RX_RESPONSE_END event since the last clear by software
FED[5] : Falling Edge from Level 1 to Level 0 Detected
This bit is set by hardware when a falling edge is detected on the RX line.
0 : No falling edge detected
1 : Falling edge detected
RED[6] : Rising Edge from Level 0 to Level 1 Detected
This bit is set by hardware when a rising edge is detected on the RX line.
0 : No rising edge detected
1 : Rising edge detected
TWRQ[13] : Transmit Wake Request Flag
Signals that transmission of wake has been requested. No interrupt triggered. As soon as the wake pulse transmission starts, the bit is cleared by the hardware.
0 : No Transmit Wake Request pending
1 : Transmit Wake Request pending.
THRQ[14] : Transmit Header Request Flag
Signals that transmission of header has been requested. No interrupt triggered. As soon as the header transmission starts, the bit is cleared by the hardware.
0 : No Transmit Header Request pending
1 : Transmit Header Request pending.
TRRQ[15] : Transmit Response Request Flag
Signals that transmission of response has been requested. No interrupt triggered. As soon as the response transmission starts, the bit is cleared by the hardware.
0 : No Transmit Response Request pending
1 : Transmit Response Request pending.
PE[16] : Parity Error Flag
Signals parity error. If enabled, an error interrupt is triggered.
Parity error occurs if the internally calculated parity bit is not equal to the received parity bit.
0 : Last message received error free
1 : Last message received with parity error
TC[17] : Transmission Completed Flag
Signals an end of an ASC or SPI frame. This bit is set after the last stop bit transmission in ASC mode, or after the trailing delay in case of SPI mode.
In LIN mode, if the node is transmitting a header this flag is set after each transmission break (incl lead) field, Sync field or PID field.
If the node is transmitting a response, this flag is set after each byte is transmitted. If enabled, an EX interrupt is triggered. Should be cleared by software.
0 : No end of frame event occurred
1 : End of frame event occurred
FE[18] : Framing Error Flag
Signals framing error. If enabled, an error interrupt is triggered. Framing error occurs if “0” is received at a stop bit position.
If autobaud detection is deactivated, then the sync field is checked for framing error.
0 : Last message received error free
1 : Last message received with error
HT[19] : Header Timeout Flag
Signals violation of the header duration limit. If enabled, an error interrupt is triggered.
0 : No HEADER_OVERFLOW event since the last clear by software
1 : New HEADER_OVERFLOW event since the last clear by software
RT[20] : Response Timeout Flag
Signals violation of the response or frame duration limit as defined in DATCON.RM bit.
If enabled, an error interrupt is triggered.
0 : No timeout event since the last clear by software
1 : New timeout event since the last clear by software
BD[21] : Break Detected Flag
Signals a detection of a break pulse. If enabled, an error interrupt is triggered. Slave mode only.
0 : No Break/Wake/Stuck event since the last clear by software
1 : New Break/Wake/Stuck event since the last clear by software
LP[22] : LIN Parity Error Flag
Signals parity error in the LIN identifier. If enabled, an error interrupt is triggered. Applies to LIN mode only.
LIN parity error occurs if the internally calculated parity bits are not equal to the received parity bits.
0 : Last ID received error free
1 : Last ID received with parity error
LA[23] : LIN Autobaud Detection Error Flag
Signals baudrate outside the range defined by BRD.LOWERLIMIT and BRD.UPPERLIMIT.
0 : No autobaud detection error
1 : Autobaud detection error
LC[24] : LIN Checksum Error Flag
Signals checksum error when receiving response, if the internally calculated checksum is different than the received checksum.
If enabled, an error interrupt is triggered.
0 : Last checksum error free
1 : Last checksum shows an error
CE[25] : Collision Detection Error Flag
When transmitting, signals if the transmitted data differs from the received data.
If enabled, an error interrupt is triggered in case of a
mismatch.
Collision detection is mandatory only when supporting LIN version 2.1.
0 : No mismatch
1 : Mismatch detected
RFO[26] : Receive FIFO Overflow Flag
Signals an overflow error. If enabled, an error interrupt is triggered.
0 : No overflow error occurred
1 : Overflow error occurred
RFU[27] : Receive FIFO Underflow Flag
Signals an underflow error. If enabled, an error interrupt is triggered. See also RxFIFO Overview.
0 : No underflow error occurred
1 : Underflow error occurred
RFL[28] : Receive FIFO Level Flag
This flag signals whenever a RXFIFO fill interrupt is generated based on RXFIFOCON.FM mode.
0 : No receive interrupt occurred
1 : Receive interrupt occurred
TFO[30] : Transmit FIFO Overflow Flag
Signals an overflow error. If enabled, an error interrupt is triggered.
0 : No overflow error occurred
1 : Overflow error occurred
TFL[31] : Transmit FIFO Level Flag
This flag signals whenever a TXFIFO refill interrupt (if enabled) is generated based on TXFIFOCON.FM mode.
0 : No transmit interrupt occurred
1 : Transmit interrupt occurred
보면, 특정 상황에서 Trigger 검출로 Interuupt를 걸거나,
Error를 잡기 위해 Parity를 활용하거나,
LIN 통신 전용이 있다. 필요에 따라 찾아서 사용하면 된다.
| 비트 | 이름 | 설명 | 상태 '1'의 의미 | 인터럽트 발생 여부 |
|---|---|---|---|---|
| 0 | TH | Transmit Header End | 헤더 전송 완료 | 전송 인터럽트 발생 가능 |
| 1 | TR | Transmit Response End | 응답 전송 완료 | 전송 인터럽트 발생 가능 |
| 2 | RH | Receive Header End | 헤더 수신 완료 | 수신 인터럽트 발생 가능 |
| 3 | RR | Receive Response End | 응답 수신 완료 | 수신 인터럽트 발생 가능 |
| 5 | FED | Falling Edge Detected | RX 라인에서 하강 에지 감지됨 | X |
| 6 | RED | Rising Edge Detected | RX 라인에서 상승 에지 감지됨 | X |
| 13 | TWRQ | Transmit Wake Request | 웨이크 전송 요청 중 | X (전송 시작 시 자동 클리어) |
| 14 | THRQ | Transmit Header Request | 헤더 전송 요청 중 | X (전송 시작 시 자동 클리어) |
| 15 | TRRQ | Transmit Response Request | 응답 전송 요청 중 | X (전송 시작 시 자동 클리어) |
| 16 | PE | Parity Error | 패리티 오류 발생 | 에러 인터럽트 발생 가능 |
| 17 | TC | Transmission Complete | 프레임 전송 완료 | EX 인터럽트 발생 가능 |
| 18 | FE | Framing Error | 정지 비트에서 오류 감지 | 에러 인터럽트 발생 가능 |
| 19 | HT | Header Timeout | 헤더 시간 초과 | 에러 인터럽트 발생 가능 |
| 20 | RT | Response Timeout | 응답 시간 초과 | 에러 인터럽트 발생 가능 |
| 21 | BD | Break Detected | Break 신호 감지 (Slave 전용) | 에러 인터럽트 발생 가능 |
| 22 | LP | LIN Parity Error | LIN ID의 패리티 오류 | 에러 인터럽트 발생 가능 |
| 23 | LA | LIN Autobaud Error | 자동 보레이트 실패 | 에러 인터럽트 발생 가능 |
| 24 | LC | LIN Checksum Error | 수신된 체크섬 오류 | 에러 인터럽트 발생 가능 |
| 25 | CE | Collision Error | 송신 데이터와 수신 데이터 불일치 | 에러 인터럽트 발생 가능 |
| 26 | RFO | RX FIFO Overflow | 수신 FIFO 오버플로우 | 에러 인터럽트 발생 가능 |
| 27 | RFU | RX FIFO Underflow | 수신 FIFO 언더플로우 | 에러 인터럽트 발생 가능 |
| 28 | RFL | RX FIFO Level | RX FIFO 채워짐 (설정 기준 도달) | 수신 인터럽트 발생 가능 |
| 30 | TFO | TX FIFO Overflow | 송신 FIFO 오버플로우 | 에러 인터럽트 발생 가능 |
| 31 | TFL | TX FIFO Level | TX FIFO 비워짐 (설정 기준 도달) | 송신 인터럽트 발생 가능 |
보면 RFL, TFL을 통해 FIFO 상태를 보도록 작성했다.
즉, HW에 의해 Interrupt가 걸려 FLAGS Bit field를 변경해주는데,
이를 Core에서 Polling 방식으로 checking하고 있는 것
실습
UART로 CLI에 Hello World 출력
#include "main.h"
void core0_main(void)
{
System_Init();
my_printf("Hello World\n");
while(1);
}
#include "main.h"
void core0_main(void)
{
System_Init();
GPIO_Init();
unsigned char c;
while(1){
c = Asclin0_InUart(); //get from putty
Asclin0_OutUart(c); //1개 다시 putty로 뿌림
if(c == '\r') {
Asclin0_OutUart('\n');
}
}
}
Blocking 방식 처리로, 기본적으로는 로직 없이는 입력해도 Putty에 뜨지 않는다.
#include "main.h"
void core0_main(void)
{
System_Init();
GPIO_Init();
unsigned char c;
while(1){
c= Asclin0_InUart();
if(c=='0'){
my_printf("Input : 0\n");
}
else if(c=='1'){
my_printf("Input : 1\n");
}
else{
my_printf("Other Input\n");
}
}
}
#include "main.h"
void core0_main(void)
{
System_Init();
unsigned char c;
while(1){
c= Asclin0_InUart();
if(c=='1'){
GPIO_SetLed(1,1);
}
else if(c=='0'){
GPIO_SetLed(1,0);
}
else{
my_printf("Other Input\n");
}
}
}
UART 통신을 이용한 GPIO(LED) 제어
#include "main.h"
void core0_main(void)
{
char c;
System_Init();
while(1){
c= Asclin0_InUartNonBlock();
if(c=='0'){
my_printf("Input : 0\n");
}
else if(c=='1'){
my_printf("Input : 1\n");
}
else{
my_printf("Other Input\n");
}
}
}
잘 보면 1이나 0이 올라가는게 보임
뭐 없으면 -1을 return하기에 계속 Other Input이 쭉 올라감
#include "main.h"
void core0_main(void)
{
char c;
System_Init();
while(1){
c= Asclin0_InUartNonBlock(); // 입력x -1 return하게됨
if(c=='0'){
my_printf("Input : 0\n");
}
else if(c=='1'){
my_printf("Input : 1\n");
}
else if(c>0){
my_printf("Other Input\n");
}
}
}
이건 c>0 처리를 통해 쭉 올라가지 않도록 확인 가능해짐.
#include "main.h"
void core0_main(void)
{
char c;
System_Init();
int on_off=0; // 1:on , 0 : off
while(1){
c= Asclin0_InUartNonBlock();
if(c=='1'){
GPIO_SetLed(1,1);
on_off=1;
}
else if(c=='0'){
GPIO_SetLed(1,0);
on_off=0;
}
if(on_off ==1){
my_printf("LED ON!\n");
}
else if(on_off ==0){
my_printf("LED OFF\n");
}
}
}
Baud Rate 921600으로 설정.
void Asclin0_InitUart(void){
/* set numerator and denominator for 115200 baudrate */
unsigned int numerator = 2304;
unsigned int denominator = 3125;
/* RXA/P14.1, TX/P14.0 */
/* Set TX/P14.0 to "output" and "high" */
MODULE_P14.IOCR0.B.PC0 = 0x12;
MODULE_P14.OUT.B.P0 = 1;
/* Enable ASCn */
IfxScuWdt_clearCpuEndinit(IfxScuWdt_getGlobalEndinitPassword());
MODULE_ASCLIN0.CLC.U = 0;
IfxScuWdt_setCpuEndinit(IfxScuWdt_getGlobalEndinitPassword());
/* read back for activating module */
(void)MODULE_ASCLIN0.CLC.U;
/* select RX as input pin */
MODULE_ASCLIN0.IOCR.B.ALTI = 0; // Select Alternate Input A
/* Program ASC0 */
MODULE_ASCLIN0.CSR.U = 0;
/* configure TX and RX FIFOs */
MODULE_ASCLIN0.TXFIFOCON.U = (1 << 6) /* INW: (1 == 1 byte) */
| (1 << 1) /* ENO */
| (1 << 0); /* FLUSH */
MODULE_ASCLIN0.RXFIFOCON.U = (1 << 31) /* BUF: (1 == Single Stage RX Buffer) */
| (1 << 6) /* OUTW: (1 == 1 byte) */
| (1 << 1) /* ENI */
| (1 << 0); /* FLUSH */
MODULE_ASCLIN0.BITCON.U = ( 4 << 0) /* PRESCALER: 10 */
| (15 << 16) /* OVERSAMPLING: 16 */
| ( 9 << 24) /* SAMPLEPOINT: position 7,8,9 */
| (1u << 31); /* SM: 3 samples per bit */
/* data format: 8N1 */
MODULE_ASCLIN0.FRAMECON.U = (1 << 9) /* STOP: 1 bit */
| (0 << 16) /* MODE: Init */
| (0 << 30); /* PEN: no parity */
MODULE_ASCLIN0.DATCON.U = (7 << 0); /* DATLEN: 8 bit */
/* set baudrate value */
MODULE_ASCLIN0.BRG.U = (denominator << 0) /* DENOMINATOR */
| (numerator << 16); /* NUMERATOR */
MODULE_ASCLIN0.FRAMECON.B.MODE = 1; /* ASC mode, 변경시 LIN가능 */
MODULE_ASCLIN0.CSR.U = 1; /* select CLC(소스) as clock source */
MODULE_ASCLIN0.FLAGSSET.U = (IFX_ASCLIN_FLAGSSET_TFLS_MSK << IFX_ASCLIN_FLAGSSET_TFLS_OFF);
}
부정방정식으로 값을 넣어 계산하면 된다
UART는 너무빠르면 오류가 나기때문에
적당한 속도가 중요하다.
그리고 블루투스 모듈도 ASCLIN1 MODULE에서 9600보율을 사용하기 때문에, 분모 분자 값을 맞춰서 설정해줘야 함.