Lập Trình Hệ Thống Nhúng: Bùi Quốc Bảo

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 37

LẬP TRÌNH HỆ THỐNG

NHÚNG

BÙI QUỐC BẢO


State Machine Programming

Sensor:
Output is 1 if water level is over
Output is 0 if water level is under

Sensor 1 = 0

STOP PUMP PUMP


____________ ___________
PumpCtrl = 0 PumpCtrl = 1

Sensor 2 = 1

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 2


State.h
typedef enum {S_STOPPUMP,S_PUMP} state_t;
typedef enum {WATERUNDER, WATEROVER} sensor_t;
void initState(void);
void statemMachineUpdate(void);
void SensorsInit(void);
sensor_t sensor1(void);
sensor_t sensor2(void);
void pumpCtrlInit(void);
void pumpCtrl(int state);

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 3


State.c
#include "state.h"

static state_t State;

void initState()

State = S_STOPPUMP;

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 4


State.c
void stateMachineUpdate(void)

{ switch (State)
switch (State) {
{ case S_STOPPUMP:
case S_STOPPUMP: pumpCtrl(PUMPOFF);
if (sensor1() == WATERUNDER)
break;
State = S_PUMP;
case S_PUMP:
break;
pumpCtrl(PUMPON);
case S_PUMP:
break;
if (sensor2() == WATEROVER)
}}
State = S_STOPPUMP;

break; }

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 5


main.c
#include "state.h"

int main(void)

{ sensorsInit();

pumpCtrlInit();

pumpCtrl(PUMPOFF);

initState();

while (1)
{
stateMachineUpdate();
}}

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 6


State machine Drawing

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 7


State machine drawing

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 8


Exercise

 Design state machine and write code for


TIVA lauchpad:
 After reset, all LEDs are off
 If SW1 is pressed, turn on LED Red.
 Led Red still on if SW1 is released. LED Red is off if SW1 is
pressed again, and still off if SW1 is released.
 This sequence repeats forever.

 Note: Open the example7_StateMachine project and modify the


source code (marked as TODO)

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 9


Software Timer
 Systick interrupt can be used to implement a software timer
 The timer resolution is the systick timer period. We often choose
1ms.
void SysTickIntHandler(void)

if (genTimerCount != 0)
{ genTimerCount--;
}}

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 10


Software Timer
void genStateMachineUpdate(void) case S_GRIDOFF_WAIT:

