1 of 35

EE 319K�Introduction to Embedded Systems

Lecture 12b: �Serial Communication (UART), �Lab 9, FIFO Queues

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

12-1

2 of 35

Agenda

  • Recap
    • Communication
    • Serial UART busy-wait
  • Agenda
    • Serial: UART, interrupts
    • FIFO Queues used as buffers in communication
    • Lab 9: Distributing Lab 8
      • Transmitter uses ADC to read potentiometer
      • Receiver uses LCD to display position.
      • FIFO serves as buffer at receiver

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

12-2

3 of 35

EE319H Distributed Measurement

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

wireless

Why layered?

12-3

4 of 35

Lab 9 – Distributed Measurement

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

P

o

s

i

t

i

o

n

S

e

n

s

o

r

V

o

l

t

a

g

e

0

t

o

+

3.3V

A

D

C

h

a

r

d

w

a

r

e

A

D

C

d

r

i

v

e

r

S

a

m

p

l

e

0

t

o

4

0

9

5

S

y

s

T

i

c

k

I

S

R

S

a

m

p

l

e

0

t

o

4

0

9

5

S

y

s

T

i

c

k

h

a

r

d

w

a

r

e

L

C

D

d

i

s

p

l

a

y

L

C

D

d

r

i

v

e

r

F

i

x

e

d

-

p

o

i

n

t

0

t

o

3

.

0

0

0

P

o

s

i

t

i

o

n

0

t

o

3

c

m

U

A

R

T

d

r

i

v

e

r

U

A

R

T

1

h

a

r

d

w

a

r

e

m

a

i

n

U

A

R

T

1

I

S

R

U

A

R

T

1

h

a

r

d

w

a

r

e

C

o

m

p

u

t

e

r

1

C

o

m

p

u

t

e

r

2

M

e

s

s

a

g

e

M

e

s

s

a

g

e

F

I

F

O

M

e

s

s

a

g

e

M

e

s

s

a

g

e

M

e

s

s

a

g

e

M

e

s

s

a

g

e

S

T

X

d

1

.

d

2

d

3

d

4

C

R

E

T

X

M

e

s

s

a

g

e

<,d1,dot,d2,d3,d4,CR,>

0 to 2.00cm

0 to 2 cm

Spring 2022: Two different computers

12-4

5 of 35

Lab 9 Profile

Time to ADC_In with SAC=6?

Time to send message?

Transmitter 10 Hz ISR:

  • Toggle PF2
  • Measure ADC
  • Convert
  • Create message
  • Call OutChar 8 times

<

>

d3

<,d1,dot,d2,d3,d4,CR,>

12-5

6 of 35

UART Interrupts

  • UARTx_IFLS_R register (bits 5,4,3)

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

RXIFLSEL RX FIFO Set RXRIS interrupt trigger when

0x0 ≥ ⅛ full Receive FIFO goes from 1 to 2 characters

0x1 ≥ ¼ full Receive FIFO goes from 3 to 4 characters

0x2 ≥ ½ full Receive FIFO goes from 7 to 8 characters

0x3 ≥ ¾ full Receive FIFO goes from 11 to 12 characters

0x4 ≥ ⅞ full Receive FIFO goes from 13 to 14 characters

TXIFLSEL TX FIFO Set TXRIS interrupt trigger when

0x0 ≤ ⅞ empty Transmit FIFO goes from 15 to 14 characters

0x1 ≤ ¾ empty Transmit FIFO goes from 13 to 12 characters

0x2 ≤ ½ empty Transmit FIFO goes from 9 to 8 characters

0x3 ≤ ¼ empty Transmit FIFO goes from 5 to 4 characters

0x4 ≤ ⅛ empty Transmit FIFO goes from 3 to 2 characters

12-6

7 of 35

Lab9: Transmitter SysTick ISR

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

  • Toggle a heartbeat
  • Sample ADC
  • Convert to integer part of fixed point
  • Send message, 8 calls to UART_OutChar
    • <
    • Ones digit
    • Decimal point
    • Tenths digit
    • Hundredths digit
    • Thousandth digit
    • CR
    • >

Busy-wait version

Busy-wait version

<,d1,dot,d2,d3,d4,CR,>

12-7

8 of 35

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;

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

C++ add extern "C" void UART1_Handler(void);

12-8

9 of 35

Lab9: Interrupt+Mailbox?

  • RXRIS ISR
    • Read UART1_DR_R
    • Store in RXmail
    • Set RXstatus

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

  • Main loop
    • Wait for RXstatus
    • Read RXmail
    • Clear RXstatus
    • Convert to distance
    • Display on LCD

Background thread

Foreground thread

What can go wrong?

12-9

10 of 35

