EE 319K Introduction to Embedded Systems Lecture 12: Serial Communication (UART), Lab 9, FIFO Queues Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-1 Agenda Recap ADC, fixed-point Assembly-C mix Lab 8 Agenda Communication Serial: UART, interrupts FIFO Queues used as buffers in communication Lab 9: Distributing Lab 8 o Transmitter uses ADC to read potentiometer o Receiver uses LCD to display position. o FIFO serves as buffer at receiver Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-2 Universal Asynchronous Receiver/Transmitter (UART) UART (Serial Port) Interface One frame Serial port Start b b b b b b b 7 Stop 0 2 3 4 1 5 b6 3.3V 0V Send/receive a frame of (5-8) data bits with a single (start) bit prefix and a 1 or 2 (stop) bit suffix Baud rate is total number of bits per unit time o Baudrate = 1 / bit-time Bandwidth is data per unit time o Bandwidth = (data-bits / frame-bits) * baudrate Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-3 TM4C123 LaunchPad I/O Pins IO PA2 PA3 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3 PD6 PD7 PE0 PE1 PE2 PE3 PE4 PE5 PF0 PF1 PF2 PF3 Ain Ain10 Ain11 C1C1+ C0+ C0Ain7 Ain6 Ain5 Ain4 Ain3 Ain2 Ain1 Ain0 Ain9 Ain8 0 Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port Port 1 2 SSI0Clk SSI0Fss SSI0Rx SSI0Tx 3 4 I2C1SCL I2C1SDA 5 6 I2C0SCL I2C0SDA U4Rx U4Tx U3Rx U3Tx SSI3Clk SSI3Fss SSI3Rx SSI3Tx U2Rx U2Tx U7Rx U7Tx M0PWM2 M0PWM3 M0PWM0 M0PWM1 M0PWM6 M0PWM7 IDX1 PhA1 PhB1 SSI1Clk I2C3SCL M0PWM6 M1PWM0 SSI1Fss I2C3SDA M0PWM7 M1PWM1 SSI1Rx M0Fault0 SSI1Tx IDX0 M0Fault0 PhA0 PhB0 U5Rx U5Tx U1RTS SSI1Rx U1CTS SSI1Tx SSI1Clk SSI1Fss 8 9 14 M1PWM2 M1PWM3 U1Rx U1Tx SSI2Clk SSI2Fss SSI2Rx SSI2Tx U1Rx U1Tx 7 I2C2SCL M0PWM4 M1PWM2 I2C2SDA M0PWM5 M1PWM3 CAN0Rx M1PWM4 PhA0 M1PWM5 PhB0 M0Fault0 M1PWM6 CAN0Tx M1PWM7 T2CCP0 T2CCP1 T3CCP0 T3CCP1 T1CCP0 T1CCP1 T0CCP0 T0CCP1 WT0CCP0 WT0CCP1 WT1CCP0 WT1CCP1 WT2CCP0 WT2CCP1 WT3CCP0 WT3CCP1 WT5CCP0 WT5CCP1 T0CCP0 T0CCP1 T1CCP0 T1CCP1 CAN0Rx CAN0Tx U1RTS U1CTS USB0epen USB0pflt USB0epen USB0pflt NMI CAN0Rx CAN0Tx NMI C0o C1o TRD1 TRD0 TRCLK 12-4 RS-232 Serial Port +3.3V 0.1F 16 0.1F TM4C123 0.1F PA1/U0Tx 0 PA0/U1Rx PB1/U1Tx PB0/U1Rx PD7/U2Tx PD6/U2Rx DB25 Pin 2 3 7 RS232 Name BA BB AB DB9 Pin 3 2 5 RxD MAX 3232 3 4 DB9 female 0.1F 1 2 +5.5V 6 -5.5V Vss 5 9 0.1F 5 4 8 9 Sin 8 3 TxD 10 7 Sout 7 2 6 15 EIA-574 Name 103 104 102 Signal TxD RxD SG 1 Description True DTE DCE Transmit Data Receive Data Signal Ground -5.5V -5.5V out in in out // this U1Tx PD3 not connected // this U1Rx PD2 tied to U1Tx PD3 of other microcontroller Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-5 Serial I/O Serial communication Transmit Data (TxD), Receive Data (RxD), and Signal Ground (SG) implement duplex communication link Both communicating devices must operate at the same bit rate Least significant bit sent first Full duplex Half duplex Simplex Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-6 UART - Transmitter Stop 7 6 5 4 3 2 1 0 Start Shift clock 1 Data U0Tx 0 Transmit shift register 16-element FIFO TXEF Fifo empty flag TXFF Fifo full flag Write data UART0_DR_R Transmit data register Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-7 UART - Transmitter Tx Operation Data written to UART0_DR_R o passes through 16-element FIFO o permits small amount of data rate matching between processor and UART Shift clock is generated from 16x clock o permits differences in Tx and Rx clocks to be reconciled One frame Serial port Start b b b b b b b 7 Stop 0 2 3 4 1 5 b6 Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 3.3V 0V 12-8 UART - Receiver Stop 7 6 5 4 3 2 1 0 Start Shift clock 1 Data OE BE PE FE 0 U0Rx Receive shift register 12-bit, 16-element FIFO Read data RXFE Fifo empty flag RXFF Fifo full flag UART0_DR_R Receive data register Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-9 UART - Receiver Rx Operation RXFE is 0 when data are available RXFF is 1 when FIFO is full FIFO entries have four control bits o BE set when Tx signal held low for more than one frame (break) o OE set when FIFO is full and new frame has arrived o PE set if frame parity error o FE set if stop bit timing error One frame Serial port Start b b b b b b b 7 Stop 0 2 3 4 1 5 b6 Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 3.3V 0V 12-10 UART – Overrun Error "A"=$41 "B"=$42 CDEFGHIJKLMNO s 0 1 2 3 4 5 6 7 s s 0 1 2 3 4 5 6 7 s "P"=$50 "Q"=$51 s 0 1 2 3 4 5 6 7 s s 0 1 2 3 4 5 6 7 s RXFE=0 OE=1 RXFF=1 17 frames transmitted and none read => overrun error Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-11 TM4C UART0 – Registers 31–12 $4000.C000 11 OE 10 BE 9 PE 31–3 $4000.C004 31–8 $4000.C018 7 TXFE 6 RXFF 5 TXFF 31–16 8 FE 7–0 DATA 3 OE 2 BE 4 RXFE 3 BUSY $4000.C030 $4000.C038 $4000.C03C $4000.C040 $4000.C044 UART0_FBRD_R 6–5 WPEN 4 FEN 3 STP2 2 EPS 1 PEN 0 BRK 9 RXE 8 TXE 7 LBE 6–3 2 SIRLP 1 SIREN 0 UARTEN 5-3 RXIFLSEL $4000.C034 31-11 UART0_FR_R 7 SPS 31–6 10 OEIM OERIS OEMIS OEIC 9 BEIM BERIS BEMIS BEIC 8 PEIM PERIS PEMIS PEIC 7 FEIM FERIS FEMIS FEIC UART0_RSR_R 2–0 5–0 DIVFRAC $4000.C028 31–10 0 FE UART0_IBRD_R 31–6 $4000.C02C 1 PE 15–0 DIVINT $4000.C024 31–8 Name UART0_DR_R 6 RTIM RTRIS RTMIS RTIC 2-0 TXIFLSEL 5 TXIM TXRIS TXMIS TXIC Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 4 RXIM RXRIS RXMIS RXIC UART0_LCRH_R UART0_CTL_R UART0_IFLS_R UART0_IM_R UART0_RIS_R UART0_MIS_R UART0_IC_R 12-12 TM4C UART Setup UART0 operation UART clock started in SYSCTL_RCGCUART_R Digital port clock started in SYSCTL_RCGCGPIO_R UART0_CTL_R contains UART enable (UARTEN), Tx (TXE), and Rx enable (RXE) o set each to 1 to enable o UART disabled during initialization UART0_IBRD_R and UART_FBRD_R specify baud rate o bit rate = (bus clock frequency)/(16*divider) o ex: want 19.2 kb/s and bus clock is 8 MHz o 8 MHz/(16*19.2 k) = 26.04167 = 11010.0000112 o Tx and Rx clo ck rates must be within 5% to avoid errors GPIO_PORTA_AFSEL_R to choose alternate function Write appropriate values to GPIO_PORTA_PCTL_R (See slide 4) GPIO_PORTA_DEN_R Enable digital I/O on pins 1-0 GPIO_PORTA_AMSEL_R no Analog I/O on pins 1-0 write to UART0_LCRH_R to activate Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-13 UART Setup // Assumes a 50 MHz bus clock, creates 115200 baud rate void UART_Init(void){ SYSCTL_RCGCUART_R |= 0x0001; // activate UART0 SYSCTL_RCGCGPIO_R |= 0x0001; // activate port A UART0_CTL_R &= ~0x0001; // disable UART UART0_IBRD_R = 27; // IBRD=int(50000000/(16*115,200)) = int(27.1267) UART0_FBRD_R = 8; // FBRD = round(0.1267 * 64) = 8 UART0_LCRH_R = 0x0070; // 8-bit length, enable FIFO UART0_CTL_R = 0x0301; // enable RXE, TXE and UART GPIO_PORTA_AFSEL_R |= 0x03; // alt funct on PA1-0 GPIO_PORTA_PCTL_R = (GPIO_PORTA_PCTL_R&0xFFFFFF00)+0x00000011; GPIO_PORTA_DEN_R |= 0x03; // digital I/O on PA1-0 GPIO_PORTA_AMSEL_R &= ~0x03; // No analog on PA1-0 } Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-14 UART Synchronization Busy-wait operation InChar Empty 1 RXFE 0 OutChar Full 1 Not empty TXFF 0 Not full Read data Write data return return Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-15 UART Busy-Wait Send/Recv // Wait for new input, // then return ASCII code uint8_t UART_InChar(void) { while((UART0_FR_R&0x0010) != 0); // wait until RXFE is 0 return((uint8_t)(UART0_DR_R&0xFF)); } // Wait for buffer to be not full, // then output void UART_OutChar(uint8_t data) { while((UART0_FR_R&0x0020) != 0); // wait until TXFF is 0 UART0_DR_R = data; } Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-16 UART Interrupts UART0_IFLS_R register (bits 5,4,3) RXIFLSEL 0x0 0x1 0x2 0x3 0x4 RX FIFO ≥ ⅛ full ≥ ¼ full ≥ ½ full ≥ ¾ full ≥ ⅞ full Set RXRIS interrupt trigger when Receive FIFO goes from 1 to 2 characters Receive FIFO goes from 3 to 4 characters Receive FIFO goes from 7 to 8 characters Receive FIFO goes from 11 to 12 characters Receive FIFO goes from 13 to 14 characters TXIFLSEL 0x0 0x1 0x2 0x3 0x4 TX FIFO ≤ ⅞ empty ≤ ¾ empty ≤ ½ empty ≤ ¼ empty ≤ ⅛ empty Set TXRIS interrupt trigger when Transmit FIFO goes from 15 to 14 characters Transmit FIFO goes from 13 to 12 characters Transmit FIFO goes from 9 to 8 characters Transmit FIFO goes from 5 to 4 characters Transmit FIFO goes from 3 to 2 characters Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-17 Lab 9 – Distributed Measurement Position Voltage 0 to 3 cm 0 to +3.3V Position Sensor ADC hardware STX d1 . ADC driver Sample 0 to 4095 d2 d3 d4 CR ETX Message SysTick ISR Message UART driver SysTick hardware Computer 1 Fixed-point 0 to 3.000 Computer 2 LCD display Message Sample 0 to 4095 LCD driver main UART1 hardware Message Message Message FIFO Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi Message UART1 ISR UART1 hardware 12-18 Lab9: Transmitter SysTick ISR Toggle heartbeat Busy-wait version Sample ADC Toggle heartbeat Convert to integer part of fixed point Send message, 8 calls to UART_OutChar STX Ones digit Decimal point Tenths digit Hundreds digit Thousandth digit CR ETX Busy-wait version Interrupt Perform I/O return from interrupt Toggle heartbeat Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-19 Lab9: UART Rx Interrupt Interrupt Trigger, sets RXRIS Receive FIFO has gone from 7 to 8 elements (1/2 full) Initialization (add these) Arm RXRIS UART1_IM_R |= 0x10; Set UART1_IFLS_R bits 5,4,3 to 010 (1/2 full) NVIC_PRI1_R // bits 21-23 NVIC_EN0_R // enable interrupt 6 in NVIC Interrupt vector in startup.s Name ISR UART1_Handler Acknowledge (in ISR) UART1_ICR_R = 0x10; Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-20 Lab9: Interrupt+Mailbox? Background thread Foreground thread RXRIS ISR Main loop Read UART1_DR_R Store in RXmail Set RXstatus Main program ISR Read data from input Other calculations a Empty c Status Wait for RXstatus Read RXmail Clear RXstatus Convert to distance Display on LCD Mail = data b Status = Full Full Process Mail Status = Empty d What can go wrong? Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-21 First-In/First-Out (FIFO) Queues Fifo_Put Source process Producer Fifo_Get FIFO Sink process Consumer Order preserving Producer(s) put (on tail end) Consumer(s) get (from head end) Buffer decouples producer & consumer Even out temporary mismatch in rates Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-22 FIFO Operation I/O bound input interface Input device busy Interrupt service routine Main program Elements in FIFO done busy done b a empty b c 1 d a c d empty 1 empty Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi a 12-23 FIFO Operation High bandwidth input burst Input device busy done busy done busy done busy done busy done Interrupt service routine Main program b b a Elements empty in FIFO c 1 b b b d empty 1 c 2 Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi busy 3 d 2 3 12-24 FIFO Queue Synchronization Input ISR Input Read data from input Empty RxFifo Not empty Output ISR RxFifo RxFifo_Get ERROR Empty TxFifo_Get Full RxFifo_Put return Output Full Not full TxFifo Not empty TxFifo Not full TxFifo_Put Write data to output Disarm output Arm output return Lab 9 Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-25 Lab 9 - RXRIS ISR 1. 2. 3. 4. 5. 6. 7. toggle PF2 (change from 0 to 1, or from 1 to 0), heartbeat toggle PF2 (change from 0 to 1, or from 1 to 0), heartbeat as long as the RXFE bit in the UART1_FR_R is zero o Read bytes from UART1_DR_R o Put all bytes into your software FIFO, RxFifo_Put o Should be exactly 8 bytes, but could be more possibly o If your software FIFO is full (data lost) increment a global error count (but don’t loop back) o The message will be interpreted in the main program Increment a Counter, o debugging monitor of the number of UART messages received acknowledge the interrupt by clearing the flag which requested it o UART1_ICR_R = 0x10; // clears bit 4 (RXRIS) in RIS register toggle PF2 (change from 0 to 1, or from 1 to 0), heartbeat return from interrupt Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-26 FIFO Queue Implementation How is memory allocated? FIFO implies that we write new data at the head of the queue and we read data from the tail of the queue What problem does this cause? To address that problem the queue is operated in a circular manner An array of locations is processed so that the FIRST element of array appears to follow the LAST element of the array Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-27 FIFO Queue Implementation Two parameters are needed to specify the FIFO buffer (array) FIRST (usually index 0) o points to the first location of the buffer LIMIT (usually index SIZE) o points to last location+1 of the buffer o since LIMIT is outside the buffer, data must not be written there FIRST and LIMIT are constants o they are NOT modified by either the source or sink processing routines Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-28 FIFO Queue Implementation RxFifo GetPt PutPt Valid data PutPt: Points to the location where the next element to be added goes GetPt: Points to the location of the oldest valid element, hence the element to be removed first Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-29 FIFO Full/Empty Conditions FIFO Parameter Relations Buffer is EMPTY o PutPt equals GetPt Buffer is FULL o PutPt + 1 equals GetPt note that there is no data stored at PutPt as a result, if N locations are allocated for a buffer, only N-1 data elements will fill the buffer Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-30 FIFO Wrapping Put Put Put Put PPt FIRST newest PPt newest PPt Pointer wrap on 2nd put GPt GPt PPt GPt oldest oldest GPt oldest GPt oldest newest PPt newest LIMIT Get Get Get Get GPt newest PPt newest PPt newest PPt oldest newest PPt FIRST GPt PPt Pointer wrap on 4th get GPt oldest GPt oldest GPt oldest LIMIT Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-31 FIFO Queue FIFO Implementations FIFO_Put o stores a single value on the FIFO queue operates with interrupts disabled updates PutPt detects buffer full condition handles transition from LIMIT-1 to FIRST FIFO_Get o reads a single value from the FIFO queue operates with interrupts disabled updates GetPt detects buffer empty condition handles transition from LIMIT-1 to FIRST Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-32 FIFO in C #define int32_t int32_t int32_t FIFO_SIZE 10 static means static *PutPt; private to this file static *GetPt; static Fifo[FIFO_SIZE]; void Fifo_Init(void){ PutPt = GetPt = &Fifo[0]; } Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-33 FIFO Routines in C int Fifo_Put(int32_t data) Actually plus 4 bytes { int32_t *tempPt; tempPt = PutPt+1; // see if there is room if(tempPt==&Fifo[FIFO_SIZE]){ tempPt = &Fifo[0]; } if(tempPt == GetPt){ return(0); // full! } else{ *(PutPt) = data; // save PutPt = tempPt; // OK return(1); } } Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-34 FIFO Routines in C int Fifo_Get(int32_t *datapt){ if(PutPt == GetPt){ return(0); // Empty } Actually plus 4 bytes else{ *datapt = *(GetPt++); if(GetPt==&Fifo[FIFO_SIZE]){ GetPt = &Fifo[0]; } return(1); } } Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-35 FIFO Queue – Index Implementation FIFO Implementations FIFO_Put o stores a single value on the FIFO queue operates with interrupts disabled updates PutI detects buffer full condition handles transition from LIMIT-1 to FIRST FIFO_Get o reads a single value from the FIFO queue operates with interrupts disabled updates GetI detects buffer empty condition handles transition from LIMIT-1 to FIRST Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-36 FIFO in C – Index Implementation static means private to this file #define FIFO_SIZE 10 int32_t static PutI; //Index in FIFO to // put new item in int32_t static GetI; //Index of oldest // item in FIFO int32_t static Fifo[FIFO_SIZE]; void Fifo_Init(void){ PutI = GetI = 0; } Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-37 FIFO in C – Index Implementation int Fifo_Put(int32_t data) { if ( (PutI+1)% FIFO_SIZE) == GetI) { return(0); } Full FIFO check FIFO[PutI] = data; PutI = (PutI+1)%FIFO_SIZE; return(1); } int Fifo_Get(int32_t *datapt) Empty FIFO check { if (GetI == PutI) { return(0); } *datapt = FIFO[GetI]; GetI = (GetI+1)%FIFO_SIZE; return(1); } Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-38 FIFO Full Errors Average producer rate exceeds Producer rate temporarily the average consumer rate exceeds the consumer rate Sample ADC every 50 ms Sample ADC every 50 Average time to process the ms sample is 51 ms Every 100th sample it Solution: decrease producer takes 1 sec to process rate or increase consumer Solution: increase FIFO rate queue size o Lower sampling rate o o o o Faster computer More efficient compiler Rewrite time-critical code in assembly More computers (distributed processing) Bill Bard, Andreas Gerstlauer, Jon Valvano, Ramesh Yerraballi 12-39