{ switch (genState) if (gridState() == GRIDON)


{ {

case S_GRIDON: genState = S_GRIDON;}

if (gridState() == GRIDOFF) else if(genTimerCount == 0)

{ {

genState= S_GRIDOFF_WAIT; genState = S_GRIDOFF;

genTimerCount = 20; } }

break; break;

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 11


 Design state machine and write code for
TIVA launchpad:
 After reset, all LEDs are off
 If SW2 is pressed in 3 second, turn on LED Green. LED Green
still on if SW2 is released. LED Green is off is SW2 is pressed
again in 6 second, and still off if SW2 is released after that. This
sequence repeats forever.

 Note: Open the example8_MultiStateMachine project and


modify the source code (marked as TODO)

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 12


Multi Tasking

 To have more than one task to work


concurrently, we just need to call them in
a super loop
while (1)
{

StatemMachine1Update();

StateMachine2Update();

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 13


Exercise

 Design state machine and write code for


TIVA lauchpad:
 After reset, all LEDs are off
 If SW1 is pressed, turn on LED Red. Led Red still on if SW1 is
released. LED Red is off if SW1 is pressed again, and still off if
SW1 is released. This sequence repeats forever.
 If SW2 is pressed in 3 second, turn on LED Green. LED Green
still on if SW2 is released. LED Green is off is SW2 is pressed
again in 6 second, and still off if SW2 is released after that. This
sequence repeats forever.
 Note: Open the example8_MultiStateMachine project and
modify the source code.

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 14


Shared variable (biến dùng chung)

Hoạt động của một hệ thống có thể được


chia thành nhiều tác vụ độc lập mặc dù
chúng có liên quan tới nhau.

VD:
Một hệ thống phát hiện chuyển động sử dụng 1 sensor kết nối vào
chân P1.0. Một chuyển động được phát hiện khi sensor bằng 1 trong
2 lần lâý mẫu liên tiếp cách nhau 200ms.
LED1 (nôí vào P1.1) được nhấp nháy sau với chu kỳ 200ms trong
thời gian phát hiện chuyển động.
LED2 (nôí vào P1.2) được bật khi phát hiện chuyển động và tắt 10s
sau khi chuyển động không còn bị phát hiện.

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 15


Shared variable (biến dùng chung)
!P1.0 !P1.0 P1.0

P1.0 P1.0
S0 S1 S2

mnt
mnt = 0 mnt = 1
!P1.0

!mnt mnt !mnt && (cnt < 50)

mnt !mnt
T0 T1 T2
cnt = 0
cnt++

!mnt && !(cnt < 50)

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 16


I/O and software synchronization

 Hardware has 3 basic state: idle, busy and


done

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 17


I/O and software synchronization

If the input device were faster than the software, a situation called CPU
bound, then the software waiting time would be zero

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 18


I/O and software synchronization

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 19


Interrupt
 An interrupt is the automatic transfer of software
execution in response to a hardware event that is
asynchronous with the current software execution
 When the hardware needs service, it will request an
interrupt by setting its trigger flag
 A thread is defined as the path of action of software
as it executes
 The execution of the interrupt service routine is called
a background thread

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 20


Interrupt synchronization
 ISR should execute as fast as possible
 Placing backward branches (busy-wait loops,
iterations) in the interrupt software should be avoided
if possible
 Busy-wait synchronization is appropriate when the I/O
timing is predicable, and when the I/O structure is
simple and fixed
 Interrupt synchronization is appropriate when the I/O
timing is variable, and when the I/O structure is
complex

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 21


Interrupt synchronization using semaphore

No wait on the ISR


A semaphore can be
used to synchronize
threads

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 22


Interrupt synchronization using mail box

Mailbox là phương pháp sử dụng 1


semaphore cùng với 1 biến để lưu giữ giá
trị cần thông tin

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 23


Interrupt synchronization using FIFO

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 24


Interrupt synchronization using FIFO

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 25


Sharing Data Safely between ISRs and other Threads

 Volatile data – can be updated outside of


the program’s immediate control

 Non-atomic shared data – can be


interrupted partway through read or
write, is vulnerable to race conditions.

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 26


Volatile Data
 Compilers assume that variables in memory do not change
spontaneously, and optimize based on that belief
 Don’t reload a variable from memory if current function hasn’t changed it
 Read variable from memory into register (faster access)
 Write back to memory at end of the procedure, or before a procedure call, or
when compiler runs out of free registers
 This optimization can fail
 Example: reading from input port, polling for key press
 while (SW_0) ; will read from SW_0 once and reuse that
value
 Will generate an infinite loop triggered by SW_0 being true
 Variables for which it fails
 Memory-mapped peripheral register – register changes on its own
 Global variables modified by an ISR – ISR changes the variable
 Global variables in a multithreaded application – another thread or ISR
changes the variable

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 27


The Volatile Directive
 Need to tell compiler which variables may change outside of its
control
 Use volatile keyword to force compiler to reload these vars from
memory for each use
volatile unsigned int num_ints;
 Pointer to a volatile int
volatile int * var; // or
int volatile * var;

 Now each C source read of a variable (e.g. status register) will result
in an assembly language LDR instruction

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 28


Non-Atomic Shared Data
void GetDateTime(DateTimeType * DT){
 Want to keep track of DT->day = TimerVal.day;
current time and date DT->hour = TimerVal.hour;
DT->minute = TimerVal.minute;
DT->second = TimerVal.second;
 Use 1 Hz interrupt from }
timer
void DateTimeISR(void){
TimerVal.second++;
if (TimerVal.second > 59){
 System TimerVal.second = 0;
 TimerVal structure tracks TimerVal.minute++;
time and days since some if (TimerVal.minute > 59) {
reference event TimerVal.minute = 0;
TimerVal.hour++;
 TimerVal’s fields are if (TimerVal.hour > 23) {
updated by periodic 1 Hz TimerVal.hour = 0;
timer ISR TimerVal.day++;
… etc.
}
BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 29
Non-Atomic Shared Data
 Problem
 An interrupt at the wrong time will lead to half-updated data in DT
 Failure Case
 TimerVal is {10, 23, 59, 59} (10th day, 23:59:59)
 Task code calls GetDateTime(), which starts copying the TimerVal fields to
DT: day = 10, hour = 23
 A timer interrupt occurs, which updates TimerVal to {11, 0, 0, 0}
 GetDateTime() resumes executing, copying the remaining TimerVal fields to
DT: minute = 0, second = 0
 DT now has a time stamp of {10, 23, 0, 0}.
 The system thinks time just jumped backwards one hour!
 Fundamental problem – “race condition”
 Preemption enables ISR to interrupt other code and possibly overwrite data
 Must ensure atomic (indivisible) access to the object
 Native atomic object size depends on processor’s instruction set and word size.
 Is 32 bits for ARM
BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 30
Non-Atomic Shared Data
 Must protect any data object which both
 (1) requires multiple instructions to read or write (non-atomic access),
and
 (2) is potentially written by an ISR

 How many tasks/ISRs can write to the data object?


 One? Then we have one-way communication
 Must ensure the data isn’t overwritten partway through being read

 Writer and reader don’t interrupt each other


 More than one?
 Must ensure the data isn’t overwritten partway through being read

 Writer and reader don’t interrupt each other


 Must ensure the data isn’t overwritten partway through being written
 Writers don’t interrupt each other

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 31


Definitions
 Race condition: Anomalous behavior due to unexpected
critical dependence on the relative timing of events.
Result of example code depends on the relative timing of
the read and write operations.

 Critical section: A section of code which creates a


possible race condition. The code section can only be
executed by one process at a time. Some synchronization
mechanism is required at the entry and exit of the critical
section to ensure exclusive use. (Exclusive Accesses
needed)

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 32


Solution: Briefly Disable Preemption
 Prevent preemption within
void GetDateTime(DateTimeType *
critical section
DT){
 If an ISR can write to the
uint32_t m;
shared data object, need to
disable interrupts
 Restore previous state
IntMasterDisable();
afterwards
DT->day = TimerVal.day;
DT->hour = TimerVal.hour;
 Avoid if possible
 Disabling interrupts delays response to all DT->minute = TimerVal.minute;
other processing requests DT->second = TimerVal.second;
 Make this time as short as possible (e.g. a
few instructions) IntMasterEnable();
}

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 33


Solution: Briefly Disable Preemption
 Can use CMIS core void GetDateTime(DateTimeType *
 If an ISR can write to the DT){
shared data object, need to uint32_t m;
disable interrupts
 save current interrupt
m = __get_PRIMASK();
masking state in m
 disable interrupts
__disable_irq();
 Restore previous state
afterwards (interrupts DT->day = TimerVal.day;
may have already been DT->hour = TimerVal.hour;
disabled for another reason) DT->minute = TimerVal.minute;
 Use CMSIS-CORE to save, DT->second = TimerVal.second;
control and restore interrupt __set_PRIMASK(m);
masking state }

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 34


Summary for Sharing Data
 In thread/ISR diagram, identify shared data
 Determine which shared data is too large to be handled atomically by
default
 This needs to be protected from preemption (e.g. disable interrupt(s), use an
RTOS synchronization mechanism)
 Declare (and initialize) shared variables as volatile in main file (or
globals.c)
 volatile int my_shared_var=0;
 Update extern.h to make these variables available to functions in other
files
 volatile extern int my_shared_var;
 #include “extern.h” in every file which uses these shared variables
 When using long (non-atomic) shared data, save, disable and restore
interrupt masking status
 CMSIS-CORE interface: __disable_irq(), __get_PRIMASK(),
__set_PRIMASK()
BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 35
CMSIS
 TIVA C families are based on ARM Cortex-M4
Core. There are also many other vendors who
use CM4 in their products.
 A standard hardware abstraction layer is
therefore needed.
 Cortex Microcontroller Software Interface
Standard(CMSIS) is a vendor-independent
HAL for Cortex-M processor series.

BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 36


BM Kỹ Thuật Điện Tử - ĐH Bách Khoa TP.HCM 37

You might also like