First-In/First-Out (FIFO) Queues

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

  • Order preserving
  • Producer(s) put (on tail end)
  • Consumer(s) get (from head end)
  • Buffer decouples producer & consumer
    • Even out temporary mismatch in rates

12-10

11 of 35

FIFO Operation

  • I/O bound input interface

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

12-11

12 of 35

FIFO Operation

  • High bandwidth input burst

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

12-12

13 of 35

FIFO Queue Synchronization

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

Lab 9

12-13

14 of 35

Lab 9 - RXRIS ISR

  1. toggle PF1 (change from 0 to 1, or from 1 to 0), heartbeat
  2. as long as the RXFE bit in the UART1_FR_R is zero
    • Read bytes from UART1_DR_R
    • Put all bytes into your software FIFO, RxFifo_Put
    • Should be exactly 8 bytes, but could be more possibly
    • If your software FIFO is full (data lost)

increment a global error count (but don’t loop back)

    • The message will be interpreted in the main program
  • Increment a Counter, debugging monitor of messages received
  • acknowledge the interrupt by clearing the flag which requested it
    • UART1_ICR_R = 0x10; // clears bit 4 (RXRIS) in RIS register
  • return from interrupt

12-14

15 of 35

FIFO Queue Design

  • 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

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

12-15

16 of 35

Index vs pointers

  • EE319K Fifo uses indices
  • EE319H Fifo is a C++ class
  • EE319H FIFO uses pointers

Bard, Erez, Gerstlauer, Holt, Telang, Tiwari, Valvano, Yerraballi

12-16

17 of 35

FIFO Queue Implementation

  • Three parameters are needed
    • Where is the oldest data (next data to Get)?
      • Index (EE319K) or pointer (EE319H)
    • Where is an empty spot (next place to Put)?
      • Index (EE319K) or pointer (EE319H)
    • Maximum size
      • EE319K fixed at compile time (SIZE=16 can store 15)
      • EE319H size could be adjusted dynamically (isn’t)

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

12-17

18 of 35

FIFO Index Implementation

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

  • PutI: Index to an empty location where the next element to be added goes
  • GetI: Index to the location of the oldest valid element, hence the element to be removed first

GetI

PutI

12-18

19 of 35

FIFO Index Full/Empty Conditions

  • FIFO Parameter Relations
    • Buffer is EMPTY
      • PutI equals GetI
    • Buffer is FULL
      • (PutI +1)%SIZE equals GetI
        • note that there is no data stored at PutI
        • as a result, if N locations are allocated for a buffer, only N-1 data elements will fill the buffer

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

What if SIZE is a power of 2?

12-19

20 of 35

FIFO Index Wrapping

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

Pointer wrap

on 2nd put

Pointer wrap

on 4th get

FIRST

LIMIT

FIRST

LIMIT

GetI

GetI

GetI

GetI

GetI

GetI

GetI

GetI

GetI

GetI

PutI

PutI

PutI

PutI

PutI

PutI

PutI

PutI

PutI

PutI

12-20

21 of 35

FIFO Index Functions

    • FIFO_Put
      • stores a single value on the FIFO queue
        • Called from ISR
        • updates PutI
          • detects buffer full condition
        • handles wrapping of PutI
    • FIFO_Get
      • reads a single value from the FIFO queue
        • Called from the main
        • updates GetI
          • detects buffer empty condition
        • handles wrapping of GetI

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

12-21

22 of 35

FIFO in C – Index Implementation

#define FIFO_SIZE 10

int32_t static PutI; // Index to put new

int32_t static GetI; // Index of oldest

int32_t static Fifo[FIFO_SIZE];

void Fifo_Init(void){

PutI = GetI = 0;

}

Bard, Erez, Gerstlauer, Holt, Telang, Tiwari, Valvano, Yerraballi

static means private to this file

EMPTY: PutI equals GetI

FULL: (PutI +1)%SIZE equals GetI

12-22

23 of 35

FIFO in C – Index Implementation

int Fifo_Put(int32_t data)

{

if ( ((PutI+1)%FIFO_SIZE) == GetI) {

return(0);

}

FIFO[PutI] = data;

PutI = (PutI+1)%FIFO_SIZE;

return(1);

}

int Fifo_Get(int32_t *datapt)

{

if (GetI == PutI) {

return(0);

}

*datapt = FIFO[GetI];

GetI = (GetI+1)%FIFO_SIZE;

return(1);

}

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

Empty FIFO check

Full FIFO check

12-23

24 of 35

FIFO Queuing Theory

Average producer rate exceeds the average consumer rate

  • Sample ADC every 50 ms
  • Average time to process the sample is 51 ms
  • Solution: decrease producer rate or increase consumer rate
      • Lower sampling rate
      • Faster computer
      • More efficient compiler
      • Rewrite time-critical code in assembly
      • More computers (distributed processing)

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

Producer rate temporarily exceeds the consumer rate

  • Sample ADC every 50 ms
  • Every 100th sample it takes 1 sec to process
  • Solution: increase FIFO queue size

On average the arrival rate must be slower than the service rate

12-24

25 of 35

FIFO Queue EE319H

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

  • 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

12-25

26 of 35

FIFO Full/Empty EE319H

  • FIFO Parameter Relations
    • Buffer is EMPTY
      • PutPt equals GetPt
    • Buffer is FULL
      • 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

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

12-26

27 of 35

FIFO Wrapping EE319H

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

Pointer wrap

on 2nd put

Pointer wrap

on 4th get

FIRST

LIMIT

FIRST

LIMIT

12-27

28 of 35

FIFO Queue EE319H

  • FIFO Implementations
    • FIFO_Put
      • stores a single value on the FIFO queue
        • Called from ISR
        • updates PutPt
          • detects buffer full condition
        • handles wrapping of PutPt
    • FIFO_Get
      • reads a single value from the FIFO queue
        • Called from main
        • updates GetPt
          • detects buffer empty condition
        • handles wrapping of GetPt

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

12-28

29 of 35

FIFO EE319H

#define FIFO_SIZE 10

private:

char *PutPt;

char *GetPt;

char Fifo[FIFO_SIZE];

public:

bool Put(char x);

bool Get(char *pt);

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

private to this class

Public to user

12-29

30 of 35

FIFO Routines EE319H

int Fifo_Put(int32_t data)

{

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);

}

}

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

Change

this C into C++

integer to char

12-30

31 of 35

FIFO Routines EE319H

int Fifo_Get(int32_t *datapt){

if(PutPt == GetPt){

return(0); // Empty

}

else{

*datapt = *(GetPt++);

if(GetPt==&Fifo[FIFO_SIZE]){

GetPt = &Fifo[0];

}

return(1);

}

}

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

Change

this C into C++

integer to char

12-31

32 of 35

Deque

How to make a FIFO queue using the EE312H linked lists?

class Node {

public: string val;

Node *next;

~Node() { delete next; }

};

class List {

Node *head;

int si;

void List::add(string el) {

Node *n = new Node();

n->val = el;

n->next = nullptr;

if (head != nullptr) {

n->next = head; }

head = n; si++;

}

12-32

33 of 35

TM4C123 ADC Fifos

  • ADC hardware FIFO
  • UART1 Tx hardware FIFO
  • UART1 Rx hardware FIFO
  • Receiver software FIFO

12-33

34 of 35

FIFO Macro EE319H

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

// macro to create a pointer FIFO

#define AddPointerFifo(NAME,SIZE,TYPE,SUCCESS,FAIL) \

TYPE volatile *NAME ## PutPt; \

TYPE volatile *NAME ## GetPt; \

TYPE static NAME ## Fifo [SIZE]; \

void NAME ## Fifo_Init(void){ \

NAME ## PutPt = NAME ## GetPt = &NAME ## Fifo[0]; \

} \

int NAME ## Fifo_Put (TYPE data){ \

TYPE volatile *nextPutPt; \

nextPutPt = NAME ## PutPt + 1; \

if(nextPutPt == &NAME ## Fifo[SIZE]){ \

nextPutPt = &NAME ## Fifo[0]; \

} \

if(nextPutPt == NAME ## GetPt ){ \

return(FAIL); \

} \

else{ \

*( NAME ## PutPt ) = data; \

NAME ## PutPt = nextPutPt; \

return(SUCCESS); \

} \

} \

int NAME ## Fifo_Get (TYPE *datapt){ \

if( NAME ## PutPt == NAME ## GetPt ){ \

return(FAIL); \

} \

*datapt = *( NAME ## GetPt ## ++); \

if( NAME ## GetPt == &NAME ## Fifo[SIZE]){ \

NAME ## GetPt = &NAME ## Fifo[0]; \

} \

return(SUCCESS); \

}

Implementing an object in C!

Which does this have?

  • Encapsulation
  • Polymorphism
  • Inheritance

AddPointerFifo(Rx, 20, uint8_t, 1, 0)

12-34

35 of 35

Little’s Theorem EE319H

Bard, Erez, Cuevas, Holt, Gerstlauer, Telang, Tiwari, Valvano, Yerraballi

  • N average number of data packets in the queue
          • plus the one packet currently being processed.
        • N is the average number of packets in the system.
  • λ average arrival rate in packets per second (pps).
  • R average response time of a packet,
  • time waiting in the queue
  • plus the time for the consumer to process the packet.

Little’s Theorem states

N = λR

12-35