rtos labs

This commit is contained in:
Ondrej Hladuvka 2025-05-21 21:17:55 +03:00
commit b275f4d83e
25 changed files with 5943 additions and 0 deletions

544
Lab1_4C123/Lab1.c Normal file
View File

@ -0,0 +1,544 @@
// Lab1.c
// Runs on either MSP432 or TM4C123
// Start project to Lab 1. Take sensor readings, process the data,
// and output the results. Specifically, this program will
// measure steps using the accelerometer, audio noise using
// microphone, and light intensity using the light sensor.
// Daniel and Jonathan Valvano
// February 3, 2016
/* This example accompanies the books
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Introduction to the MSP432 Microcontroller",
ISBN: 978-1512185676, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Interfacing to the MSP432 Microcontroller",
ISBN: 978-1514676585, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
// J1 J3 J4 J2
// [ 1] [21] [40] [20]
// [ 2] [22] [39] [19]
// [ 3] [23] [38] [18]
// [ 4] [24] [37] [17]
// [ 5] [25] [36] [16]
// [ 6] [26] [35] [15]
// [ 7] [27] [34] [14]
// [ 8] [28] [33] [13]
// [ 9] [29] [32] [12]
// [10] [30] [31] [11]
// +3.3V connected to J1.1 (power)
// joystick horizontal (X) connected to J1.2 (analog)
// UART from BoosterPack to LaunchPad connected to J1.3 (UART)
// UART from LaunchPad to BoosterPack connected to J1.4 (UART)
// joystick Select button connected to J1.5 (digital)
// microphone connected to J1.6 (analog)
// LCD SPI clock connected to J1.7 (SPI)
// ambient light (OPT3001) interrupt connected to J1.8 (digital)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SCL connected to J1.9 (I2C)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SDA connected to J1.10 (I2C)
// temperature sensor (TMP006) interrupt connected to J2.11 (digital)
// nothing connected to J2.12 (SPI CS_Other)
// LCD SPI CS connected to J2.13 (SPI)
// nothing connected to J2.14 (SPI MISO)
// LCD SPI data connected to J2.15 (SPI)
// nothing connected to J2.16 (reset)
// LCD !RST connected to J2.17 (digital)
// nothing connected to J2.18 (SPI CS_Wireless)
// servo PWM connected to J2.19 (PWM)
// GND connected to J2.20 (ground)
// +5V connected to J3.21 (power)
// GND connected to J3.22 (ground)
// accelerometer X connected to J3.23 (analog)
// accelerometer Y connected to J3.24 (analog)
// accelerometer Z connected to J3.25 (analog)
// joystick vertical (Y) connected to J3.26 (analog)
// nothing connected to J3.27 (I2S WS)
// nothing connected to J3.28 (I2S SCLK)
// nothing connected to J3.29 (I2S SDout)
// nothing connected to J3.30 (I2S SDin)
// LCD RS connected to J4.31 (digital)
// user Button2 (bottom) connected to J4.32 (digital)
// user Button1 (top) connected to J4.33 (digital)
// gator hole switch connected to J4.34 (digital)
// nothing connected to J4.35
// nothing connected to J4.36
// RGB LED blue connected to J4.37 (PWM)
// RGB LED green connected to J4.38 (PWM)
// RGB LED red (jumper up) or LCD backlight (jumper down) connected to J4.39 (PWM)
// buzzer connected to J4.40 (PWM)
#include <stdint.h>
#include "BSP.h"
#include "Profile.h"
#include "Texas.h"
#include "CortexM.h"
uint32_t sqrt32(uint32_t s);
//---------------- Global variables shared between tasks ----------------
uint32_t Time; // elasped time in seconds
uint32_t Steps; // number of steps counted
uint32_t Magnitude; // will not overflow (3*1,023^2 = 3,139,587)
// Exponentially Weighted Moving Average
uint32_t EWMA; // https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
uint16_t SoundData; // raw data sampled from the microphone
uint32_t SoundRMS; // Root Mean Square average of most recent sound samples
uint32_t LightData;
int ReDrawAxes = 0; // non-zero means redraw axes on next display task
enum plotstate{
Accelerometer,
Microphone,
Light
};
enum plotstate PlotState = Accelerometer;
//color constants
#define BGCOLOR LCD_BLACK
#define AXISCOLOR LCD_ORANGE
#define MAGCOLOR LCD_YELLOW
#define EWMACOLOR LCD_CYAN
#define SOUNDCOLOR LCD_CYAN
#define LIGHTCOLOR LCD_LIGHTGREEN
#define TOPTXTCOLOR LCD_WHITE
#define TOPNUMCOLOR LCD_ORANGE
//------------ end of Global variables shared between tasks -------------
//---------------- Task0 samples sound from microphone ----------------
//#define SOUNDRMSLENGTH 10 // number of samples to collect before calculating RMS (may overflow if greater than 4104)
#define SOUNDRMSLENGTH 1000 // number of samples to collect before calculating RMS (may overflow if greater than 4104)
int16_t SoundArray[SOUNDRMSLENGTH];
// *********Task0_Init*********
// initializes microphone
// Task0 measures sound intensity
// Inputs: none
// Outputs: none
void Task0_Init(void){
BSP_Microphone_Init();
SoundRMS = 0;
}
// *********Task0*********
// collects data from microphone
// Inputs: none
// Outputs: none
void Task0(void){
static int32_t soundSum = 0;
static int time = 0;// units of microphone sampling rate
int32_t soundAvg;
int i;
TExaS_Task0(); // record system time in array, toggle virtual logic analyzer
Profile_Toggle0(); // viewed by the logic analyzer to know Task0 started
BSP_Microphone_Input(&SoundData);
soundSum = soundSum + (int32_t)SoundData;
SoundArray[time] = SoundData;
time = time + 1;
if(time == SOUNDRMSLENGTH){
time = 0;
soundAvg = soundSum/SOUNDRMSLENGTH;
soundSum = 0;
for(i=0; i<SOUNDRMSLENGTH; i=i+1){
soundSum = soundSum + (SoundArray[i] - soundAvg)*(SoundArray[i] - soundAvg);
}
SoundRMS = sqrt32(soundSum/SOUNDRMSLENGTH);
soundSum = 0;
}
}
/* ****************************************** */
/* End of Task0 Section */
/* ****************************************** */
//---------------- Task1 measures acceleration ----------------
uint16_t AccX, AccY, AccZ; // returned by BSP as 10-bit numbers
#define ALPHA 128 // The degree of weighting decrease, a constant smoothing factor between 0 and 1,023. A higher ALPHA discounts older observations faster.
// basic step counting algorithm is based on a forum post from
// http://stackoverflow.com/questions/16392142/android-accelerometer-profiling/16539643#16539643
enum state{ // the step counting algorithm cycles through four states
LookingForMax, // looking for a local maximum in current magnitude
LookingForCross1, // looking for current magnitude to cross average magnitude, minus a constant
LookingForMin, // looking for a local minimum in current magnitude
LookingForCross2 // looking for current magnitude to cross average magnitude, plus a constant
};
enum state AlgorithmState = LookingForMax;
uint32_t LocalMin = 1024; // smallest measured magnitude since odd-numbered step detected
uint32_t LocalMax = 0; // largest measured magnitude since even-numbered step detected
uint32_t LocalCount = 0; // number of measured magnitudes above local min or below local max
#define LOCALCOUNTTARGET 5 // The number of valid measured magnitudes needed to confirm a local min or local max. Increase this number for longer strides or more frequent measurements.
#define AVGOVERSHOOT 25 // The amount above or below average a measurement must be to count as "crossing" the average. Increase this number to reject increasingly hard shaking as steps.
// *********Task1_Init*********
// initializes accelerometer
// Task1 counts Steps
// Inputs: none
// Outputs: none
void Task1_Init(void){
BSP_Accelerometer_Init();
// initialize the exponential weighted moving average filter
BSP_Accelerometer_Input(&AccX, &AccY, &AccZ);
Magnitude = sqrt32(AccX*AccX + AccY*AccY + AccZ*AccZ);
EWMA = Magnitude; // this is a guess; there are many options
Steps = 0;
}
// *********Task1*********
// collects data from accelerometer
// counts Steps
// Inputs: none
// Outputs: none
void Task1(void){
TExaS_Task1(); // record system time in array, toggle virtual logic analyzer
Profile_Toggle1(); // viewed by the logic analyzer to know Task1 started
BSP_Accelerometer_Input(&AccX, &AccY, &AccZ);
Magnitude = sqrt32(AccX*AccX + AccY*AccY + AccZ*AccZ);
EWMA = (ALPHA*Magnitude + (1023 - ALPHA)*EWMA)/1024;
if(AlgorithmState == LookingForMax){
if(Magnitude > LocalMax){
LocalMax = Magnitude;
LocalCount = 0;
} else{
LocalCount = LocalCount + 1;
if(LocalCount >= LOCALCOUNTTARGET){
AlgorithmState = LookingForCross1;
}
}
} else if(AlgorithmState == LookingForCross1){
if(Magnitude > LocalMax){
// somehow measured a very large magnitude
LocalMax = Magnitude;
LocalCount = 0;
AlgorithmState = LookingForMax;
} else if(Magnitude < (EWMA - AVGOVERSHOOT)){
// step detected
Steps = Steps + 1;
LocalMin = 1024;
LocalCount = 0;
AlgorithmState = LookingForMin;
}
} else if(AlgorithmState == LookingForMin){
if(Magnitude < LocalMin){
LocalMin = Magnitude;
LocalCount = 0;
} else{
LocalCount = LocalCount + 1;
if(LocalCount >= LOCALCOUNTTARGET){
AlgorithmState = LookingForCross2;
}
}
} else if(AlgorithmState == LookingForCross2){
if(Magnitude < LocalMin){
// somehow measured a very small magnitude
LocalMin = Magnitude;
LocalCount = 0;
AlgorithmState = LookingForMin;
} else if(Magnitude > (EWMA + AVGOVERSHOOT)){
// step detected
Steps = Steps + 1;
LocalMax = 0;
LocalCount = 0;
AlgorithmState = LookingForMax;
}
}
}
/* ****************************************** */
/* End of Task1 Section */
/* ****************************************** */
//---------------- Task2 measures light ----------------
uint32_t Task2Failures; // number of times Light wasn't ready
// *********Task2_Init*********
// initializes light sensor
// Task2 measures light intensity
// Inputs: none
// Outputs: none
void Task2_Init(void){
Task2Failures = 0;
BSP_LightSensor_Init();
LightData = BSP_LightSensor_Input();
BSP_LightSensor_Start();
}
// *********Task2*********
// collects data from light sensor
// Inputs: none
// Outputs: none
// must be called less than once a second
void Task2(void){
TExaS_Task2(); // record system time in array, toggle virtual logic analyzer
Profile_Toggle2(); // viewed by the logic analyzer to know Task2 started
if(BSP_LightSensor_End(&LightData)==0){
Task2Failures++; // should have been ready
}
BSP_LightSensor_Start(); // start measurement for next time
}
/* ****************************************** */
/* End of Task2 Section */
/* ****************************************** */
//------------Task3 handles switch input, buzzer output, LED output-------
// *********Task3_Init*********
// initializes switches, buzzer, and LEDs
// Task3 checks the switches, updates the mode, and outputs to the buzzer and LED
// Inputs: none
// Outputs: none
void Task3_Init(void){
BSP_Button1_Init();
BSP_Button2_Init();
BSP_Buzzer_Init(0);
BSP_RGB_Init(0, 0, 0);
}
// *********Task3*********
// non-real-time task
// checks the switches, updates the mode, and outputs to the buzzer and LED
// Inputs: none
// Outputs: none
void Task3(void){
static uint8_t prev1 = 0, prev2 = 0;
uint8_t current;
TExaS_Task3(); // record system time in array, toggle virtual logic analyzer
Profile_Toggle3(); // viewed by the logic analyzer to know Task3 started
BSP_Buzzer_Set(0);
current = BSP_Button1_Input();
if((current == 0) && (prev1 != 0)){
// Button1 was pressed since last loop
if(PlotState == Accelerometer){
PlotState = Microphone;
} else if(PlotState == Microphone){
PlotState = Light;
} else if(PlotState == Light){
PlotState = Accelerometer;
}
ReDrawAxes = 1; // redraw axes on next call of display task
BSP_Buzzer_Set(512); // beep until next call of this task
}
prev1 = current;
current = BSP_Button2_Input();
if((current == 0) && (prev2 != 0)){
// Button2 was pressed since last loop
if(PlotState == Accelerometer){
PlotState = Light;
} else if(PlotState == Microphone){
PlotState = Accelerometer;
} else if(PlotState == Light){
PlotState = Microphone;
}
ReDrawAxes = 1; // redraw axes on next call of display task
BSP_Buzzer_Set(512); // beep until next call of this task
}
prev2 = current;
// update the LED
switch(AlgorithmState){
case LookingForMax: BSP_RGB_Set(500, 0, 0); break;
case LookingForCross1: BSP_RGB_Set(350, 350, 0); break;
case LookingForMin: BSP_RGB_Set(0, 500, 0); break;
case LookingForCross2: BSP_RGB_Set(0, 0, 500); break;
default: BSP_RGB_Set(0, 0, 0);
}
}
/* ****************************************** */
/* End of Task3 Section */
/* ****************************************** */
//---------------- Task4 plots data on LCD ----------------
#define ACCELERATION_MAX 1400
#define ACCELERATION_MIN 600
#define SOUND_MAX 900
#define SOUND_MIN 300
#define LIGHT_MAX 200000
#define LIGHT_MIN 0
void drawaxes(void){
if(PlotState == Accelerometer){
BSP_LCD_Drawaxes(AXISCOLOR, BGCOLOR, "Time", "Mag", MAGCOLOR, "Ave", EWMACOLOR, ACCELERATION_MAX, ACCELERATION_MIN);
} else if(PlotState == Microphone){
BSP_LCD_Drawaxes(AXISCOLOR, BGCOLOR, "Time", "Sound", SOUNDCOLOR, "", 0, SoundData+100, SoundData-100);
} else if(PlotState == Light){
BSP_LCD_Drawaxes(AXISCOLOR, BGCOLOR, "Time", "Light", LIGHTCOLOR, "", 0, LIGHT_MAX, LIGHT_MIN);
}
}
// return the number of digits
int numlength(uint32_t n){
if(n < 10) return 1;
if(n < 100) return 2;
if(n < 1000) return 3;
if(n < 10000) return 4;
if(n < 100000) return 5;
if(n < 1000000) return 6;
if(n < 10000000) return 7;
if(n < 100000000) return 8;
if(n < 1000000000) return 9;
return 10;
}
// *********Task4_Init*********
// initializes LCD
// Task4 updates the plot and Task5 updates the text at the top of the plot
// Inputs: none
// Outputs: none
void Task4_Init(void){
BSP_LCD_Init();
BSP_LCD_FillScreen(BSP_LCD_Color565(0, 0, 0));
drawaxes();
ReDrawAxes = 0;
}
// *********Task4*********
// updates the plot
// Inputs: none
// Outputs: none
void Task4(void){
TExaS_Task4(); // record system time in array, toggle virtual logic analyzer
Profile_Toggle4(); // viewed by the logic analyzer to know Task4 started
if(ReDrawAxes){
ReDrawAxes = 0;
drawaxes();
}
if(PlotState == Accelerometer){
BSP_LCD_PlotPoint(Magnitude, MAGCOLOR);
BSP_LCD_PlotPoint(EWMA, EWMACOLOR);
} else if(PlotState == Microphone){
BSP_LCD_PlotPoint(SoundData, SOUNDCOLOR);
} else if(PlotState == Light){
BSP_LCD_PlotPoint(LightData, LIGHTCOLOR);
}
BSP_LCD_PlotIncrement();
}
/* ****************************************** */
/* End of Task4 Section */
/* ****************************************** */
/* ------------------------------------------ */
//------- Task5 displays text on LCD -----------
/* ------------------------------------------ */
// *********Task5_Init*********
// initializes LCD
// Task5 updates the text at the top of the plot
// Inputs: none
// Outputs: none
void Task5_Init(void){
// assumes BSP_LCD_Init(); has been called
BSP_LCD_DrawString(0, 0, "Time=", TOPTXTCOLOR);
BSP_LCD_DrawString(0, 1, "Step=", TOPTXTCOLOR);
BSP_LCD_DrawString(10, 0, "Light=", TOPTXTCOLOR);
BSP_LCD_DrawString(10, 1, "Sound=", TOPTXTCOLOR);
}
// *********Task5*********
// updates the text at the top of the LCD
// Inputs: none
// Outputs: none
void Task5(void){
TExaS_Task5(); // record system time in array, toggle virtual logic analyzer
Profile_Toggle5(); // viewed by the logic analyzer to know Task5 started
BSP_LCD_SetCursor(5, 0); BSP_LCD_OutUDec4(Time, TOPNUMCOLOR);
BSP_LCD_SetCursor(5, 1); BSP_LCD_OutUDec4(Steps, MAGCOLOR);
BSP_LCD_SetCursor(16, 0); BSP_LCD_OutUDec4(LightData/100, LIGHTCOLOR);
BSP_LCD_SetCursor(16, 1); BSP_LCD_OutUDec4(SoundRMS, SOUNDCOLOR);
}
/* ****************************************** */
/* End of Task5 Section */
/* ****************************************** */
int main(void){
DisableInterrupts();
BSP_Clock_InitFastest();
Profile_Init(); // initialize the 7 hardware profiling pins
// change 1000 to 4-digit number from edX
TExaS_Init(GRADER, 1000 ); // initialize the Lab 1 grader
// TExaS_Init(LOGICANALYZER, 1000); // initialize the Lab 1 logic analyzer
Task0_Init(); // microphone init
Task1_Init(); // accelerometer init
Task2_Init(); // light init
Task3_Init(); // buttons init
Task4_Init(); // LCD graphics init
Task5_Init(); // LCD text init
Time = 0;
EnableInterrupts(); // interrupts needed for grader to run
/*
Task0 runs approximately every 1ms
Task1 runs approximately every 100ms
Task2 runs approximately every 1s
Task3 runs approximately every 100ms
Task4 runs approximately every 100ms
Task5 runs approximately every 1s
*/
for(int i = 0;; i = (i + 1) % 1000){
BSP_Delay1ms(1);
Task0();
if (i % 100 == 0)
Task1();
if (i == 1)
Task2();
if (i % 100 == 2)
Task3();
if (i % 100 == 3)
Task4();
if (i == 4)
Task5();
Profile_Toggle6();
if (i == 5)
++Time;
}
/*
while(1){
for(int i=0; i<10; i++){ // runs at about 10 Hz
Task0(); // sample microphone
Task1(); // sample accelerometer
Task3(); // check the buttons and change mode if pressed
Task4(); // update the plot
BSP_Delay1ms(100);
}
Task2(); // sample light at 1 Hz
Task5(); // update the LCD text at 1 Hz
Time++; // 1 Hz
Profile_Toggle6();
}
*/
}
// Newton's method
// s is an integer
// sqrt(s) is an integer
uint32_t sqrt32(uint32_t s){
uint32_t t; // t*t will become s
int n; // loop counter
t = s/16+1; // initial guess
for(n = 16; n; --n){ // will finish
t = ((t*t+s)/t)/2;
}
return t;
}

118
Lab1_4C123/Texas.h Normal file
View File

@ -0,0 +1,118 @@
// *****************Texas.h**************
// grading engine for Lab 1
//
// Runs on TM4C123
// Daniel and Jonathan Valvano
// July 17, 2016
/* This example accompanies the books
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
// J1 J3 J4 J2
// [ 1] [21] [40] [20]
// [ 2] [22] [39] [19]
// [ 3] [23] [38] [18]
// [ 4] [24] [37] [17]
// [ 5] [25] [36] [16]
// [ 6] [26] [35] [15]
// [ 7] [27] [34] [14]
// [ 8] [28] [33] [13]
// [ 9] [29] [32] [12]
// [10] [30] [31] [11]
// +3.3V connected to J1.1 (power)
// joystick horizontal (X) connected to J1.2 (analog)
// UART from BoosterPack to LaunchPad connected to J1.3 (UART)
// UART from LaunchPad to BoosterPack connected to J1.4 (UART)
// joystick Select button connected to J1.5 (digital)
// microphone connected to J1.6 (analog)
// LCD SPI clock connected to J1.7 (SPI)
// ambient light (OPT3001) interrupt connected to J1.8 (digital)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SCL connected to J1.9 (I2C)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SDA connected to J1.10 (I2C)
// temperature sensor (TMP006) interrupt connected to J2.11 (digital)
// nothing connected to J2.12 (SPI CS_Other)
// LCD SPI CS connected to J2.13 (SPI)
// nothing connected to J2.14 (SPI MISO)
// LCD SPI data connected to J2.15 (SPI)
// nothing connected to J2.16 (reset)
// LCD !RST connected to J2.17 (digital)
// nothing connected to J2.18 (SPI CS_Wireless)
// servo PWM connected to J2.19 (PWM)
// GND connected to J2.20 (ground)
// +5V connected to J3.21 (power)
// GND connected to J3.22 (ground)
// accelerometer X connected to J3.23 (analog)
// accelerometer Y connected to J3.24 (analog)
// accelerometer Z connected to J3.25 (analog)
// joystick vertical (Y) connected to J3.26 (analog)
// nothing connected to J3.27 (I2S WS)
// nothing connected to J3.28 (I2S SCLK)
// nothing connected to J3.29 (I2S SDout)
// nothing connected to J3.30 (I2S SDin)
// LCD RS connected to J4.31 (digital)
// user Button2 (bottom) connected to J4.32 (digital)
// user Button1 (top) connected to J4.33 (digital)
// gator hole switch connected to J4.34 (digital)
// nothing connected to J4.35
// nothing connected to J4.36
// RGB LED blue connected to J4.37 (PWM)
// RGB LED green connected to J4.38 (PWM)
// RGB LED red (jumper up) or LCD backlight (jumper down) connected to J4.39 (PWM)
// buzzer connected to J4.40 (PWM)
enum TExaSmode{
GRADER,
LOGICANALYZER
};
// ************TExaS_Init*****************
// Initialize grader, triggered by periodic timer
// This needs to be called once
// Inputs: Grading or Logic analyzer
// 4 digit edX number 1000 to 9999
// Outputs: none
void TExaS_Init(enum TExaSmode mode, uint32_t edXcode);
// ************TExaS_Stop*****************
// Stop the transfer
// Inputs: none
// Outputs: none
void TExaS_Stop(void);
// record time Task 0 is started
void TExaS_Task0(void);
// record time Task 0 is started
void TExaS_Task1(void);
// record time Task 2 is started
void TExaS_Task2(void);
// record time Task 3 is started
void TExaS_Task3(void);
// record time Task 4 is started
void TExaS_Task4(void);
// record time Task 5 is started
void TExaS_Task5(void);

544
Lab2_4C123/Lab2.c Normal file
View File

@ -0,0 +1,544 @@
// Lab2.c
// Runs on either MSP432 or TM4C123
// Starter project to Lab 2. Take sensor readings, process the data,
// and output the results. Specifically, this program will
// measure steps using the accelerometer, audio sound amplitude using
// microphone, and temperature. (we will add light back in Lab 3)
// Daniel and Jonathan Valvano
// July 12, 2016
/* This example accompanies the books
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Introduction to the MSP432 Microcontroller",
ISBN: 978-1512185676, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Interfacing to the MSP432 Microcontroller",
ISBN: 978-1514676585, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
#include <stdint.h>
#include "../inc/BSP.h"
#include "../inc/Profile.h"
#include "Texas.h"
#include "../inc/CortexM.h"
#include "os.h"
uint32_t sqrt32(uint32_t s);
#define THREADFREQ 1000 // frequency in Hz of round robin scheduler
//---------------- Global variables shared between tasks ----------------
uint32_t Time; // elasped time in 100 ms units
uint32_t Steps; // number of steps counted
uint32_t Magnitude; // will not overflow (3*1,023^2 = 3,139,587)
// Exponentially Weighted Moving Average
uint32_t EWMA; // https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
uint16_t SoundData; // raw data sampled from the microphone
int32_t SoundAvg;
uint32_t LightData;
int32_t TemperatureData; // 0.1C
// semaphores
int32_t NewData; // true when new numbers to display on top of LCD
int32_t LCDmutex; // exclusive access to LCD
int ReDrawAxes = 0; // non-zero means redraw axes on next display task
enum plotstate{
Accelerometer,
Microphone,
Temperature
};
enum plotstate PlotState = Accelerometer;
//color constants
#define BGCOLOR LCD_BLACK
#define AXISCOLOR LCD_ORANGE
#define MAGCOLOR LCD_YELLOW
#define EWMACOLOR LCD_CYAN
#define SOUNDCOLOR LCD_CYAN
#define TEMPCOLOR LCD_LIGHTGREEN
#define TOPTXTCOLOR LCD_WHITE
#define TOPNUMCOLOR LCD_ORANGE
//------------ end of Global variables shared between tasks -------------
//---------------- Task0 samples sound from microphone ----------------
// Event thread run by OS in real time at 1000 Hz
#define SOUNDRMSLENGTH 1000 // number of samples to collect before calculating RMS (may overflow if greater than 4104)
int16_t SoundArray[SOUNDRMSLENGTH];
// *********Task0_Init*********
// initializes microphone
// Task0 measures sound intensity
// Inputs: none
// Outputs: none
void Task0_Init(void){
BSP_Microphone_Init();
}
// *********Task0*********
// Periodic event thread runs in real time at 1000 Hz
// collects data from microphone
// Inputs: none
// Outputs: none
void Task0(void){
static int32_t soundSum = 0;
static int time = 0; // units of microphone sampling rate
TExaS_Task0(); // record system time in array, toggle virtual logic analyzer
Profile_Toggle0(); // viewed by a real logic analyzer to know Task0 started
// ADC is shared, but on the TM4C123 it is not critical with other ADC inputs
BSP_Microphone_Input(&SoundData);
soundSum = soundSum + (int32_t)SoundData;
SoundArray[time] = SoundData;
time = time + 1;
if(time == SOUNDRMSLENGTH){
SoundAvg = soundSum/SOUNDRMSLENGTH;
soundSum = 0;
OS_Signal(&NewData); // makes task5 run every 1 sec
time = 0;
}
}
/* ****************************************** */
/* End of Task0 Section */
/* ****************************************** */
//---------------- Task1 measures acceleration ----------------
// Event thread run by OS in real time at 10 Hz
uint16_t AccX, AccY, AccZ; // returned by BSP as 10-bit numbers
// *********Task1_Init*********
// initializes accelerometer
// Task1 counts Steps
// Inputs: none
// Outputs: none
void Task1_Init(void){
BSP_Accelerometer_Init();
// initialize the exponential weighted moving average filter
BSP_Accelerometer_Input(&AccX, &AccY, &AccZ);
Magnitude = sqrt32(AccX*AccX + AccY*AccY + AccZ*AccZ);
EWMA = Magnitude; // this is a guess; there are many options
Steps = 0;
}
// *********Task1*********
// collects data from accelerometer
// sends data to Task2
// Inputs: none
// Outputs: none
void Task1(void){uint32_t squared;
TExaS_Task1(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle1(); // viewed by a real logic analyzer to know Task1 started
BSP_Accelerometer_Input(&AccX, &AccY, &AccZ);
squared = AccX*AccX + AccY*AccY + AccZ*AccZ;
OS_MailBox_Send(squared); // makes Task2 run every 100ms
Time++; // in 100ms units
}
/* ****************************************** */
/* End of Task1 Section */
/* ****************************************** */
//---------------- Task2 calculates steps and plots data on LCD ----------------
// Main thread scheduled by OS round robin preemptive scheduler
// accepts data from accelerometer, calculates steps, plots on LCD, and output to LED
// If no data are lost, the main loop in Task2 runs exactly at 10 Hz, but not in real time
enum state{ // the step counting algorithm cycles through four states
LookingForMax, // looking for a local maximum in current magnitude
LookingForCross1, // looking for current magnitude to cross average magnitude, minus a constant
LookingForMin, // looking for a local minimum in current magnitude
LookingForCross2 // looking for current magnitude to cross average magnitude, plus a constant
};
enum state AlgorithmState = LookingForMax;
#define LOCALCOUNTTARGET 5 // The number of valid measured magnitudes needed to confirm a local min or local max. Increase this number for longer strides or more frequent measurements.
#define AVGOVERSHOOT 25 // The amount above or below average a measurement must be to count as "crossing" the average. Increase this number to reject increasingly hard shaking as steps.
#define ACCELERATION_MAX 1400
#define ACCELERATION_MIN 600
#define ALPHA 128 // The degree of weighting decrease, a constant smoothing factor between 0 and 1,023. A higher ALPHA discounts older observations faster.
// basic step counting algorithm is based on a forum post from
// http://stackoverflow.com/questions/16392142/android-accelerometer-profiling/16539643#16539643
#define SOUND_MAX 900
#define SOUND_MIN 300
#define LIGHT_MAX 200000
#define LIGHT_MIN 0
#define TEMP_MAX 1023
#define TEMP_MIN 0
void drawaxes(void){
OS_Wait(&LCDmutex);
if(PlotState == Accelerometer){
BSP_LCD_Drawaxes(AXISCOLOR, BGCOLOR, "Time", "Mag", MAGCOLOR, "Ave", EWMACOLOR, ACCELERATION_MAX, ACCELERATION_MIN);
} else if(PlotState == Microphone){
BSP_LCD_Drawaxes(AXISCOLOR, BGCOLOR, "Time", "Sound", SOUNDCOLOR, "", 0, SoundData+100, SoundData-100);
} else if(PlotState == Temperature){
BSP_LCD_Drawaxes(AXISCOLOR, BGCOLOR, "Time", "Temp", TEMPCOLOR, "", 0, TEMP_MAX, TEMP_MIN);
}
OS_Signal(&LCDmutex); ReDrawAxes = 0;
}
void Task2(void){uint32_t data;
uint32_t localMin; // smallest measured magnitude since odd-numbered step detected
uint32_t localMax; // largest measured magnitude since even-numbered step detected
uint32_t localCount; // number of measured magnitudes above local min or below local max
localMin = 1024;
localMax = 0;
localCount = 0;
drawaxes();
while(1){
data = OS_MailBox_Recv(); // acceleration data from Task 1
TExaS_Task2(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle2(); // viewed by a real logic analyzer to know Task2 started
Magnitude = sqrt32(data);
EWMA = (ALPHA*Magnitude + (1023 - ALPHA)*EWMA)/1024;
if(AlgorithmState == LookingForMax){
if(Magnitude > localMax){
localMax = Magnitude;
localCount = 0;
} else{
localCount = localCount + 1;
if(localCount >= LOCALCOUNTTARGET){
AlgorithmState = LookingForCross1;
}
}
} else if(AlgorithmState == LookingForCross1){
if(Magnitude > localMax){
// somehow measured a very large magnitude
localMax = Magnitude;
localCount = 0;
AlgorithmState = LookingForMax;
} else if(Magnitude < (EWMA - AVGOVERSHOOT)){
// step detected
Steps = Steps + 1;
localMin = 1024;
localCount = 0;
AlgorithmState = LookingForMin;
}
} else if(AlgorithmState == LookingForMin){
if(Magnitude < localMin){
localMin = Magnitude;
localCount = 0;
} else{
localCount = localCount + 1;
if(localCount >= LOCALCOUNTTARGET){
AlgorithmState = LookingForCross2;
}
}
} else if(AlgorithmState == LookingForCross2){
if(Magnitude < localMin){
// somehow measured a very small magnitude
localMin = Magnitude;
localCount = 0;
AlgorithmState = LookingForMin;
} else if(Magnitude > (EWMA + AVGOVERSHOOT)){
// step detected
Steps = Steps + 1;
localMax = 0;
localCount = 0;
AlgorithmState = LookingForMax;
}
}
if(ReDrawAxes){
drawaxes();
ReDrawAxes = 0;
}
OS_Wait(&LCDmutex);
if(PlotState == Accelerometer){
BSP_LCD_PlotPoint(Magnitude, MAGCOLOR);
BSP_LCD_PlotPoint(EWMA, EWMACOLOR);
} else if(PlotState == Microphone){
BSP_LCD_PlotPoint(SoundData, SOUNDCOLOR);
} else if(PlotState == Temperature){
BSP_LCD_PlotPoint(TemperatureData, TEMPCOLOR);
}
BSP_LCD_PlotIncrement();
OS_Signal(&LCDmutex);
// update the LED
switch(AlgorithmState){
case LookingForMax: BSP_RGB_Set(500, 0, 0); break;
case LookingForCross1: BSP_RGB_Set(350, 350, 0); break;
case LookingForMin: BSP_RGB_Set(0, 500, 0); break;
case LookingForCross2: BSP_RGB_Set(0, 0, 500); break;
default: BSP_RGB_Set(0, 0, 0);
}
}
}
/* ****************************************** */
/* End of Task2 Section */
/* ****************************************** */
//------------Task3 handles switch input, buzzer output, LED output-------
// *********Task3*********
// Main thread scheduled by OS round robin preemptive scheduler
// non-real-time task
// checks the switches, updates the mode, and outputs to the buzzer
// Inputs: none
// Outputs: none
void Task3(void){
static uint8_t prev1 = 0, prev2 = 0;
uint8_t current;
BSP_Button1_Init();
BSP_Button2_Init();
BSP_Buzzer_Init(0);
BSP_RGB_Init(0, 0, 0);
while(1){
TExaS_Task3(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle3(); // viewed by a real logic analyzer to know Task3 started
BSP_Buzzer_Set(0);
current = BSP_Button1_Input();
if((current == 0) && (prev1 != 0)){
// Button1 was pressed since last loop
if(PlotState == Accelerometer){
PlotState = Microphone;
} else if(PlotState == Microphone){
PlotState = Temperature;
} else if(PlotState == Temperature){
PlotState = Accelerometer;
}
ReDrawAxes = 1; // redraw axes on next call of display task
BSP_Buzzer_Set(512); // beep until next call of this task
}
prev1 = current;
current = BSP_Button2_Input();
if((current == 0) && (prev2 != 0)){
// Button2 was pressed since last loop
if(PlotState == Accelerometer){
PlotState = Temperature;
} else if(PlotState == Microphone){
PlotState = Accelerometer;
} else if(PlotState == Temperature){
PlotState = Microphone;
}
ReDrawAxes = 1; // redraw axes on next call of display task
BSP_Buzzer_Set(512); // beep until next call of this task
}
prev2 = current;
BSP_Delay1ms(5); // very inefficient, but does debounce the switches
}
}
/* ****************************************** */
/* End of Task3 Section */
/* ****************************************** */
//------------Task4 measures temperature-------
// *********Task4*********
// Main thread scheduled by OS round robin preemptive scheduler
// measures temperature
// Inputs: none
// Outputs: none
void Task4(void){int32_t voltData,tempData;
int done;
BSP_TempSensor_Init();
while(1){
TExaS_Task4(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle4(); // viewed by a real logic analyzer to know Task4 started
BSP_TempSensor_Start();
done = 0;
while(done == 0){
done = BSP_TempSensor_End(&voltData,&tempData); // waits about 1 sec
}
TemperatureData = tempData/10000;
}
}
/* ****************************************** */
/* End of Task4 Section */
/* ****************************************** */
/* ------------------------------------------ */
//------- Task5 displays text on LCD -----------
/* ------------------------------------------ */
// If no data are lost, the main loop in Task5 runs exactly at 1 Hz, but not in real time
// *********Task5*********
// Main thread scheduled by OS round robin preemptive scheduler
// updates the text at the top of the LCD
// Inputs: none
// Outputs: none
void Task5(void){int32_t soundSum;
uint32_t soundRMS; // Root Mean Square average of most recent sound samples
OS_Wait(&LCDmutex);
BSP_LCD_DrawString(0, 0, "Time=", TOPTXTCOLOR);
BSP_LCD_DrawString(0, 1, "Step=", TOPTXTCOLOR);
BSP_LCD_DrawString(10, 0, "Temp =", TOPTXTCOLOR);
BSP_LCD_DrawString(10, 1, "Sound=", TOPTXTCOLOR);
OS_Signal(&LCDmutex);
while(1){
OS_Wait(&NewData);
TExaS_Task5(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle5(); // viewed by a real logic analyzer to know Task5 started
soundSum = 0;
for(int i=0; i<SOUNDRMSLENGTH; i=i+1){
soundSum = soundSum + (SoundArray[i] - SoundAvg)*(SoundArray[i] - SoundAvg);
}
soundRMS = sqrt32(soundSum/SOUNDRMSLENGTH);
OS_Wait(&LCDmutex);
BSP_LCD_SetCursor(5, 0); BSP_LCD_OutUDec4(Time/10, TOPNUMCOLOR);
BSP_LCD_SetCursor(5, 1); BSP_LCD_OutUDec4(Steps, MAGCOLOR);
BSP_LCD_SetCursor(16, 0); BSP_LCD_OutUFix2_1(TemperatureData, TEMPCOLOR);
BSP_LCD_SetCursor(16, 1); BSP_LCD_OutUDec4(soundRMS, SOUNDCOLOR);
OS_Signal(&LCDmutex);
}
}
/* ****************************************** */
/* End of Task5 Section */
/* ****************************************** */
int main_step1(void); // OK
int main_step2(void); // OK
int main_step3(void); // OK
int main_step4(void); // OK
int main_step5(void); // BROKEN
int main(void){
//TExaS_Init(LOGICANALYZER, 1000);
//main_step5();
//return 0;
OS_Init();
Profile_Init(); // initialize the 7 hardware profiling pins
Task0_Init(); // microphone init
Task1_Init(); // accelerometer init
BSP_LCD_Init();
BSP_LCD_FillScreen(BSP_LCD_Color565(0, 0, 0));
Time = 0;
OS_InitSemaphore(&NewData, 0); // 0 means no data
OS_InitSemaphore(&LCDmutex, 1); // 1 means free
OS_MailBox_Init(); // initialize mailbox used to send data between Task1 and Task2
// Task 0 should run every 1ms and Task 1 should run every 100ms
OS_AddPeriodicEventThreads(&Task0, 1, &Task1, 100);
// Task2, Task3, Task4, Task5 are main threads
OS_AddThreads(&Task2, &Task3, &Task4, &Task5);
// when grading change 1000 to 4-digit number from edX
TExaS_Init(GRADER, 1000); // initialize the Lab 2 grader
//TExaS_Init(LOGICANALYZER, 1000); // initialize the Lab 2 logic analyzer
OS_Launch(BSP_Clock_GetFreq()/THREADFREQ); // doesn't return, interrupts enabled in here
return 0; // this never executes
}
//******************Step 1************************** done
// implement and test the semaphores
int32_t s1,s2;
int main_step1(void){
OS_InitSemaphore(&s1,0);
OS_InitSemaphore(&s2,1);
while(1){
OS_Wait(&s2); //now s1=0, s2=0
OS_Signal(&s1); //now s1=1, s2=0
OS_Signal(&s2); //now s1=1, s2=1
OS_Signal(&s1); //now s1=2, s2=1
OS_Wait(&s1); //now s1=1, s2=1
OS_Wait(&s1); //now s1=0, s2=1
}
}
//***************Step 2************************* done
// Implement the three mailbox functions as defined in OS.c and OS.h
// Use this a simple main program to test the mailbox functions.
uint32_t Out;
int main_step2(void){ uint32_t in=0;
OS_MailBox_Init();
while(1){
OS_MailBox_Send(in);
Out = OS_MailBox_Recv();
in++;
}
}
//***************Step 3************************* done
// Test the round robin scheduler
// The minimal set of functions you need to write to get the system running is
// SysTick_Handler (without calling the C function and without running periodic threads)
// StartOS
// OS_Init
// OS_AddThreads3 (with just 3 threads for now)
// OS_Launch
int main_step3(void){
OS_Init();
Profile_Init(); // initialize the 7 hardware profiling pins
Task0_Init(); // microphone init
Task1_Init(); // accelerometer init
BSP_LCD_Init();
BSP_LCD_FillScreen(BSP_LCD_Color565(0, 0, 0));
Time = 0;
// semaphores and mailbox not used
// Tasks 0, 1, 2 will not run
// Task3, Task4, Task5 are main threads
// Task2 will stall
OS_AddThreads3(&Task3, &Task4, &Task5);
// when grading change 1000 to 4-digit number from edX
TExaS_Init(GRADER, 1000); // initialize the Lab 2 grader
//TExaS_Init(LOGICANALYZER, 1000); // initialize the Lab 2 logic analyzer
OS_Launch(BSP_Clock_GetFreq()/THREADFREQ); // doesn't return, interrupts enabled in here
return 0; // this never executes
}
//***************Step 4*************************
// Increase to 4 threads
int main_step4(void){
OS_Init();
Profile_Init(); // initialize the 7 hardware profiling pins
Task0_Init(); // microphone init
Task1_Init(); // accelerometer init
BSP_LCD_Init();
BSP_LCD_FillScreen(BSP_LCD_Color565(0, 0, 0));
Time = 0;
OS_InitSemaphore(&NewData, 0); // 0 means no data
OS_InitSemaphore(&LCDmutex, 1); // 1 means free
OS_MailBox_Init(); // initialize mailbox used to send data between Task1 and Task2
// Tasks 0, 1 will not run
// Task2, Task3, Task4, Task5 are main threads
// Tasks 2 and 5 will stall
OS_AddThreads(&Task2, &Task3, &Task4, &Task5);
// when grading change 1000 to 4-digit number from edX
TExaS_Init(GRADER, 1000); // initialize the Lab 2 grader
//TExaS_Init(LOGICANALYZER, 1000); // initialize the Lab 2 logic analyzer
OS_Launch(BSP_Clock_GetFreq()/THREADFREQ); // doesn't return, interrupts enabled in here
return 0; // this never executes
}
//***************Step 5*************************
// add one periodic task
void Dummy(void){}; // place holder
int main_step5(void){
OS_Init();
Profile_Init(); // initialize the 7 hardware profiling pins
Task0_Init(); // microphone init
Task1_Init(); // accelerometer init
BSP_LCD_Init();
BSP_LCD_FillScreen(BSP_LCD_Color565(0, 0, 0));
Time = 0;
OS_InitSemaphore(&NewData, 0); // 0 means no data
OS_InitSemaphore(&LCDmutex, 1); // 1 means free
OS_MailBox_Init(); // initialize mailbox used to send data between Task1 and Task2
// Task1 will not run
// Task5 will stall
// Task 0 should run every 1ms and dummy is not run
OS_AddPeriodicEventThreads(&Task0, 1, &Dummy, 100);
// Task2, Task3, Task4, Task5 are main threads
OS_AddThreads(&Task2, &Task3, &Task4, &Task5);
// when grading change 1000 to 4-digit number from edX
TExaS_Init(GRADER, 1000); // initialize the Lab 2 grader
//TExaS_Init(LOGICANALYZER, 1000); // initialize the Lab 2 logic analyzer
OS_Launch(BSP_Clock_GetFreq()/THREADFREQ); // doesn't return, interrupts enabled in here
return 0; // this never executes
}
// Newton's method
// s is an integer
// sqrt(s) is an integer
uint32_t sqrt32(uint32_t s){
uint32_t t; // t*t will become s
int n; // loop counter
t = s/16+1; // initial guess
for(n = 16; n; --n){ // will finish
t = ((t*t+s)/t)/2;
}
return t;
}

118
Lab2_4C123/Texas.h Normal file
View File

@ -0,0 +1,118 @@
// *****************Texas.h**************
// grading engine for Lab 2
//
// Runs on TM4C123
// Daniel and Jonathan Valvano
// February 24, 2016
/* This example accompanies the books
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
// J1 J3 J4 J2
// [ 1] [21] [40] [20]
// [ 2] [22] [39] [19]
// [ 3] [23] [38] [18]
// [ 4] [24] [37] [17]
// [ 5] [25] [36] [16]
// [ 6] [26] [35] [15]
// [ 7] [27] [34] [14]
// [ 8] [28] [33] [13]
// [ 9] [29] [32] [12]
// [10] [30] [31] [11]
// +3.3V connected to J1.1 (power)
// joystick horizontal (X) connected to J1.2 (analog)
// UART from BoosterPack to LaunchPad connected to J1.3 (UART)
// UART from LaunchPad to BoosterPack connected to J1.4 (UART)
// joystick Select button connected to J1.5 (digital)
// microphone connected to J1.6 (analog)
// LCD SPI clock connected to J1.7 (SPI)
// ambient light (OPT3001) interrupt connected to J1.8 (digital)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SCL connected to J1.9 (I2C)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SDA connected to J1.10 (I2C)
// temperature sensor (TMP006) interrupt connected to J2.11 (digital)
// nothing connected to J2.12 (SPI CS_Other)
// LCD SPI CS connected to J2.13 (SPI)
// nothing connected to J2.14 (SPI MISO)
// LCD SPI data connected to J2.15 (SPI)
// nothing connected to J2.16 (reset)
// LCD !RST connected to J2.17 (digital)
// nothing connected to J2.18 (SPI CS_Wireless)
// servo PWM connected to J2.19 (PWM)
// GND connected to J2.20 (ground)
// +5V connected to J3.21 (power)
// GND connected to J3.22 (ground)
// accelerometer X connected to J3.23 (analog)
// accelerometer Y connected to J3.24 (analog)
// accelerometer Z connected to J3.25 (analog)
// joystick vertical (Y) connected to J3.26 (analog)
// nothing connected to J3.27 (I2S WS)
// nothing connected to J3.28 (I2S SCLK)
// nothing connected to J3.29 (I2S SDout)
// nothing connected to J3.30 (I2S SDin)
// LCD RS connected to J4.31 (digital)
// user Button2 (bottom) connected to J4.32 (digital)
// user Button1 (top) connected to J4.33 (digital)
// gator hole switch connected to J4.34 (digital)
// nothing connected to J4.35
// nothing connected to J4.36
// RGB LED blue connected to J4.37 (PWM)
// RGB LED green connected to J4.38 (PWM)
// RGB LED red (jumper up) or LCD backlight (jumper down) connected to J4.39 (PWM)
// buzzer connected to J4.40 (PWM)
enum TExaSmode{
GRADER,
LOGICANALYZER
};
// ************TExaS_Init*****************
// Initialize grader, triggered by periodic timer
// This needs to be called once
// Inputs: Grading or Logic analyzer
// 4-digit number from edX
// Outputs: none
void TExaS_Init(enum TExaSmode mode, uint32_t edXcode);
// ************TExaS_Stop*****************
// Stop the transfer
// Inputs: none
// Outputs: none
void TExaS_Stop(void);
// record time Task 0 is started
void TExaS_Task0(void);
// record time Task 0 is started
void TExaS_Task1(void);
// record time Task 2 is started
void TExaS_Task2(void);
// record time Task 3 is started
void TExaS_Task3(void);
// record time Task 4 is started
void TExaS_Task4(void);
// record time Task 5 is started
void TExaS_Task5(void);

237
Lab2_4C123/os.c Normal file
View File

@ -0,0 +1,237 @@
// os.c
// Runs on LM4F120/TM4C123/MSP432
// Lab 2 starter file.
// Daniel Valvano
// February 20, 2016
#include <stdint.h>
#include "os.h"
#include "../inc/CortexM.h"
#include "../inc/BSP.h"
// function definitions in osasm.s
void StartOS(void);
periodicType periodic[2];
tcbType tcbs[4];
tcbType *RunPt;
int32_t Stacks[4][STACKSIZE];
// ******** OS_Init ************
// Initialize operating system, disable interrupts
// Initialize OS controlled I/O: systick, bus clock as fast as possible
// Initialize OS global variables
// Inputs: none
// Outputs: none
void OS_Init(void){
DisableInterrupts();
BSP_Clock_InitFastest();// set processor clock to fastest speed
// initialize any global variables as needed
}
void SetInitialStack(int i){
tcbs[i].sp = &Stacks[i][STACKSIZE - 16];
Stacks[i][STACKSIZE-1] = 0x01000000; // Thumb bit
//Stacks[i][STACKSIZE-2] is reserved for PC
//and is initialized with start address of task
Stacks[i][STACKSIZE-3] = 0x14141414; // R14 = LR
Stacks[i][STACKSIZE-4] = 0x12121212; // R12
Stacks[i][STACKSIZE-5] = 0x03030303; // R3
Stacks[i][STACKSIZE-6] = 0x02020202; // R2
Stacks[i][STACKSIZE-7] = 0x01010101; // R1
Stacks[i][STACKSIZE-8] = 0x00000000; // R0
Stacks[i][STACKSIZE-9] = 0x11111111; // R11
Stacks[i][STACKSIZE-10] = 0x10101010; // R10
Stacks[i][STACKSIZE-11] = 0x09090909; // R9
Stacks[i][STACKSIZE-12] = 0x08080808; // R8
Stacks[i][STACKSIZE-13] = 0x07070707; // R7
Stacks[i][STACKSIZE-14] = 0x06060606; // R6
Stacks[i][STACKSIZE-15] = 0x05050505; // R5
Stacks[i][STACKSIZE-16] = 0x04040404; // R4
}
//******** OS_AddThreads ***************
// Add four main threads to the scheduler
// Inputs: function pointers to four void/void main threads
// Outputs: 1 if successful, 0 if this thread can not be added
// This function will only be called once, after OS_Init and before OS_Launch
int OS_AddThreads(void(*thread0)(void),
void(*thread1)(void),
void(*thread2)(void),
void(*thread3)(void)){
// initialize TCB circular list
// initialize RunPt
// initialize four stacks, including initial PC
uint32_t status = StartCritical();
tcbs[0].next = &tcbs[1];
tcbs[1].next = &tcbs[2];
tcbs[2].next = &tcbs[3];
tcbs[3].next = &tcbs[0];
SetInitialStack(0); Stacks[0][STACKSIZE-2] = (int32_t)(thread0);
SetInitialStack(1); Stacks[1][STACKSIZE-2] = (int32_t)(thread1);
SetInitialStack(2); Stacks[2][STACKSIZE-2] = (int32_t)(thread2);
SetInitialStack(3); Stacks[3][STACKSIZE-2] = (int32_t)(thread3);
RunPt = &tcbs[0];
EndCritical(status);
return 1; // successful
}
//******** OS_AddThreads3 ***************
// add three foregound threads to the scheduler
// This is needed during debugging and not part of final solution
// Inputs: three pointers to a void/void foreground tasks
// Outputs: 1 if successful, 0 if this thread can not be added
int OS_AddThreads3(void(*task0)(void),
void(*task1)(void),
void(*task2)(void)){
// initialize TCB circular list (same as RTOS project)
// initialize RunPt
// initialize four stacks, including initial PC
uint32_t status = StartCritical();
tcbs[0].next = &tcbs[1];
tcbs[1].next = &tcbs[2];
tcbs[2].next = &tcbs[0];
SetInitialStack(0); Stacks[0][STACKSIZE-2] = (int32_t)(task0);
SetInitialStack(1); Stacks[1][STACKSIZE-2] = (int32_t)(task1);
SetInitialStack(2); Stacks[2][STACKSIZE-2] = (int32_t)(task2);
RunPt = &tcbs[0];
EndCritical(status);
return 1; // successful
}
//******** OS_AddPeriodicEventThreads ***************
// Add two background periodic event threads
// Typically this function receives the highest priority
// Inputs: pointers to a void/void event thread function2
// periods given in units of OS_Launch (Lab 2 this will be msec)
// Outputs: 1 if successful, 0 if this thread cannot be added
// It is assumed that the event threads will run to completion and return
// It is assumed the time to run these event threads is short compared to 1 msec
// These threads cannot spin, block, loop, sleep, or kill
// These threads can call OS_Signal
int OS_AddPeriodicEventThreads(void(*thread1)(void), uint32_t period1,
void(*thread2)(void), uint32_t period2){ //TODO
int32_t status;
status = StartCritical();
periodic[0].period = period1;
periodic[0].task = thread1;
periodic[1].period = period2;
periodic[1].task = thread2;
EndCritical(status);
return 1; // successful
}
//******** OS_Launch ***************
// Start the scheduler, enable interrupts
// Inputs: number of clock cycles for each time slice
// Outputs: none (does not return)
// Errors: theTimeSlice must be less than 16,777,216
void OS_Launch(uint32_t theTimeSlice){
STCTRL = 0; // disable SysTick during setup
STCURRENT = 0; // any write to current clears it
SYSPRI3 =(SYSPRI3&0x00FFFFFF)|0xE0000000; // priority 7
STRELOAD = theTimeSlice - 1; // reload value
STCTRL = 0x00000007; // enable, core clock and interrupt arm
StartOS(); // start on the first task
}
static uint32_t timer = 0;
// runs every ms
void Scheduler(void){ // every time slice
// run any periodic event threads if needed
// implement round robin scheduler, update RunPt
for (int i = 0; i < 2; ++i) {
if ((timer % periodic[i].period) == 0) {
periodic[i].task();
}
}
++timer;
RunPt = RunPt->next; // Round Robin
}
// ******** OS_InitSemaphore ************
// Initialize counting semaphore
// Inputs: pointer to a semaphore
// initial value of semaphore
// Outputs: none
void OS_InitSemaphore(int32_t *semaPt, int32_t value){
*semaPt = value;
}
// ******** OS_Wait ************
// Decrement semaphore
// Lab2 spinlock (does not suspend while spinning)
// Lab3 block if less than zero
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Wait(int32_t *semaPt){
uint32_t status = StartCritical();
while (*semaPt <= 0) {
EndCritical(status);
status = StartCritical();
}
--(*semaPt);
EndCritical(status);
}
// ******** OS_Signal ************
// Increment semaphore
// Lab2 spinlock
// Lab3 wakeup blocked thread if appropriate
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Signal(int32_t *semaPt){
uint32_t status = StartCritical();
++(*semaPt);
EndCritical(status);
}
// ******** OS_MailBox_Init ************
// Initialize communication channel
// Producer is an event thread, consumer is a main thread
// Inputs: none
// Outputs: none
uint32_t MailBox;
int32_t MailBox_Send;
int32_t MailBox_Ack;
void OS_MailBox_Init(void){
// include data field and semaphore
MailBox = 0;
OS_InitSemaphore(&MailBox_Send, 0);
OS_InitSemaphore(&MailBox_Ack, 0);
}
// ******** OS_MailBox_Send ************
// Enter data into the MailBox, do not spin/block if full
// Use semaphore to synchronize with OS_MailBox_Recv
// Inputs: data to be sent
// Outputs: none
// Errors: data lost if MailBox already has data
void OS_MailBox_Send(uint32_t data){
MailBox = data; // Overwrite data (may lose old data)
OS_Signal(&MailBox_Send); // Signal data availability
}
// ******** OS_MailBox_Recv ************
// retreive mail from the MailBox
// Use semaphore to synchronize with OS_MailBox_Send
// Lab 2 spin on semaphore if mailbox empty
// Lab 3 block on semaphore if mailbox empty
// Inputs: none
// Outputs: data retreived
// Errors: none
uint32_t OS_MailBox_Recv(void){
OS_Wait(&MailBox_Send);
int32_t data = MailBox; // read mail
return data;
}

142
Lab2_4C123/os.h Normal file
View File

@ -0,0 +1,142 @@
// os.h
// Runs on LM4F120/TM4C123/MSP432
// A very simple real time operating system with minimal features.
// Daniel Valvano
// February 20, 2016
/* This example accompanies the book
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, , Jonathan Valvano, copyright (c) 2016
Programs 4.4 through 4.12, section 4.2
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
#ifndef __OS_H
#define __OS_H 1
// grader needs access to TCBs and stacks
#define NUMTHREADS 4 // maximum number of threads
#define NUMEVENTTHREADS 2
#define STACKSIZE 100 // number of 32-bit words in stack per thread
struct tcb{
int32_t *sp; // pointer to stack (valid for threads not running
struct tcb *next; // linked-list pointer
};
typedef struct tcb tcbType;
struct periodic{
uint32_t period;
void(*task)(void);
};
typedef struct periodic periodicType;
// ******** OS_Init ************
// Initialize operating system, disable interrupts
// Initialize OS controlled I/O: systick, bus clock as fast as possible
// Initialize OS global variables
// Inputs: none
// Outputs: none
void OS_Init(void);
//******** OS_AddThreads ***************
// Add four main threads to the scheduler
// Inputs: function pointers to four void/void main threads
// Outputs: 1 if successful, 0 if this thread can not be added
// This function will only be called once, after OS_Init and before OS_Launch
int OS_AddThreads(void(*thread0)(void),
void(*thread1)(void),
void(*thread2)(void),
void(*thread3)(void));
//******** OS_AddThreads3 ***************
// add three foregound threads to the scheduler
// This is needed during debugging and not part of final solution
// Inputs: three pointers to a void/void foreground tasks
// Outputs: 1 if successful, 0 if this thread can not be added
int OS_AddThreads3(void(*task0)(void),
void(*task1)(void),
void(*task2)(void));
//******** OS_AddPeriodicEventThreads ***************
// Add two background periodic event threads
// Typically this function receives the highest priority
// Inputs: pointers to a void/void event thread function2
// periods given in units of OS_Launch (Lab 2 this will be msec)
// Outputs: 1 if successful, 0 if this thread cannot be added
// It is assumed that the event threads will run to completion and return
// It is assumed the time to run these event threads is short compared to 1 msec
// These threads cannot spin, block, loop, sleep, or kill
// These threads can call OS_Signal
int OS_AddPeriodicEventThreads(void(*thread1)(void), uint32_t period1,
void(*thread2)(void), uint32_t period2);
//******** OS_Launch ***************
// Start the scheduler, enable interrupts
// Inputs: number of clock cycles for each time slice
// Outputs: none (does not return)
// Errors: theTimeSlice must be less than 16,777,216
void OS_Launch(uint32_t theTimeSlice);
// ******** OS_InitSemaphore ************
// Initialize counting semaphore
// Inputs: pointer to a semaphore
// initial value of semaphore
// Outputs: none
void OS_InitSemaphore(int32_t *semaPt, int32_t value);
// ******** OS_Wait ************
// Decrement semaphore
// Lab2 spinlock (does not suspend while spinning)
// Lab3 block if less than zero
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Wait(int32_t *semaPt);
// ******** OS_Signal ************
// Increment semaphore
// Lab2 spinlock
// Lab3 wakeup blocked thread if appropriate
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Signal(int32_t *semaPt);
// ******** OS_MailBox_Init ************
// Initialize communication channel
// Producer is an event thread, consumer is a main thread
// Inputs: none
// Outputs: none
void OS_MailBox_Init(void);
// ******** OS_MailBox_Send ************
// Enter data into the MailBox, do not spin/block if full
// Use semaphore to synchronize with OS_MailBox_Recv
// Inputs: data to be sent
// Outputs: none
// Errors: data lost if MailBox already has data
void OS_MailBox_Send(uint32_t data);
// ******** OS_MailBox_Recv ************
// retreive mail from the MailBox
// Use semaphore to synchronize with OS_MailBox_Send
// Lab 2 spin on semaphore if mailbox empty
// Lab 3 block on semaphore if mailbox empty
// Inputs: none
// Outputs: data retreived
// Errors: none
uint32_t OS_MailBox_Recv(void);
#endif

49
Lab2_4C123/osasm.s Normal file
View File

@ -0,0 +1,49 @@
;/*****************************************************************************/
; OSasm.s: low-level OS commands, written in assembly */
; Runs on LM4F120/TM4C123/MSP432
; Lab 2 starter file
; February 10, 2016
;
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
EXTERN RunPt ; currently running thread
EXPORT StartOS
EXPORT SysTick_Handler
IMPORT Scheduler
SysTick_Handler ; 1) Saves R0-R3,R12,LR,PC,PSR
CPSID I ; 2) Prevent interrupt during switch
PUSH {R4-R11} ; 3) Save remaining regs r4-11
LDR R0, =RunPt ; 4) R0=pointer to RunPt, old thread
LDR R1, [R0] ; R1 = RunPt
STR SP, [R1] ; 5) Save SP into TCB
PUSH {R0,LR}
BL Scheduler
POP {R0,LR}
LDR R1, [R0] ; 6) R1 = RunPt, new thread
LDR SP, [R1] ; 7) new thread SP; SP = RunPt->sp;
POP {R4-R11} ; 8) restore regs r4-11
CPSIE I ; 9) tasks run with interrupts enabled
BX LR ; 10) restore R0-R3,R12,LR,PC,PSR
StartOS
LDR R0, =RunPt ; currently running thread
LDR R2, [R0] ; R2 = value of RunPt
LDR SP, [R2] ; new thread SP; SP = RunPt->stackPointer;
POP {R4-R11} ; restore regs r4-11
POP {R0-R3} ; restore regs r0-3
POP {R12}
ADD SP,SP,#4 ; discard LR from initial stack
POP {LR} ; start location
ADD SP,SP,#4 ; discard PSR
CPSIE I ; Enable interrupts at processor level
BX LR ; start first thread
ALIGN
END

1263
Lab3_4C123/Lab3.c Normal file

File diff suppressed because it is too large Load Diff

125
Lab3_4C123/Texas.h Normal file
View File

@ -0,0 +1,125 @@
// *****************Texas.h**************
// grading engine for Lab 3
//
// Runs on TM4C123
// Daniel and Jonathan Valvano
// March 23, 2016
/* This example accompanies the books
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
// J1 J3 J4 J2
// [ 1] [21] [40] [20]
// [ 2] [22] [39] [19]
// [ 3] [23] [38] [18]
// [ 4] [24] [37] [17]
// [ 5] [25] [36] [16]
// [ 6] [26] [35] [15]
// [ 7] [27] [34] [14]
// [ 8] [28] [33] [13]
// [ 9] [29] [32] [12]
// [10] [30] [31] [11]
// +3.3V connected to J1.1 (power)
// joystick horizontal (X) connected to J1.2 (analog)
// UART from BoosterPack to LaunchPad connected to J1.3 (UART)
// UART from LaunchPad to BoosterPack connected to J1.4 (UART)
// joystick Select button connected to J1.5 (digital)
// microphone connected to J1.6 (analog)
// LCD SPI clock connected to J1.7 (SPI)
// ambient light (OPT3001) interrupt connected to J1.8 (digital)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SCL connected to J1.9 (I2C)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SDA connected to J1.10 (I2C)
// temperature sensor (TMP006) interrupt connected to J2.11 (digital)
// nothing connected to J2.12 (SPI CS_Other)
// LCD SPI CS connected to J2.13 (SPI)
// nothing connected to J2.14 (SPI MISO)
// LCD SPI data connected to J2.15 (SPI)
// nothing connected to J2.16 (reset)
// LCD !RST connected to J2.17 (digital)
// nothing connected to J2.18 (SPI CS_Wireless)
// servo PWM connected to J2.19 (PWM)
// GND connected to J2.20 (ground)
// +5V connected to J3.21 (power)
// GND connected to J3.22 (ground)
// accelerometer X connected to J3.23 (analog)
// accelerometer Y connected to J3.24 (analog)
// accelerometer Z connected to J3.25 (analog)
// joystick vertical (Y) connected to J3.26 (analog)
// nothing connected to J3.27 (I2S WS)
// nothing connected to J3.28 (I2S SCLK)
// nothing connected to J3.29 (I2S SDout)
// nothing connected to J3.30 (I2S SDin)
// LCD RS connected to J4.31 (digital)
// user Button2 (bottom) connected to J4.32 (digital)
// user Button1 (top) connected to J4.33 (digital)
// gator hole switch connected to J4.34 (digital)
// nothing connected to J4.35
// nothing connected to J4.36
// RGB LED blue connected to J4.37 (PWM)
// RGB LED green connected to J4.38 (PWM)
// RGB LED red (jumper up) or LCD backlight (jumper down) connected to J4.39 (PWM)
// buzzer connected to J4.40 (PWM)
enum TExaSmode{
GRADER,
GRADESTEP2,
GRADESTEP3,
GRADESTEP4,
GRADESTEP5,
LOGICANALYZER
};
// ************TExaS_Init*****************
// Initialize grader, triggered by periodic timer
// This needs to be called once
// Inputs: Grading or Logic analyzer
// 4-digit number from edX
// Outputs: none
void TExaS_Init(enum TExaSmode mode, uint32_t edXcode);
// ************TExaS_Stop*****************
// Stop the transfer
// Inputs: none
// Outputs: none
void TExaS_Stop(void);
// record time Task 0 is started
void TExaS_Task0(void);
// record time Task 0 is started
void TExaS_Task1(void);
// record time Task 2 is started
void TExaS_Task2(void);
// record time Task 3 is started
void TExaS_Task3(void);
// record time Task 4 is started
void TExaS_Task4(void);
// record time Task 5 is started
void TExaS_Task5(void);
// record time Task 6 is started
void TExaS_Task6(void);

215
Lab3_4C123/os.c Normal file
View File

@ -0,0 +1,215 @@
// os.c
// Runs on LM4F120/TM4C123/MSP432
// Lab 3 starter file.
// Daniel Valvano
// March 24, 2016
#include <stdint.h>
#include "os.h"
#include "CortexM.h"
#include "BSP.h"
// function definitions in osasm.s
void StartOS(void);
#define NUMTHREADS 6 // maximum number of threads
#define NUMPERIODIC 2 // maximum number of periodic threads
#define STACKSIZE 100 // number of 32-bit words in stack per thread
struct tcb{
int32_t *sp; // pointer to stack (valid for threads not running
struct tcb *next; // linked-list pointer
// nonzero if blocked on this semaphore
// nonzero if this thread is sleeping
//*FILL THIS IN****
};
typedef struct tcb tcbType;
tcbType tcbs[NUMTHREADS];
tcbType *RunPt;
int32_t Stacks[NUMTHREADS][STACKSIZE];
// ******** OS_Init ************
// Initialize operating system, disable interrupts
// Initialize OS controlled I/O: periodic interrupt, bus clock as fast as possible
// Initialize OS global variables
// Inputs: none
// Outputs: none
void OS_Init(void){
DisableInterrupts();
BSP_Clock_InitFastest();// set processor clock to fastest speed
// perform any initializations needed
}
void SetInitialStack(int i){
// **Same as Lab 2****
tcbs[i].sp = &Stacks[i][STACKSIZE - 16];
Stacks[i][STACKSIZE-1] = 0x01000000; // Thumb bit
//Stacks[i][STACKSIZE-2] is reserved for PC
//and is initialized with start address of task
Stacks[i][STACKSIZE-3] = 0x14141414; // R14 = LR
Stacks[i][STACKSIZE-4] = 0x12121212; // R12
Stacks[i][STACKSIZE-5] = 0x03030303; // R3
Stacks[i][STACKSIZE-6] = 0x02020202; // R2
Stacks[i][STACKSIZE-7] = 0x01010101; // R1
Stacks[i][STACKSIZE-8] = 0x00000000; // R0
Stacks[i][STACKSIZE-9] = 0x11111111; // R11
Stacks[i][STACKSIZE-10] = 0x10101010; // R10
Stacks[i][STACKSIZE-11] = 0x09090909; // R9
Stacks[i][STACKSIZE-12] = 0x08080808; // R8
Stacks[i][STACKSIZE-13] = 0x07070707; // R7
Stacks[i][STACKSIZE-14] = 0x06060606; // R6
Stacks[i][STACKSIZE-15] = 0x05050505; // R5
Stacks[i][STACKSIZE-16] = 0x04040404; // R4
}
//******** OS_AddThreads ***************
// Add six main threads to the scheduler
// Inputs: function pointers to six void/void main threads
// Outputs: 1 if successful, 0 if this thread can not be added
// This function will only be called once, after OS_Init and before OS_Launch
int OS_AddThreads(void(*thread0)(void),
void(*thread1)(void),
void(*thread2)(void),
void(*thread3)(void),
void(*thread4)(void),
void(*thread5)(void)){
// **similar to Lab 2. initialize as not blocked, not sleeping****
return 1; // successful
}
//******** OS_AddPeriodicEventThread ***************
// Add one background periodic event thread
// Typically this function receives the highest priority
// Inputs: pointer to a void/void event thread function
// period given in units of OS_Launch (Lab 3 this will be msec)
// Outputs: 1 if successful, 0 if this thread cannot be added
// It is assumed that the event threads will run to completion and return
// It is assumed the time to run these event threads is short compared to 1 msec
// These threads cannot spin, block, loop, sleep, or kill
// These threads can call OS_Signal
// In Lab 3 this will be called exactly twice
int OS_AddPeriodicEventThread(void(*thread)(void), uint32_t period){
// ****IMPLEMENT THIS****
return 1;
}
void static runperiodicevents(void){
// ****IMPLEMENT THIS****
// **RUN PERIODIC THREADS, DECREMENT SLEEP COUNTERS
}
//******** OS_Launch ***************
// Start the scheduler, enable interrupts
// Inputs: number of clock cycles for each time slice
// Outputs: none (does not return)
// Errors: theTimeSlice must be less than 16,777,216
void OS_Launch(uint32_t theTimeSlice){
STCTRL = 0; // disable SysTick during setup
STCURRENT = 0; // any write to current clears it
SYSPRI3 =(SYSPRI3&0x00FFFFFF)|0xE0000000; // priority 7
STRELOAD = theTimeSlice - 1; // reload value
STCTRL = 0x00000007; // enable, core clock and interrupt arm
StartOS(); // start on the first task
}
// runs every ms
void Scheduler(void){ // every time slice
// ROUND ROBIN, skip blocked and sleeping threads
}
//******** OS_Suspend ***************
// Called by main thread to cooperatively suspend operation
// Inputs: none
// Outputs: none
// Will be run again depending on sleep/block status
void OS_Suspend(void){
STCURRENT = 0; // any write to current clears it
INTCTRL = 0x04000000; // trigger SysTick
// next thread gets a full time slice
}
// ******** OS_Sleep ************
// place this thread into a dormant state
// input: number of msec to sleep
// output: none
// OS_Sleep(0) implements cooperative multitasking
void OS_Sleep(uint32_t sleepTime){
// set sleep parameter in TCB
// suspend, stops running
}
// ******** OS_InitSemaphore ************
// Initialize counting semaphore
// Inputs: pointer to a semaphore
// initial value of semaphore
// Outputs: none
void OS_InitSemaphore(int32_t *semaPt, int32_t value){
//***IMPLEMENT THIS***
}
// ******** OS_Wait ************
// Decrement semaphore and block if less than zero
// Lab2 spinlock (does not suspend while spinning)
// Lab3 block if less than zero
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Wait(int32_t *semaPt){
//***IMPLEMENT THIS***
}
// ******** OS_Signal ************
// Increment semaphore
// Lab2 spinlock
// Lab3 wakeup blocked thread if appropriate
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Signal(int32_t *semaPt){
//***IMPLEMENT THIS***
}
#define FSIZE 10 // can be any size
uint32_t PutI; // index of where to put next
uint32_t GetI; // index of where to get next
uint32_t Fifo[FSIZE];
int32_t CurrentSize;// 0 means FIFO empty, FSIZE means full
uint32_t LostData; // number of lost pieces of data
// ******** OS_FIFO_Init ************
// Initialize FIFO.
// One event thread producer, one main thread consumer
// Inputs: none
// Outputs: none
void OS_FIFO_Init(void){
//***IMPLEMENT THIS***
}
// ******** OS_FIFO_Put ************
// Put an entry in the FIFO.
// Exactly one event thread puts,
// do not block or spin if full
// Inputs: data to be stored
// Outputs: 0 if successful, -1 if the FIFO is full
int OS_FIFO_Put(uint32_t data){
//***IMPLEMENT THIS***
return 0; // success
}
// ******** OS_FIFO_Get ************
// Get an entry from the FIFO.
// Exactly one main thread get,
// do block if empty
// Inputs: none
// Outputs: data retrieved
uint32_t OS_FIFO_Get(void){uint32_t data;
//***IMPLEMENT THIS***
return data;
}

132
Lab3_4C123/os.h Normal file
View File

@ -0,0 +1,132 @@
// os.h
// Runs on LM4F120/TM4C123/MSP432
// A very simple real time operating system with minimal features.
// Daniel Valvano
// March 24, 2016
/* This example accompanies the book
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, , Jonathan Valvano, copyright (c) 2016
Programs 4.4 through 4.12, section 4.2
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
#ifndef __OS_H
#define __OS_H 1
// ******** OS_Init ************
// Initialize operating system, disable interrupts
// Initialize OS controlled I/O: periodic interrupt, bus clock as fast as possible
// Initialize OS global variables
// Inputs: none
// Outputs: none
void OS_Init(void);
//******** OS_AddThreads ***************
// Add six main threads to the scheduler
// Inputs: function pointers to six void/void main threads
// Outputs: 1 if successful, 0 if this thread can not be added
// This function will only be called once, after OS_Init and before OS_Launch
int OS_AddThreads(void(*thread0)(void),
void(*thread1)(void),
void(*thread2)(void),
void(*thread3)(void),
void(*thread4)(void),
void(*thread5)(void));
//******** OS_AddPeriodicEventThread ***************
// Add one background periodic event thread
// Typically this function receives the highest priority
// Inputs: pointer to a void/void event thread function
// period given in units of OS_Launch (Lab 3 this will be msec)
// Outputs: 1 if successful, 0 if this thread cannot be added
// It is assumed that the event threads will run to completion and return
// It is assumed the time to run these event threads is short compared to 1 msec
// These threads cannot spin, block, loop, sleep, or kill
// These threads can call OS_Signal
// In Lab 3 this will be called exactly twice
int OS_AddPeriodicEventThread(void(*thread)(void), uint32_t period);
//******** OS_Launch ***************
// Start the scheduler, enable interrupts
// Inputs: number of clock cycles for each time slice
// Outputs: none (does not return)
// Errors: theTimeSlice must be less than 16,777,216
void OS_Launch(uint32_t theTimeSlice);
//******** OS_Suspend ***************
// Called by main thread to cooperatively suspend operation
// Inputs: none
// Outputs: none
// Will be run again depending on sleep/block status
void OS_Suspend(void);
// ******** OS_Sleep ************
// place this thread into a dormant state
// input: number of msec to sleep
// output: none
// OS_Sleep(0) implements cooperative multitasking
void OS_Sleep(uint32_t sleepTime);
// ******** OS_InitSemaphore ************
// Initialize counting semaphore
// Inputs: pointer to a semaphore
// initial value of semaphore
// Outputs: none
void OS_InitSemaphore(int32_t *semaPt, int32_t value);
// ******** OS_Wait ************
// Decrement semaphore and block if less than zero
// Lab2 spinlock (does not suspend while spinning)
// Lab3 block if less than zero
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Wait(int32_t *semaPt);
// ******** OS_Signal ************
// Increment semaphore
// Lab2 spinlock
// Lab3 wakeup blocked thread if appropriate
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Signal(int32_t *semaPt);
// ******** OS_FIFO_Init ************
// Initialize FIFO.
// One event thread producer, one main thread consumer
// Inputs: none
// Outputs: none
void OS_FIFO_Init(void);
// ******** OS_FIFO_Put ************
// Put an entry in the FIFO.
// Exactly one event thread puts,
// do not block or spin if full
// Inputs: data to be stored
// Outputs: 0 if successful, -1 if the FIFO is full
int OS_FIFO_Put(uint32_t data);
// ******** OS_FIFO_Get ************
// Get an entry from the FIFO.
// Exactly one main thread get,
// do block if empty
// Inputs: none
// Outputs: data retrieved
uint32_t OS_FIFO_Get(void);
#endif

34
Lab3_4C123/osasm.s Normal file
View File

@ -0,0 +1,34 @@
;/*****************************************************************************/
; OSasm.s: low-level OS commands, written in assembly */
; Runs on LM4F120/TM4C123/MSP432
; Lab 3 starter file
; March 2, 2016
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
EXTERN RunPt ; currently running thread
EXPORT StartOS
EXPORT SysTick_Handler
IMPORT Scheduler
SysTick_Handler ; 1) Saves R0-R3,R12,LR,PC,PSR
CPSID I ; 2) Prevent interrupt during switch
;YOU IMPLEMENT THIS (same as Lab 2)
CPSIE I ; 9) tasks run with interrupts enabled
BX LR ; 10) restore R0-R3,R12,LR,PC,PSR
StartOS
;YOU IMPLEMENT THIS (same as Lab 2)
CPSIE I ; Enable interrupts at processor level
BX LR ; start first thread
ALIGN
END

783
Lab4_Fitness_4C123/Lab4.c Normal file
View File

@ -0,0 +1,783 @@
// Lab4.c
// Runs on either MSP432 or TM4C123
// Starter project to Lab 4. Take sensor readings, process the data,
// and output the results. Specifically, this program will
// measure steps using the accelerometer, audio sound amplitude using
// the microphone, temperature using the TMP006, and light using the
// OPT3001.
// Daniel and Jonathan Valvano
// August 22, 2016
/* This example accompanies the books
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Introduction to the MSP432 Microcontroller",
ISBN: 978-1512185676, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Interfacing to the MSP432 Microcontroller",
ISBN: 978-1514676585, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
#include <stdint.h>
#include "BSP.h"
#include "Profile.h"
#include "Texas.h"
#include "CortexM.h"
#include "os.h"
uint32_t sqrt32(uint32_t s);
#define THREADFREQ 1000 // frequency in Hz of round robin scheduler
//---------------- Global variables shared between tasks ----------------
uint32_t Time; // elasped time in 100 ms units
uint32_t Steps; // number of steps counted
uint32_t Magnitude; // will not overflow (3*1,023^2 = 3,139,587)
// Exponentially Weighted Moving Average
uint32_t EWMA; // https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
uint16_t SoundData; // raw data sampled from the microphone
int32_t SoundAvg;
uint32_t SoundRMS; // Root Mean Square average of most recent sound samples
uint32_t LightData; // 100 lux
int32_t TemperatureData; // 0.1C
// semaphores
int32_t NewData; // true when new numbers to display on top of LCD
int32_t LCDmutex; // exclusive access to LCD
int32_t I2Cmutex; // exclusive access to I2C
int ReDrawAxes = 0; // non-zero means redraw axes on next display task
enum plotstate{
Accelerometer,
Microphone,
Temperature,
Light
};
enum plotstate PlotState = Accelerometer;
//color constants
#define BGCOLOR LCD_BLACK
#define AXISCOLOR LCD_ORANGE
#define MAGCOLOR LCD_YELLOW
#define EWMACOLOR LCD_CYAN
#define SOUNDCOLOR LCD_CYAN
#define LIGHTCOLOR LCD_RED
#define TEMPCOLOR LCD_LIGHTGREEN
#define TOPTXTCOLOR LCD_WHITE
#define TOPNUMCOLOR LCD_ORANGE
//------------ end of Global variables shared between tasks -------------
//---------------- Task0 samples sound from microphone ----------------
// High priority thread run by OS in real time at 1000 Hz
#define SOUNDRMSLENGTH 1000 // number of samples to collect before calculating RMS (may overflow if greater than 4104)
int16_t SoundArray[SOUNDRMSLENGTH];
int32_t TakeSoundData; // binary semaphore
int32_t ADCmutex; // access to ADC
// *********Task0*********
// Task0 measures sound intensity
// Periodic main thread runs in real time at 1000 Hz
// collects data from microphone, high priority
// Inputs: none
// Outputs: none
void Task0(void){
static int32_t soundSum = 0;
static int time = 0;// units of microphone sampling rate
SoundRMS = 0;
while(1){
OS_Wait(&TakeSoundData); // signaled by OS every 1ms
TExaS_Task0(); // record system time in array, toggle virtual logic analyzer
Profile_Toggle0(); // viewed by the logic analyzer to know Task0 started
OS_Wait(&ADCmutex);
BSP_Microphone_Input(&SoundData);
OS_Signal(&ADCmutex);
soundSum = soundSum + (int32_t)SoundData;
SoundArray[time] = SoundData;
time = time + 1;
if(time == SOUNDRMSLENGTH){
SoundAvg = soundSum/SOUNDRMSLENGTH;
soundSum = 0;
OS_Signal(&NewData); // makes task5 run every 1 sec
time = 0;
}
}
}
/* ****************************************** */
/* End of Task0 Section */
/* ****************************************** */
//---------------- Task1 measures acceleration ----------------
// Event thread run by OS in real time at 10 Hz
int32_t TakeAccelerationData;
uint32_t LostTask1Data; // number of times that the FIFO was full when acceleration data was ready
uint16_t AccX, AccY, AccZ; // returned by BSP as 10-bit numbers
#define ALPHA 128 // The degree of weighting decrease, a constant smoothing factor between 0 and 1,023. A higher ALPHA discounts older observations faster.
// basic step counting algorithm is based on a forum post from
// http://stackoverflow.com/questions/16392142/android-accelerometer-profiling/16539643#16539643
enum state{ // the step counting algorithm cycles through four states
LookingForMax, // looking for a local maximum in current magnitude
LookingForCross1, // looking for current magnitude to cross average magnitude, minus a constant
LookingForMin, // looking for a local minimum in current magnitude
LookingForCross2 // looking for current magnitude to cross average magnitude, plus a constant
};
enum state AlgorithmState = LookingForMax;
#define LOCALCOUNTTARGET 5 // The number of valid measured magnitudes needed to confirm a local min or local max. Increase this number for longer strides or more frequent measurements.
#define AVGOVERSHOOT 25 // The amount above or below average a measurement must be to count as "crossing" the average. Increase this number to reject increasingly hard shaking as steps.
// *********Task1*********
// Task1 collects data from accelerometer in real time
// Periodic main thread runs in real time at 10 Hz
// Inputs: none
// Outputs: none
void Task1(void){uint32_t squared;
// initialize the exponential weighted moving average filter
BSP_Accelerometer_Input(&AccX, &AccY, &AccZ);
Magnitude = sqrt32(AccX*AccX + AccY*AccY + AccZ*AccZ);
EWMA = Magnitude; // this is a guess; there are many options
Steps = 0;
LostTask1Data = 0;
while(1){
OS_Wait(&TakeAccelerationData); // signaled by OS every 100ms
TExaS_Task1(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle1(); // viewed by the logic analyzer to know Task1 started
OS_Wait(&ADCmutex);
BSP_Accelerometer_Input(&AccX, &AccY, &AccZ);
OS_Signal(&ADCmutex);
squared = AccX*AccX + AccY*AccY + AccZ*AccZ;
if(OS_FIFO_Put(squared) == -1){ // makes Task2 run every 100ms
LostTask1Data = LostTask1Data + 1;
}
Time++; // in 100ms units
}
}
/* ****************************************** */
/* End of Task1 Section */
/* ****************************************** */
//---------------- Task2 calculates steps and plots data on LCD ----------------
// Main thread scheduled by OS round robin preemptive scheduler
// accepts data from accelerometer, calculates steps, plots on LCD
// If no data are lost, the main loop in Task2 runs exactly at 10 Hz, but not in real time
#define ACCELERATION_MAX 1400
#define ACCELERATION_MIN 600
#define SOUND_MAX 900
#define SOUND_MIN 300
#define LIGHT_MAX 2000
#define LIGHT_MIN 0
#define TEMP_MAX 1023
#define TEMP_MIN 0
void drawaxes(void){
OS_Wait(&LCDmutex);
if(PlotState == Accelerometer){
BSP_LCD_Drawaxes(AXISCOLOR, BGCOLOR, "Time", "Mag", MAGCOLOR, "Ave", EWMACOLOR, ACCELERATION_MAX, ACCELERATION_MIN);
} else if(PlotState == Microphone){
BSP_LCD_Drawaxes(AXISCOLOR, BGCOLOR, "Time", "Sound", SOUNDCOLOR, "", 0, SoundData+100, SoundData-100);
} else if(PlotState == Temperature){
BSP_LCD_Drawaxes(AXISCOLOR, BGCOLOR, "Time", "Temp", TEMPCOLOR, "", 0, TEMP_MAX, TEMP_MIN);
} else if(PlotState == Light){
BSP_LCD_Drawaxes(AXISCOLOR, BGCOLOR, "Time", "Light", LIGHTCOLOR, "", 0, LIGHT_MAX, LIGHT_MIN);
}
OS_Signal(&LCDmutex); ReDrawAxes = 0;
}
void Task2(void){uint32_t data;
uint32_t localMin; // smallest measured magnitude since odd-numbered step detected
uint32_t localMax; // largest measured magnitude since even-numbered step detected
uint32_t localCount; // number of measured magnitudes above local min or below local max
localMin = 1024;
localMax = 0;
localCount = 0;
drawaxes();
while(1){
data = OS_FIFO_Get();
TExaS_Task2(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle2(); // viewed by the logic analyzer to know Task2 started
Magnitude = sqrt32(data);
EWMA = (ALPHA*Magnitude + (1023 - ALPHA)*EWMA)/1024;
if(AlgorithmState == LookingForMax){
if(Magnitude > localMax){
localMax = Magnitude;
localCount = 0;
} else{
localCount = localCount + 1;
if(localCount >= LOCALCOUNTTARGET){
AlgorithmState = LookingForCross1;
}
}
} else if(AlgorithmState == LookingForCross1){
if(Magnitude > localMax){
// somehow measured a very large magnitude
localMax = Magnitude;
localCount = 0;
AlgorithmState = LookingForMax;
} else if(Magnitude < (EWMA - AVGOVERSHOOT)){
// step detected
Steps = Steps + 1;
localMin = 1024;
localCount = 0;
AlgorithmState = LookingForMin;
}
} else if(AlgorithmState == LookingForMin){
if(Magnitude < localMin){
localMin = Magnitude;
localCount = 0;
} else{
localCount = localCount + 1;
if(localCount >= LOCALCOUNTTARGET){
AlgorithmState = LookingForCross2;
}
}
} else if(AlgorithmState == LookingForCross2){
if(Magnitude < localMin){
// somehow measured a very small magnitude
localMin = Magnitude;
localCount = 0;
AlgorithmState = LookingForMin;
} else if(Magnitude > (EWMA + AVGOVERSHOOT)){
// step detected
Steps = Steps + 1;
localMax = 0;
localCount = 0;
AlgorithmState = LookingForMax;
}
}
if(ReDrawAxes){
drawaxes();
ReDrawAxes = 0;
}
OS_Wait(&LCDmutex);
if(PlotState == Accelerometer){
BSP_LCD_PlotPoint(Magnitude, MAGCOLOR);
BSP_LCD_PlotPoint(EWMA, EWMACOLOR);
} else if(PlotState == Microphone){
BSP_LCD_PlotPoint(SoundData, SOUNDCOLOR);
} else if(PlotState == Temperature){
BSP_LCD_PlotPoint(TemperatureData, TEMPCOLOR);
} else if(PlotState == Light){
BSP_LCD_PlotPoint(LightData, LIGHTCOLOR);
}
BSP_LCD_PlotIncrement();
OS_Signal(&LCDmutex);
}
}
/* ****************************************** */
/* End of Task2 Section */
/* ****************************************** */
//------------Task3 handles switch input, buzzer output-------
// *********Task3*********
// Main thread scheduled by OS round robin preemptive scheduler
// real-time task, signaled on touch
// with bouncing, may also be called on release
// checks the switches, updates the mode, and outputs to the buzzer and LED
// Inputs: none
// Outputs: none
int32_t SwitchTouch;
void Task3(void){
uint8_t current;
OS_InitSemaphore(&SwitchTouch,0); // signaled on touch button1
OS_EdgeTrigger_Init(&SwitchTouch, 3);
while(1){
OS_Wait(&SwitchTouch); // OS signals on touch
TExaS_Task3(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle3(); // viewed by the logic analyzer to know Task3 started
OS_Sleep(10); // debounce the switches
current = BSP_Button1_Input();
if(current == 0){ // Button1 was pressed
BSP_Buzzer_Set(512); // beep for 20ms
OS_Sleep(20);
BSP_Buzzer_Set(0);
if(PlotState == Accelerometer){
PlotState = Microphone;
} else if(PlotState == Microphone){
PlotState = Temperature;
} else if(PlotState == Temperature){
PlotState = Light;
} else if(PlotState == Light){
PlotState = Accelerometer;
}
ReDrawAxes = 1; // redraw axes on next call of display task
}
OS_EdgeTrigger_Restart();
}
}
/* ****************************************** */
/* End of Task3 Section */
/* ****************************************** */
//------------Task4 measures temperature-------
// *********Task4*********
// Main thread scheduled by OS round robin preemptive scheduler
// measures temperature
// Inputs: none
// Outputs: none
void Task4(void){int32_t voltData,tempData;
int done;
while(1){
TExaS_Task4(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle4(); // viewed by the logic analyzer to know Task4 started
OS_Wait(&I2Cmutex);
BSP_TempSensor_Start();
OS_Signal(&I2Cmutex);
done = 0;
OS_Sleep(1000); // waits about 1 sec
while(done == 0){
OS_Wait(&I2Cmutex);
done = BSP_TempSensor_End(&voltData, &tempData);
OS_Signal(&I2Cmutex);
}
TemperatureData = tempData/10000;
}
}
/* ****************************************** */
/* End of Task4 Section */
/* ****************************************** */
/* ------------------------------------------ */
//------- Task5 displays text on LCD -----------
/* ------------------------------------------ */
// If no data are lost, the main loop in Task5 runs exactly at 1 Hz, but not in real time
// *********Task5*********
// Main thread scheduled by OS round robin preemptive scheduler
// updates the text at the top and bottom of the LCD
// Inputs: none
// Outputs: none
void Task5(void){int32_t soundSum;
OS_Wait(&LCDmutex);
BSP_LCD_DrawString(0, 0, "Temp=", TOPTXTCOLOR);
BSP_LCD_DrawString(0, 1, "Step=", TOPTXTCOLOR);
BSP_LCD_DrawString(10, 0, "Light=", TOPTXTCOLOR);
BSP_LCD_DrawString(10, 1, "Sound=", TOPTXTCOLOR);
OS_Signal(&LCDmutex);
while(1){
OS_Wait(&NewData);
TExaS_Task5(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle5(); // viewed by the logic analyzer to know Task5 started
soundSum = 0;
for(int i=0; i<SOUNDRMSLENGTH; i=i+1){
soundSum = soundSum + (SoundArray[i] - SoundAvg)*(SoundArray[i] - SoundAvg);
}
SoundRMS = sqrt32(soundSum/SOUNDRMSLENGTH);
OS_Wait(&LCDmutex);
BSP_LCD_SetCursor(5, 0); BSP_LCD_OutUFix2_1(TemperatureData, TEMPCOLOR);
BSP_LCD_SetCursor(5, 1); BSP_LCD_OutUDec4(Steps, MAGCOLOR);
BSP_LCD_SetCursor(16, 0); BSP_LCD_OutUDec4(LightData, LIGHTCOLOR);
BSP_LCD_SetCursor(16, 1); BSP_LCD_OutUDec4(SoundRMS, SOUNDCOLOR);
BSP_LCD_SetCursor(16,12); BSP_LCD_OutUDec4(Time/10, TOPNUMCOLOR);
//debug code
if(LostTask1Data){
BSP_LCD_SetCursor(0, 12); BSP_LCD_OutUDec4(LostTask1Data, BSP_LCD_Color565(255, 0, 0));
}
//end of debug code
OS_Signal(&LCDmutex);
}
}
/* ****************************************** */
/* End of Task5 Section */
/* ****************************************** */
//---------------- Task6 measures light ----------------
// *********Task6*********
// Main thread scheduled by OS round robin preemptive scheduler
// Task6 measures light intensity
// Inputs: none
// Outputs: none
void Task6(void){ uint32_t lightData;
int done;
while(1){
TExaS_Task6(); // records system time in array, toggles virtual logic analyzer
Profile_Toggle6(); // viewed by the logic analyzer to know Task6 started
OS_Wait(&I2Cmutex);
BSP_LightSensor_Start();
OS_Signal(&I2Cmutex);
done = 0;
OS_Sleep(800); // waits about 0.8 sec
while(done == 0){
OS_Wait(&I2Cmutex);
done = BSP_LightSensor_End(&lightData);
OS_Signal(&I2Cmutex);
}
LightData = lightData/100;
}
}
/* ****************************************** */
/* End of Task6 Section */
/* ****************************************** */
//---------------- Task7 dummy function ----------------
// *********Task7*********
// Main thread scheduled by OS round robin preemptive scheduler
// Task7 does nothing but never blocks or sleeps
// Inputs: none
// Outputs: none
uint32_t Count7;
void Task7(void){
Count7 = 0;
while(1){
Count7++;
WaitForInterrupt();
}
}
/* ****************************************** */
/* End of Task7 Section */
/* ****************************************** */
//---------------- Step 6 ----------------
// Step 6 is to implement the fitness device by combining the
// OS functions that were implemented and tested in the earlier
// steps with the user tasks in this file. Completing this
// step will give you your grade, so remember to change the
// second parameter in TExaS_Init() to your 4-digit number.
// Task Purpose When to Run
// Task0 microphone periodically exactly every 1 ms
// Task1 accelerometer periodically exactly every 100 ms
// Task2 plot on LCD after Task1 finishes
// Task3 switch/buzzer whenever button 1 touched
// Task4 temperature periodically every 1 sec
// Task5 numbers on LCD after Task0 runs SOUNDRMSLENGTH times
// Task6 light periodically every 800 ms
// Task7 dummy no timing requirement
// Remember that you must have exactly one main() function, so
// to work on this step, you must rename all other main()
// functions in this file.
int main(void){
OS_Init();
Profile_Init(); // initialize the 7 hardware profiling pins
BSP_Button1_Init();
BSP_Button2_Init();
BSP_RGB_Init(0, 0, 0);
BSP_Buzzer_Init(0);
BSP_LCD_Init();
BSP_LCD_FillScreen(BSP_LCD_Color565(0, 0, 0));
BSP_LightSensor_Init();
BSP_TempSensor_Init();
Time = 0;
OS_InitSemaphore(&NewData, 0); // 0 means no data
OS_InitSemaphore(&LCDmutex, 1); // 1 means free
OS_InitSemaphore(&I2Cmutex, 1); // 1 means free
OS_InitSemaphore(&TakeSoundData,0);
OS_InitSemaphore(&ADCmutex,1);
BSP_Microphone_Init();
BSP_Accelerometer_Init();
OS_InitSemaphore(&TakeAccelerationData,0);
OS_FIFO_Init(); // initialize FIFO used to send data between Task1 and Task2
OS_AddThreads(&Task0,0, &Task1,1, &Task2,2, &Task3,3,
&Task4,3, &Task5,3, &Task6,3, &Task7,4);
OS_PeriodTrigger0_Init(&TakeSoundData,1); // every 1 ms
OS_PeriodTrigger1_Init(&TakeAccelerationData,100); //every 100ms
// when grading change 1000 to 4-digit number from edX
TExaS_Init(GRADER, 8864 ); // initialize the Lab 4 grader
// TExaS_Init(LOGICANALYZER, 1000); // initialize the Lab 4 logic analyzer
OS_Launch(BSP_Clock_GetFreq()/THREADFREQ); // doesn't return, interrupts enabled in here
return 0; // this never executes
}
/* ****************************************** */
/* End of Step 6 Section */
/* ****************************************** */
// Newton's method
// s is an integer
// sqrt(s) is an integer
uint32_t sqrt32(uint32_t s){
uint32_t t; // t*t will become s
int n; // loop counter
t = s/16+1; // initial guess
for(n = 16; n; --n){ // will finish
t = ((t*t+s)/t)/2;
}
return t;
}
//---------------- Step 1 ----------------
// Step 1 is to extend OS_AddThreads from Lab 4 to handle eight
// main threads, add a status field to the TCB, and rewrite
// the scheduler to handle priority.
// Task Type When to Run
// TaskA data producer periodically every 20 ms (sleep)
// TaskB data consumer after TaskA finishes
// TaskC data producer periodically every 50 ms (sleep)
// TaskD data consumer after TaskC finishes
// TaskE data producer periodically every 100 ms (sleep)
// TaskF data consumer after TaskE finishes
// TaskG low level task, runs a lot
// TaskH low level task, never runs
// Remember that you must have exactly one main() function, so
// to work on this step, you must rename all other main()
// functions in this file.
int32_t sAB,sCD,sEF;
int32_t CountA,CountB,CountC,CountD,CountE,CountF,CountG,CountH;
void TaskA(void){ // producer highest priority
CountA = 0;
while(1){
CountA++;
TExaS_Task0();
Profile_Toggle0();
OS_Signal(&sAB); // TaskB can proceed
OS_Sleep(20);
}
}
void TaskB(void){ // consumer
CountB = 0;
while(1){
CountB++;
OS_Wait(&sAB); // signaled by TaskA
TExaS_Task1();
Profile_Toggle1();
}
}
void TaskC(void){ // producer
CountC = 0;
while(1){
CountC++;
TExaS_Task2();
Profile_Toggle2();
OS_Signal(&sCD); // TaskD can proceed
OS_Sleep(50);
}
}
void TaskD(void){ // consumer
CountD = 0;
while(1){
CountD++;
OS_Wait(&sCD); // signaled by TaskC
TExaS_Task3();
Profile_Toggle3();
}
}
void TaskE(void){ // producer
CountE = 0;
while(1){
CountE++;
TExaS_Task4();
Profile_Toggle4();
OS_Signal(&sEF); // TaskF can proceed
OS_Sleep(100);
}
}
void TaskF(void){ // consumer
CountF = 0;
while(1){
CountF++;
OS_Wait(&sEF); // signaled by TaskE
TExaS_Task5();
Profile_Toggle5();
}
}
void TaskG(void){ // dummy
CountG = 0; // this should run a lot
while(1){
CountG++;
}
}
void TaskH(void){ // dummy
CountH = 0; // this one should never run
while(1){
CountH++;
}
}
int main_step1(void){
OS_Init();
Profile_Init(); // initialize the 7 hardware profiling pins
OS_InitSemaphore(&sAB, 0);
OS_InitSemaphore(&sCD, 0);
OS_InitSemaphore(&sEF, 0);
OS_AddThreads(&TaskA,0, &TaskB,1, &TaskC,2, &TaskD,3,
&TaskE,4, &TaskF,5, &TaskG,6, &TaskH,7);
TExaS_Init(LOGICANALYZER, 1000); // initialize the Lab 4 grader
// TExaS_Init(GRADESTEP1, 1000); // initialize the Lab 4 grader
OS_Launch(BSP_Clock_GetFreq()/1000);
return 0; // this never executes
}
/* ****************************************** */
/* End of Step 1 Section */
/* ****************************************** */
//---------------- Step 2 ----------------
// Step 2 id to extend the OS to implement OS_PeriodTrigger0_Init
// and OS_PeriodTrigger1_Init.
// Task Type When to Run
// TaskI data producer periodically every 20 ms(timer)
// TaskJ data consumer after TaskI finishes
// TaskK data producer periodically every 50 ms(timer)
// TaskL data consumer after TaskK finishes
// TaskM data producer periodically every 100 ms(sleep)
// TaskN data consumer after TaskL finishes
// TaskO low level task runs a lot
// TaskP low level (never runs)
// Remember that you must have exactly one main() function, so
// to work on this step, you must rename all other main()
// functions in this file.
int32_t sIJ,sKL,sMN;
int32_t sI,sK;
int32_t CountI,CountJ,CountK,CountL,CountM,CountN,CountO,CountP;
void TaskI(void){ // producer highest priority
CountI = 0;
while(1){
OS_Wait(&sI); // signaled by OS every 20ms
CountI++;
TExaS_Task0();
Profile_Toggle0();
OS_Signal(&sIJ); // TaskJ can proceed
}
}
void TaskJ(void){ // consumer
CountJ = 0;
while(1){
CountJ++;
OS_Wait(&sIJ); // signaled by TaskI
TExaS_Task1();
Profile_Toggle1();
}
}
void TaskK(void){ // producer
CountK = 0;
while(1){
OS_Wait(&sK); // signaled by OS every 50ms
CountK++;
TExaS_Task2();
Profile_Toggle2();
OS_Signal(&sKL); // TaskL can proceed
}
}
void TaskL(void){ // consumer
CountL = 0;
while(1){
CountL++;
OS_Wait(&sKL); // signaled by TaskL
TExaS_Task3();
Profile_Toggle3();
}
}
void TaskM(void){ // producer
CountM = 0;
while(1){
CountM++;
TExaS_Task4();
Profile_Toggle4();
OS_Signal(&sMN); // TaskN can proceed
OS_Sleep(100);
}
}
void TaskN(void){ // consumer
CountN = 0;
while(1){
CountN++;
OS_Wait(&sMN); // signaled by TaskM
TExaS_Task5();
Profile_Toggle5();
}
}
void TaskO(void){ // dummy
CountO = 0; // this should run a lot
while(1){
CountO++;
}
}
void TaskP(void){ // dummy
CountP = 0; // this one should never run
while(1){
CountP++;
}
}
int main_step2(void){
OS_Init();
Profile_Init(); // initialize the 7 hardware profiling pins
OS_InitSemaphore(&sI, 0);
OS_InitSemaphore(&sK, 0);
OS_InitSemaphore(&sIJ, 0);
OS_InitSemaphore(&sKL, 0);
OS_InitSemaphore(&sMN, 0);
OS_PeriodTrigger0_Init(&sI,20); // every 20 ms
OS_PeriodTrigger1_Init(&sK,50); // every 50ms
OS_AddThreads(&TaskI,0, &TaskJ,1, &TaskK,2, &TaskL,3,
&TaskM,4, &TaskN,5, &TaskO,6, &TaskP,7);
TExaS_Init(LOGICANALYZER, 1000); // initialize the Lab 4 grader
// TExaS_Init(GRADESTEP2, 1000); // initialize the Lab 4 grader
OS_Launch(BSP_Clock_GetFreq()/1000);
return 0; // this never executes
}
/* ****************************************** */
/* End of Step 2 Section */
/* ****************************************** */
//---------------- Step 3 ----------------
// Step 3 is to extend the OS to implement OS_EdgeTrigger_Init
// Task Type When to Run
// TaskI data producer periodically every 20 ms(timer)
// TaskJ data consumer after TaskI finishes
// TaskK data producer periodically every 50 ms(timer)
// TaskL data consumer after TaskK finishes
// TaskQ data producer runs on touch button1
// TaskR data consumer after TaskQ finishes
// TaskO low level task runs a lot
// TaskP low level (never runs)
// Remember that you must have exactly one main() function, so
// to work on this step, you must rename all other main()
// functions in this file.
int32_t sQR;
int32_t sQ;
int32_t CountQ,CountR;
void TaskQ(void){ // producer
CountQ = 0;
while(1){
OS_Wait(&sQ); // signaled in OS on button1 touch
CountQ++;
TExaS_Task4();
Profile_Toggle4();
OS_Signal(&sQR); // TaskQ can proceed
}
}
void TaskR(void){ // consumer
CountR = 0;
while(1){
OS_Wait(&sQR); // signaled by TaskQ
TExaS_Task5();
Profile_Toggle5();
CountR++;
OS_Sleep(10);
OS_EdgeTrigger_Restart();
}
}
int main_step3(void){
OS_Init();
Profile_Init(); // initialize the 7 hardware profiling pins
OS_InitSemaphore(&sI, 0);
OS_InitSemaphore(&sK, 0);
OS_InitSemaphore(&sQ, 0);
OS_InitSemaphore(&sIJ, 0);
OS_InitSemaphore(&sKL, 0);
OS_InitSemaphore(&sQR, 0);
OS_PeriodTrigger0_Init(&sI,50); // every 50 ms
OS_PeriodTrigger1_Init(&sK,200); // every 200ms
OS_EdgeTrigger_Init(&sQ,2);
OS_AddThreads(&TaskI,0, &TaskJ,1, &TaskK,2, &TaskL,3,
&TaskQ,4, &TaskR,5, &TaskO,6, &TaskP,7);
TExaS_Init(LOGICANALYZER, 1000); // initialize the Lab 4 grader
// TExaS_Init(GRADESTEP3, 1000); // initialize the Lab 4 grader
OS_Launch(BSP_Clock_GetFreq()/1000);
return 0; // this never executes
}
/* ****************************************** */
/* End of Step 3 Section */
/* ****************************************** */

View File

@ -0,0 +1,69 @@
// *****************Texas.h**************
// grading engine for Lab 4
//
// Runs on TM4C123/MSP432
// Daniel and Jonathan Valvano
// August 22, 2016
/* This example accompanies the books
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
enum TExaSmode{
GRADER,
GRADESTEP1,
GRADESTEP2,
GRADESTEP3,
LOGICANALYZER
};
// ************TExaS_Init*****************
// Initialize grader, triggered by periodic timer
// This needs to be called once
// Inputs: Grading or Logic analyzer
// 4-digit number from edX
// Outputs: none
void TExaS_Init(enum TExaSmode mode, uint32_t edXcode);
// ************TExaS_Stop*****************
// Stop the transfer
// Inputs: none
// Outputs: none
void TExaS_Stop(void);
// record time Task 0 is started
void TExaS_Task0(void);
// record time Task 0 is started
void TExaS_Task1(void);
// record time Task 2 is started
void TExaS_Task2(void);
// record time Task 3 is started
void TExaS_Task3(void);
// record time Task 4 is started
void TExaS_Task4(void);
// record time Task 5 is started
void TExaS_Task5(void);
// record time Task 6 is started
void TExaS_Task6(void);

298
Lab4_Fitness_4C123/os.c Normal file
View File

@ -0,0 +1,298 @@
// os.c
// Runs on LM4F120/TM4C123/MSP432
// A priority/blocking real-time operating system
// Lab 4 starter file.
// Daniel Valvano
// March 25, 2016
// Hint: Copy solutions from Lab 3 into Lab 4
#include <stdint.h>
#include "os.h"
#include "CortexM.h"
#include "BSP.h"
#include "../inc/tm4c123gh6pm.h"
// function definitions in osasm.s
void StartOS(void);
#define NUMTHREADS 8 // maximum number of threads
#define NUMPERIODIC 2 // maximum number of periodic threads
#define STACKSIZE 100 // number of 32-bit words in stack per thread
struct tcb{
int32_t *sp; // pointer to stack (valid for threads not running
struct tcb *next; // linked-list pointer
//*FILL THIS IN****
};
typedef struct tcb tcbType;
tcbType tcbs[NUMTHREADS];
tcbType *RunPt;
int32_t Stacks[NUMTHREADS][STACKSIZE];
void static runperiodicevents(void);
// ******** OS_Init ************
// Initialize operating system, disable interrupts
// Initialize OS controlled I/O: periodic interrupt, bus clock as fast as possible
// Initialize OS global variables
// Inputs: none
// Outputs: none
void OS_Init(void){
DisableInterrupts();
BSP_Clock_InitFastest();// set processor clock to fastest speed
// perform any initializations needed,
// set up periodic timer to run runperiodicevents to implement sleeping
}
void SetInitialStack(int i){
// ****IMPLEMENT THIS****
// **Same as Lab 2 and Lab 3****
}
//******** OS_AddThreads ***************
// Add eight main threads to the scheduler
// Inputs: function pointers to eight void/void main threads
// priorites for each main thread (0 highest)
// Outputs: 1 if successful, 0 if this thread can not be added
// This function will only be called once, after OS_Init and before OS_Launch
int OS_AddThreads(void(*thread0)(void), uint32_t p0,
void(*thread1)(void), uint32_t p1,
void(*thread2)(void), uint32_t p2,
void(*thread3)(void), uint32_t p3,
void(*thread4)(void), uint32_t p4,
void(*thread5)(void), uint32_t p5,
void(*thread6)(void), uint32_t p6,
void(*thread7)(void), uint32_t p7){
// **similar to Lab 3. initialize priority field****
return 1; // successful
}
void static runperiodicevents(void){
// ****IMPLEMENT THIS****
// **DECREMENT SLEEP COUNTERS
// In Lab 4, handle periodic events in RealTimeEvents
}
//******** OS_Launch ***************
// Start the scheduler, enable interrupts
// Inputs: number of clock cycles for each time slice
// Outputs: none (does not return)
// Errors: theTimeSlice must be less than 16,777,216
void OS_Launch(uint32_t theTimeSlice){
STCTRL = 0; // disable SysTick during setup
STCURRENT = 0; // any write to current clears it
SYSPRI3 =(SYSPRI3&0x00FFFFFF)|0xE0000000; // priority 7
STRELOAD = theTimeSlice - 1; // reload value
STCTRL = 0x00000007; // enable, core clock and interrupt arm
StartOS(); // start on the first task
}
// runs every ms
void Scheduler(void){ // every time slice
// ****IMPLEMENT THIS****
// look at all threads in TCB list choose
// highest priority thread not blocked and not sleeping
// If there are multiple highest priority (not blocked, not sleeping) run these round robin
}
//******** OS_Suspend ***************
// Called by main thread to cooperatively suspend operation
// Inputs: none
// Outputs: none
// Will be run again depending on sleep/block status
void OS_Suspend(void){
STCURRENT = 0; // any write to current clears it
INTCTRL = 0x04000000; // trigger SysTick
// next thread gets a full time slice
}
// ******** OS_Sleep ************
// place this thread into a dormant state
// input: number of msec to sleep
// output: none
// OS_Sleep(0) implements cooperative multitasking
void OS_Sleep(uint32_t sleepTime){
// ****IMPLEMENT THIS****
// set sleep parameter in TCB, same as Lab 3
// suspend, stops running
}
// ******** OS_InitSemaphore ************
// Initialize counting semaphore
// Inputs: pointer to a semaphore
// initial value of semaphore
// Outputs: none
void OS_InitSemaphore(int32_t *semaPt, int32_t value){
// ****IMPLEMENT THIS****
// Same as Lab 3
}
// ******** OS_Wait ************
// Decrement semaphore and block if less than zero
// Lab2 spinlock (does not suspend while spinning)
// Lab3 block if less than zero
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Wait(int32_t *semaPt){
// ****IMPLEMENT THIS****
// Same as Lab 3
}
// ******** OS_Signal ************
// Increment semaphore
// Lab2 spinlock
// Lab3 wakeup blocked thread if appropriate
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Signal(int32_t *semaPt){
// ****IMPLEMENT THIS****
// Same as Lab 3
}
#define FSIZE 10 // can be any size
uint32_t PutI; // index of where to put next
uint32_t GetI; // index of where to get next
uint32_t Fifo[FSIZE];
int32_t CurrentSize;// 0 means FIFO empty, FSIZE means full
uint32_t LostData; // number of lost pieces of data
// ******** OS_FIFO_Init ************
// Initialize FIFO. The "put" and "get" indices initially
// are equal, which means that the FIFO is empty. Also
// initialize semaphores to track properties of the FIFO
// such as size and busy status for Put and Get operations,
// which is important if there are multiple data producers
// or multiple data consumers.
// Inputs: none
// Outputs: none
void OS_FIFO_Init(void){
// ****IMPLEMENT THIS****
// Same as Lab 3
}
// ******** OS_FIFO_Put ************
// Put an entry in the FIFO. Consider using a unique
// semaphore to wait on busy status if more than one thread
// is putting data into the FIFO and there is a chance that
// this function may interrupt itself.
// Inputs: data to be stored
// Outputs: 0 if successful, -1 if the FIFO is full
int OS_FIFO_Put(uint32_t data){
// ****IMPLEMENT THIS****
// Same as Lab 3
return 0; // success
}
// ******** OS_FIFO_Get ************
// Get an entry from the FIFO. Consider using a unique
// semaphore to wait on busy status if more than one thread
// is getting data from the FIFO and there is a chance that
// this function may interrupt itself.
// Inputs: none
// Outputs: data retrieved
uint32_t OS_FIFO_Get(void){uint32_t data;
// ****IMPLEMENT THIS****
// Same as Lab 3
return data;
}
// *****periodic events****************
int32_t *PeriodicSemaphore0;
uint32_t Period0; // time between signals
int32_t *PeriodicSemaphore1;
uint32_t Period1; // time between signals
void RealTimeEvents(void){int flag=0;
static int32_t realCount = -10; // let all the threads execute once
// Note to students: we had to let the system run for a time so all user threads ran at least one
// before signalling the periodic tasks
realCount++;
if(realCount >= 0){
if((realCount%Period0)==0){
OS_Signal(PeriodicSemaphore0);
flag = 1;
}
if((realCount%Period1)==0){
OS_Signal(PeriodicSemaphore1);
flag=1;
}
if(flag){
OS_Suspend();
}
}
}
// ******** OS_PeriodTrigger0_Init ************
// Initialize periodic timer interrupt to signal
// Inputs: semaphore to signal
// period in ms
// priority level at 0 (highest
// Outputs: none
void OS_PeriodTrigger0_Init(int32_t *semaPt, uint32_t period){
PeriodicSemaphore0 = semaPt;
Period0 = period;
BSP_PeriodicTask_InitC(&RealTimeEvents,1000,0);
}
// ******** OS_PeriodTrigger1_Init ************
// Initialize periodic timer interrupt to signal
// Inputs: semaphore to signal
// period in ms
// priority level at 0 (highest
// Outputs: none
void OS_PeriodTrigger1_Init(int32_t *semaPt, uint32_t period){
PeriodicSemaphore1 = semaPt;
Period1 = period;
BSP_PeriodicTask_InitC(&RealTimeEvents,1000,0);
}
//****edge-triggered event************
int32_t *edgeSemaphore;
// ******** OS_EdgeTrigger_Init ************
// Initialize button1, PD6, to signal on a falling edge interrupt
// Inputs: semaphore to signal
// priority
// Outputs: none
void OS_EdgeTrigger_Init(int32_t *semaPt, uint8_t priority){
edgeSemaphore = semaPt;
//***IMPLEMENT THIS***
// 1) activate clock for Port D
// allow time for clock to stabilize
// 2) no need to unlock PD6
// 3) disable analog on PD6
// 4) configure PD6 as GPIO
// 5) make PD6 input
// 6) disable alt funct on PD6
// disable pull-up on PD6
// 7) enable digital I/O on PD6
// (d) PD6 is edge-sensitive
// PD6 is not both edges
// PD6 is falling edge event
// (e) clear PD6 flag
// (f) arm interrupt on PD6
// priority on Port D edge trigger is NVIC_PRI0_R 31 29
// enable is bit 3 in NVIC_EN0_R
}
// ******** OS_EdgeTrigger_Restart ************
// restart button1 to signal on a falling edge interrupt
// rearm interrupt
// Inputs: none
// Outputs: none
void OS_EdgeTrigger_Restart(void){
//***IMPLEMENT THIS***
// rearm interrupt 3 in NVIC
// clear flag6
}
void GPIOPortD_Handler(void){
//***IMPLEMENT THIS***
// step 1 acknowledge by clearing flag
// step 2 signal semaphore (no need to run scheduler)
// step 3 disarm interrupt to prevent bouncing to create multiple signals
}

159
Lab4_Fitness_4C123/os.h Normal file
View File

@ -0,0 +1,159 @@
// os.h
// Runs on LM4F120/TM4C123/MSP432
// A priority/blocking real-time operating system
// Daniel Valvano
// March 25, 2016
/* This example accompanies the book
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, , Jonathan Valvano, copyright (c) 2016
Programs 4.4 through 4.12, section 4.2
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
#ifndef __OS_H
#define __OS_H 1
// ******** OS_Init ************
// Initialize operating system, disable interrupts
// Initialize OS controlled I/O: periodic interrupt, bus clock as fast as possible
// Initialize OS global variables
// Inputs: none
// Outputs: none
void OS_Init(void);
//******** OS_AddThreads ***************
// Add eight main threads to the scheduler
// Inputs: function pointers to eight void/void main threads
// priorites for each main thread (0 highest)
// Outputs: 1 if successful, 0 if this thread can not be added
// This function will only be called once, after OS_Init and before OS_Launch
int OS_AddThreads(void(*thread0)(void), uint32_t p0,
void(*thread1)(void), uint32_t p1,
void(*thread2)(void), uint32_t p2,
void(*thread3)(void), uint32_t p3,
void(*thread4)(void), uint32_t p4,
void(*thread5)(void), uint32_t p5,
void(*thread6)(void), uint32_t p6,
void(*thread7)(void), uint32_t p7);
//******** OS_Launch ***************
// Start the scheduler, enable interrupts
// Inputs: number of clock cycles for each time slice
// Outputs: none (does not return)
// Errors: theTimeSlice must be less than 16,777,216
void OS_Launch(uint32_t theTimeSlice);
//******** OS_Suspend ***************
// Called by main thread to cooperatively suspend operation
// Inputs: none
// Outputs: none
// Will be run again depending on sleep/block status
void OS_Suspend(void);
// ******** OS_Sleep ************
// place this thread into a dormant state
// input: number of msec to sleep
// output: none
// OS_Sleep(0) implements cooperative multitasking
void OS_Sleep(uint32_t sleepTime);
// ******** OS_InitSemaphore ************
// Initialize counting semaphore
// Inputs: pointer to a semaphore
// initial value of semaphore
// Outputs: none
void OS_InitSemaphore(int32_t *semaPt, int32_t value);
// ******** OS_Wait ************
// Decrement semaphore and block if less than zero
// Lab2 spinlock (does not suspend while spinning)
// Lab3 block if less than zero
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Wait(int32_t *semaPt);
// ******** OS_Signal ************
// Increment semaphore
// Lab2 spinlock
// Lab3 wakeup blocked thread if appropriate
// Inputs: pointer to a counting semaphore
// Outputs: none
void OS_Signal(int32_t *semaPt);
// ******** OS_FIFO_Init ************
// Initialize FIFO. The "put" and "get" indices initially
// are equal, which means that the FIFO is empty. Also
// initialize semaphores to track properties of the FIFO
// such as size and busy status for Put and Get operations,
// which is important if there are multiple data producers
// or multiple data consumers.
// Inputs: none
// Outputs: none
void OS_FIFO_Init(void);
// ******** OS_FIFO_Put ************
// Put an entry in the FIFO. Consider using a unique
// semaphore to wait on busy status if more than one thread
// is putting data into the FIFO and there is a chance that
// this function may interrupt itself.
// Inputs: data to be stored
// Outputs: 0 if successful, -1 if the FIFO is full
int OS_FIFO_Put(uint32_t data);
// ******** OS_FIFO_Get ************
// Get an entry from the FIFO. Consider using a unique
// semaphore to wait on busy status if more than one thread
// is getting data from the FIFO and there is a chance that
// this function may interrupt itself.
// Inputs: none
// Outputs: data retrieved
uint32_t OS_FIFO_Get(void);
// ******** OS_PeriodTrigger0_Init ************
// Initialize periodic timer interrupt to signal
// Inputs: semaphore to signal
// period in ms
// priority level at 0 (highest)
// Outputs: none
void OS_PeriodTrigger0_Init(int32_t *semaPt, uint32_t period);
// ******** OS_PeriodTrigger1_Init ************
// Initialize periodic timer interrupt to signal
// Inputs: semaphore to signal
// period in ms
// priority level at 0 (highest)
// Outputs: none
void OS_PeriodTrigger1_Init(int32_t *semaPt, uint32_t period);
// ******** OS_EdgeTrigger_Init ************
// Initialize button1, PD6, to signal on a falling edge interrupt
// Inputs: semaphore to signal
// priority
// Outputs: none
void OS_EdgeTrigger_Init(int32_t *semaPt, uint8_t priority);
// ******** OS_EdgeTrigger_Restart ************
// restart button1 to signal on a falling edge interrupt
// rearm interrupt
// Inputs: none
// Outputs: none
void OS_EdgeTrigger_Restart(void);
#endif

View File

@ -0,0 +1,33 @@
;/*****************************************************************************/
; OSasm.s: low-level OS commands, written in assembly */
; Runs on LM4F120/TM4C123/MSP432
; Lab 4 starter file
; March 25, 2016
;
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
EXTERN RunPt ; currently running thread
EXPORT StartOS
EXPORT SysTick_Handler
IMPORT Scheduler
SysTick_Handler ; 1) Saves R0-R3,R12,LR,PC,PSR
CPSID I ; 2) Prevent interrupt during switch
;YOU IMPLEMENT THIS (same as Lab 3)
CPSIE I ; 9) tasks run with interrupts enabled
BX LR ; 10) restore R0-R3,R12,LR,PC,PSR
StartOS
;YOU IMPLEMENT THIS (same as Lab 3)
CPSIE I ; Enable interrupts at processor level
BX LR ; start first thread
ALIGN
END

208
Lab5_4C123/FlashProgram.c Normal file
View File

@ -0,0 +1,208 @@
// FlashProgram.c
// Runs on LM4F120/TM4C123
// Provide functions that initialize the flash memory, write
// 32-bit data to flash, write an array of 32-bit data to flash,
// and erase a 1 KB block.
// Daniel Valvano
// August 29, 2016
/* This example accompanies the book
"Embedded Systems: Real Time Interfacing to Arm Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
#include <stdint.h>
#include "FlashProgram.h"
#define FLASH_FMA_R (*((volatile uint32_t *)0x400FD000))
#define FLASH_FMA_OFFSET_MAX 0x0003FFFF // Address Offset max
#define FLASH_FMD_R (*((volatile uint32_t *)0x400FD004))
#define FLASH_FMC_R (*((volatile uint32_t *)0x400FD008))
#define FLASH_FMC_WRKEY 0xA4420000 // FLASH write key (KEY bit of FLASH_BOOTCFG_R set)
#define FLASH_FMC_WRKEY2 0x71D50000 // FLASH write key (KEY bit of FLASH_BOOTCFG_R cleared)
#define FLASH_FMC_MERASE 0x00000004 // Mass Erase Flash Memory
#define FLASH_FMC_ERASE 0x00000002 // Erase a Page of Flash Memory
#define FLASH_FMC_WRITE 0x00000001 // Write a Word into Flash Memory
#define FLASH_FMC2_R (*((volatile uint32_t *)0x400FD020))
#define FLASH_FMC2_WRBUF 0x00000001 // Buffered Flash Memory Write
#define FLASH_FWBN_R (*((volatile uint32_t *)0x400FD100))
#define FLASH_BOOTCFG_R (*((volatile uint32_t *)0x400FE1D0))
#define FLASH_BOOTCFG_KEY 0x00000010 // KEY Select
void DisableInterrupts(void); // Disable interrupts
void EnableInterrupts(void); // Enable interrupts
long StartCritical (void); // previous I bit, disable interrupts
void EndCritical(long sr); // restore I bit to previous value
void WaitForInterrupt(void); // low power mode
// Check if address offset is valid for write operation
// Writing addresses must be 4-byte aligned and within range
static int WriteAddrValid(uint32_t addr){
// check if address offset works for writing
// must be 4-byte aligned
return (((addr % 4) == 0) && (addr <= FLASH_FMA_OFFSET_MAX));
}
// Check if address offset is valid for mass writing operation
// Mass writing addresses must be 32-word (128-byte) aligned and within range
static int MassWriteAddrValid(uint32_t addr){
// check if address offset works for mass writing
// must be 32-word (128-byte) aligned
return (((addr % 128) == 0) && (addr <= FLASH_FMA_OFFSET_MAX));
}
// Check if address offset is valid for erase operation
// Erasing addresses must be 1 KB aligned and within range
static int EraseAddrValid(uint32_t addr){
// check if address offset works for erasing
// must be 1 KB aligned
return (((addr % 1024) == 0) && (addr <= FLASH_FMA_OFFSET_MAX));
}
//------------Flash_Init------------
// This function was critical to the write and erase
// operations of the flash memory on the LM3S811
// microcontroller. But newer processors work slightly
// differently, and for the TM4C123 the timing parameters
// for the flash and EEPROM memories are configured along
// with the PLL. This function prototype is preserved to
// try to make it easier to reuse program code between the
// LM3S811, TM4C123, and TM4C1294.
// Input: systemClockFreqMHz system clock frequency (units of MHz)
// Output: none
void Flash_Init(uint8_t systemClockFreqMHz){
// do nothing; flash and EEPROM memory configured in PLL_Init()
// if the processor is executing code out of flash memory,
// presumably everything is configured correctly
}
//------------Flash_Write------------
// Write 32-bit data to flash at given address.
// Input: addr 4-byte aligned flash memory address to write
// data 32-bit data
// Output: 'NOERROR' if successful, 'ERROR' if fail (defined in FlashProgram.h)
// Note: disables interrupts while writing
int Flash_Write(uint32_t addr, uint32_t data){
uint32_t flashkey;
if(WriteAddrValid(addr)){
DisableInterrupts(); // may be optional step
// wait for hardware idle
while(FLASH_FMC_R&(FLASH_FMC_WRITE|FLASH_FMC_ERASE|FLASH_FMC_MERASE)){
// to do later: return ERROR if this takes too long
// remember to re-enable interrupts
};
FLASH_FMD_R = data;
FLASH_FMA_R = addr;
if(FLASH_BOOTCFG_R&FLASH_BOOTCFG_KEY){ // by default, the key is 0xA442
flashkey = FLASH_FMC_WRKEY;
} else{ // otherwise, the key is 0x71D5
flashkey = FLASH_FMC_WRKEY2;
}
FLASH_FMC_R = (flashkey|FLASH_FMC_WRITE); // start writing
while(FLASH_FMC_R&FLASH_FMC_WRITE){
// to do later: return ERROR if this takes too long
// remember to re-enable interrupts
}; // wait for completion (~3 to 4 usec)
EnableInterrupts();
return NOERROR;
}
return ERROR;
}
//------------Flash_WriteArray------------
// Write an array of 32-bit data to flash starting at given address.
// Input: source pointer to array of 32-bit data
// addr 4-byte aligned flash memory address to start writing
// count number of 32-bit writes
// Output: number of successful writes; return value == count if completely successful
// Note: at 80 MHz, it takes 678 usec to write 10 words
// Note: disables interrupts while writing
int Flash_WriteArray(uint32_t *source, uint32_t addr, uint16_t count){
uint16_t successfulWrites = 0;
while((successfulWrites < count) && (Flash_Write(addr + 4*successfulWrites, source[successfulWrites]) == NOERROR)){
successfulWrites = successfulWrites + 1;
}
return successfulWrites;
}
//------------Flash_FastWrite------------
// Write an array of 32-bit data to flash starting at given address.
// This is twice as fast as Flash_WriteArray(), but the address has
// to be 128-byte aligned, and the count has to be <= 32.
// Input: source pointer to array of 32-bit data
// addr 128-byte aligned flash memory address to start writing
// count number of 32-bit writes (<=32)
// Output: number of successful writes; return value == count if completely successful
// Note: at 80 MHz, it takes 335 usec to write 10 words
// Note: disables interrupts while writing
int Flash_FastWrite(uint32_t *source, uint32_t addr, uint16_t count){
uint32_t flashkey;
uint32_t volatile *FLASH_FWBn_R = (uint32_t volatile*)0x400FD100;
int writes = 0;
if(MassWriteAddrValid(addr)){
DisableInterrupts(); // may be optional step
while(FLASH_FMC2_R&FLASH_FMC2_WRBUF){ // wait for hardware idle
// to do later: return ERROR if this takes too long
// remember to re-enable interrupts
};
while((writes < 32) && (writes < count)){
FLASH_FWBn_R[writes] = source[writes];
writes = writes + 1;
}
FLASH_FMA_R = addr;
if(FLASH_BOOTCFG_R&FLASH_BOOTCFG_KEY){ // by default, the key is 0xA442
flashkey = FLASH_FMC_WRKEY;
} else{ // otherwise, the key is 0x71D5
flashkey = FLASH_FMC_WRKEY2;
}
FLASH_FMC2_R = (flashkey|FLASH_FMC2_WRBUF); // start writing
while(FLASH_FMC2_R&FLASH_FMC2_WRBUF){
// to do later: return ERROR if this takes too long
// remember to re-enable interrupts
}; // wait for completion (~3 to 4 usec)
EnableInterrupts();
}
return writes;
}
//------------Flash_Erase------------
// Erase 1 KB block of flash.
// Input: addr 1-KB aligned flash memory address to erase
// Output: 'NOERROR' if successful, 'ERROR' if fail (defined in FlashProgram.h)
// Note: disables interrupts while erasing
int Flash_Erase(uint32_t addr){
uint32_t flashkey;
if(EraseAddrValid(addr)){
DisableInterrupts(); // may be optional step
// wait for hardware idle
while(FLASH_FMC_R&(FLASH_FMC_WRITE|FLASH_FMC_ERASE|FLASH_FMC_MERASE)){
// to do later: return ERROR if this takes too long
// remember to re-enable interrupts
};
FLASH_FMA_R = addr;
if(FLASH_BOOTCFG_R&FLASH_BOOTCFG_KEY){ // by default, the key is 0xA442
flashkey = FLASH_FMC_WRKEY;
} else{ // otherwise, the key is 0x71D5
flashkey = FLASH_FMC_WRKEY2;
}
FLASH_FMC_R = (flashkey|FLASH_FMC_ERASE); // start erasing 1 KB block
while(FLASH_FMC_R&FLASH_FMC_ERASE){
// to do later: return ERROR if this takes too long
// remember to re-enable interrupts
}; // wait for completion (~3 to 4 usec)
EnableInterrupts();
return NOERROR;
}
return ERROR;
}

78
Lab5_4C123/FlashProgram.h Normal file
View File

@ -0,0 +1,78 @@
// FlashProgram.h
// Runs on LM4F120/TM4C123
// Provide functions that initialize the flash memory, write
// 32-bit data to flash, write an array of 32-bit data to flash,
// and erase a 1 KB block.
// Daniel Valvano
// August 29, 2016
/* This example accompanies the book
"Embedded Systems: Real Time Interfacing to Arm Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
#define ERROR 1 // Value returned if failure
#define NOERROR 0 // Value returned if success
//------------Flash_Init------------
// This function was critical to the write and erase
// operations of the flash memory on the LM3S811
// microcontroller. But newer processors work slightly
// differently, and for the TM4C123 the timing parameters
// for the flash and EEPROM memories are configured along
// with the PLL. This function prototype is preserved to
// try to make it easier to reuse program code between the
// LM3S811, TM4C123, and TM4C1294.
// Input: systemClockFreqMHz system clock frequency (units of MHz)
// Output: none
void Flash_Init(uint8_t systemClockFreqMHz);
//------------Flash_Write------------
// Write 32-bit data to flash at given address.
// Input: addr 4-byte aligned flash memory address to write
// data 32-bit data
// Output: 'NOERROR' if successful, 'ERROR' if fail (defined in FlashProgram.h)
// Note: disables interrupts while writing
int Flash_Write(uint32_t addr, uint32_t data);
//------------Flash_WriteArray------------
// Write an array of 32-bit data to flash starting at given address.
// Input: source pointer to array of 32-bit data
// addr 4-byte aligned flash memory address to start writing
// count number of 32-bit writes
// Output: number of successful writes; return value == count if completely successful
// Note: at 80 MHz, it takes 678 usec to write 10 words
// Note: disables interrupts while writing
int Flash_WriteArray(uint32_t *source, uint32_t addr, uint16_t count);
//------------Flash_FastWrite------------
// Write an array of 32-bit data to flash starting at given address.
// This is twice as fast as Flash_WriteArray(), but the address has
// to be 128-byte aligned, and the count has to be <= 32.
// Input: source pointer to array of 32-bit data
// addr 128-byte aligned flash memory address to start writing
// count number of 32-bit writes (<=32)
// Output: number of successful writes; return value == count if completely successful
// Note: at 80 MHz, it takes 335 usec to write 10 words
// Note: disables interrupts while writing
int Flash_FastWrite(uint32_t *source, uint32_t addr, uint16_t count);
//------------Flash_Erase------------
// Erase 1 KB block of flash.
// Input: addr 1-KB aligned flash memory address to erase
// Output: 'NOERROR' if successful, 'ERROR' if fail (defined in FlashProgram.h)
// Note: disables interrupts while erasing
int Flash_Erase(uint32_t addr);

266
Lab5_4C123/Lab5.c Normal file
View File

@ -0,0 +1,266 @@
// Lab5.c
// Runs on either MSP432 or TM4C123
// Start project to Lab 5. High level test of the file
// system will initialize variables, store files, and access
// files.
// Daniel and Jonathan Valvano
// August 29, 2016
/* This example accompanies the books
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Introduction to the MSP432 Microcontroller",
ISBN: 978-1512185676, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Interfacing to the MSP432 Microcontroller",
ISBN: 978-1514676585, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
// J1 J3 J4 J2
// [ 1] [21] [40] [20]
// [ 2] [22] [39] [19]
// [ 3] [23] [38] [18]
// [ 4] [24] [37] [17]
// [ 5] [25] [36] [16]
// [ 6] [26] [35] [15]
// [ 7] [27] [34] [14]
// [ 8] [28] [33] [13]
// [ 9] [29] [32] [12]
// [10] [30] [31] [11]
// +3.3V connected to J1.1 (power)
// joystick horizontal (X) connected to J1.2 (analog)
// UART from BoosterPack to LaunchPad connected to J1.3 (UART)
// UART from LaunchPad to BoosterPack connected to J1.4 (UART)
// joystick Select button connected to J1.5 (digital)
// microphone connected to J1.6 (analog)
// LCD SPI clock connected to J1.7 (SPI)
// ambient light (OPT3001) interrupt connected to J1.8 (digital)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SCL connected to J1.9 (I2C)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SDA connected to J1.10 (I2C)
// temperature sensor (TMP006) interrupt connected to J2.11 (digital)
// nothing connected to J2.12 (SPI CS_Other)
// LCD SPI CS connected to J2.13 (SPI)
// nothing connected to J2.14 (SPI MISO)
// LCD SPI data connected to J2.15 (SPI)
// nothing connected to J2.16 (reset)
// LCD !RST connected to J2.17 (digital)
// nothing connected to J2.18 (SPI CS_Wireless)
// servo PWM connected to J2.19 (PWM)
// GND connected to J2.20 (ground)
// +5V connected to J3.21 (power)
// GND connected to J3.22 (ground)
// accelerometer X connected to J3.23 (analog)
// accelerometer Y connected to J3.24 (analog)
// accelerometer Z connected to J3.25 (analog)
// joystick vertical (Y) connected to J3.26 (analog)
// nothing connected to J3.27 (I2S WS)
// nothing connected to J3.28 (I2S SCLK)
// nothing connected to J3.29 (I2S SDout)
// nothing connected to J3.30 (I2S SDin)
// LCD RS connected to J4.31 (digital)
// user Button2 (bottom) connected to J4.32 (digital)
// user Button1 (top) connected to J4.33 (digital)
// gator hole switch connected to J4.34 (digital)
// nothing connected to J4.35
// nothing connected to J4.36
// RGB LED blue connected to J4.37 (PWM)
// RGB LED green connected to J4.38 (PWM)
// RGB LED red (jumper up) or LCD backlight (jumper down) connected to J4.39 (PWM)
// buzzer connected to J4.40 (PWM)
#include <stdint.h>
#include "../inc/BSP.h"
#include "../inc/CortexM.h"
#include "eDisk.h"
#include "../inc/Profile.h"
#include "Texas.h"
#include "eFile.h"
// normally this access would be poor style,
// but the access to internal data is used here for debugging
extern uint8_t Buff[512];
extern uint8_t Directory[256], FAT[256];
// Test function: Copy a NULL-terminated 'inString' into the
// 'Buff' global variable with a maximum of 512 characters.
// Uninitialized characters are set to 0xFF.
// Inputs: inString pointer to NULL-terminated character string
// Outputs: none
void testbuildbuff(char *inString){
uint32_t i = 0;
while((i < 512) && (inString[i] != 0)){
Buff[i] = inString[i];
i = i + 1;
}
while(i < 512){
Buff[i] = 0xFF; // fill the remainder of the buffer with 0xFF
i = i + 1;
}
}
// Test function: Draw a visual representation of the file
// system to the screen. It should resemble Figure 5.13.
// This function reads the contents of the flash memory, so
// first call OS_File_Flush() to synchronize.
// Inputs: index starting index of directory and FAT
// Outputs: none
#define COLORSIZE 9
#define LCD_GRAY 0xCE59 // 200, 200, 200
const uint16_t ColorArray[COLORSIZE] = {LCD_YELLOW, LCD_BLUE, LCD_GREEN, LCD_RED, LCD_CYAN, LCD_LIGHTGREEN, LCD_ORANGE, LCD_MAGENTA, LCD_WHITE};
// display 12 lines of the directory and FAT
// used for debugging
// Input: index is starting line number
// Output: none
void DisplayDirectory(uint8_t index){
uint16_t dirclr[256], fatclr[256];
volatile uint8_t *diraddr = (volatile uint8_t *)(EDISK_ADDR_MAX - 511); /* address of directory */
volatile uint8_t *fataddr = (volatile uint8_t *)(EDISK_ADDR_MAX - 255); /* address of FAT */
int i, j;
// set default color to gray
for(i=0; i<256; i=i+1){
dirclr[i] = LCD_GRAY;
fatclr[i] = LCD_GRAY;
}
// set color for each active file
for(i=0; i<255; i=i+1){
j = diraddr[i];
if(j != 255){
dirclr[i] = ColorArray[i%COLORSIZE];
}
while(j != 255){
fatclr[j] = ColorArray[i%COLORSIZE];
j = fataddr[j];
}
}
// clear the screen if necessary (very slow but helps with button bounce)
if((index + 11) > 255){
BSP_LCD_FillScreen(LCD_BLACK);
}
// print the column headers
BSP_LCD_DrawString(5, 0, "DIR", LCD_GRAY);
BSP_LCD_DrawString(15, 0, "FAT", LCD_GRAY);
// print the cloumns
i = 0;
while((i <= 11) && ((index + i) <= 255)){
BSP_LCD_SetCursor(0, i+1);
BSP_LCD_OutUDec4((uint32_t)(index + i), LCD_GRAY);
BSP_LCD_SetCursor(4, i+1);
BSP_LCD_OutUDec4((uint32_t)diraddr[index+i], dirclr[index+i]);
BSP_LCD_SetCursor(10, i+1);
BSP_LCD_OutUDec4((uint32_t)(index + i), LCD_GRAY);
BSP_LCD_SetCursor(14, i+1);
BSP_LCD_OutUDec4((uint32_t)fataddr[index+i], fatclr[index+i]);
i = i + 1;
}
}
int main(void){
uint8_t m, n, p; // file numbers
uint8_t index = 0; // row index
volatile int i;
DisableInterrupts();
BSP_Clock_InitFastest();
Profile_Init(); // initialize the 7 hardware profiling pins
eDisk_Init(0);
BSP_Button1_Init();
BSP_Button2_Init();
BSP_LCD_Init();
BSP_LCD_FillScreen(LCD_BLACK);
if(BSP_Button1_Input() == 0){ // run TExaS if Button1 is pressed
BSP_LCD_DrawString(0, 0, "Running TExaS grader", LCD_YELLOW);
// change 1000 to 4-digit number from edX
TExaS_Init(GRADER, 1000); // initialize the Lab 5 grader
// TExaS_Init(LOGICANALYZER, 1000);
// Logic analyzer will run, but the Lab 5 doesn't really use the logic analyzer
while(BSP_Button1_Input() == 0){};
BSP_LCD_DrawString(0, 0, " ", LCD_YELLOW);
}
if(BSP_Button2_Input() == 0){ // erase if Button2 is pressed
BSP_LCD_DrawString(0, 0, "Erasing entire disk", LCD_YELLOW);
OS_File_Format();
while(BSP_Button2_Input() == 0){};
BSP_LCD_DrawString(0, 0, " ", LCD_YELLOW);
}
EnableInterrupts();
n = OS_File_New(); // n = 0, 3, 6, 9, ...
testbuildbuff("buf0");
OS_File_Append(n, Buff); // 0x00020000
testbuildbuff("buf1");
OS_File_Append(n, Buff); // 0x00020200
testbuildbuff("buf2");
OS_File_Append(n, Buff); // 0x00020400
testbuildbuff("buf3");
OS_File_Append(n, Buff); // 0x00020600
testbuildbuff("buf4");
OS_File_Append(n, Buff); // 0x00020800
testbuildbuff("buf5");
OS_File_Append(n, Buff); // 0x00020A00
testbuildbuff("buf6");
OS_File_Append(n, Buff); // 0x00020C00
testbuildbuff("buf7");
OS_File_Append(n, Buff); // 0x00020E00
m = OS_File_New(); // m = 1, 4, 7, 10, ...
testbuildbuff("dat0");
OS_File_Append(m, Buff); // 0x00021000
testbuildbuff("dat1");
OS_File_Append(m, Buff); // 0x00021200
testbuildbuff("dat2");
OS_File_Append(m, Buff); // 0x00021400
testbuildbuff("dat3");
OS_File_Append(m, Buff); // 0x00021600
p = OS_File_New(); // p = 2, 5, 8, 11, ...
testbuildbuff("arr0");
OS_File_Append(p, Buff); // 0x00021800
testbuildbuff("arr1");
OS_File_Append(p, Buff); // 0x00021A00
testbuildbuff("buf8");
OS_File_Append(n, Buff); // 0x00021C00
testbuildbuff("buf9");
OS_File_Append(n, Buff); // 0x00021E00
testbuildbuff("arr2");
OS_File_Append(p, Buff); // 0x00022000
testbuildbuff("dat4");
OS_File_Append(m, Buff); // 0x00022200
i = OS_File_Size(n); // i = 10
i = OS_File_Size(m); // i = 5
i = OS_File_Size(p); // i = 3
i = OS_File_Size(p+1); // i = 0
OS_File_Flush(); // 0x0003FE00
while(1){
DisplayDirectory(index);
while((BSP_Button1_Input() != 0) && (BSP_Button2_Input() != 0)){};
if(BSP_Button1_Input() == 0){
if(index > 11){
index = index - 11;
} else{
index = 0;
}
}
if(BSP_Button2_Input() == 0){
if((index + 11) <= 255){
index = index + 11;
}
}
while((BSP_Button1_Input() == 0) || (BSP_Button2_Input() == 0)){};
}
}

125
Lab5_4C123/Texas.h Normal file
View File

@ -0,0 +1,125 @@
// *****************Texas.h**************
// grading engine for Lab 5
//
// Runs on either MSP432 or TM4C123
// Daniel and Jonathan Valvano
// May 19, 2016
/* This example accompanies the books
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
// J1 J3 J4 J2
// [ 1] [21] [40] [20]
// [ 2] [22] [39] [19]
// [ 3] [23] [38] [18]
// [ 4] [24] [37] [17]
// [ 5] [25] [36] [16]
// [ 6] [26] [35] [15]
// [ 7] [27] [34] [14]
// [ 8] [28] [33] [13]
// [ 9] [29] [32] [12]
// [10] [30] [31] [11]
// +3.3V connected to J1.1 (power)
// joystick horizontal (X) connected to J1.2 (analog)
// UART from BoosterPack to LaunchPad connected to J1.3 (UART)
// UART from LaunchPad to BoosterPack connected to J1.4 (UART)
// joystick Select button connected to J1.5 (digital)
// microphone connected to J1.6 (analog)
// LCD SPI clock connected to J1.7 (SPI)
// ambient light (OPT3001) interrupt connected to J1.8 (digital)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SCL connected to J1.9 (I2C)
// ambient light (OPT3001) and temperature sensor (TMP006) I2C SDA connected to J1.10 (I2C)
// temperature sensor (TMP006) interrupt connected to J2.11 (digital)
// nothing connected to J2.12 (SPI CS_Other)
// LCD SPI CS connected to J2.13 (SPI)
// nothing connected to J2.14 (SPI MISO)
// LCD SPI data connected to J2.15 (SPI)
// nothing connected to J2.16 (reset)
// LCD !RST connected to J2.17 (digital)
// nothing connected to J2.18 (SPI CS_Wireless)
// servo PWM connected to J2.19 (PWM)
// GND connected to J2.20 (ground)
// +5V connected to J3.21 (power)
// GND connected to J3.22 (ground)
// accelerometer X connected to J3.23 (analog)
// accelerometer Y connected to J3.24 (analog)
// accelerometer Z connected to J3.25 (analog)
// joystick vertical (Y) connected to J3.26 (analog)
// nothing connected to J3.27 (I2S WS)
// nothing connected to J3.28 (I2S SCLK)
// nothing connected to J3.29 (I2S SDout)
// nothing connected to J3.30 (I2S SDin)
// LCD RS connected to J4.31 (digital)
// user Button2 (bottom) connected to J4.32 (digital)
// user Button1 (top) connected to J4.33 (digital)
// gator hole switch connected to J4.34 (digital)
// nothing connected to J4.35
// nothing connected to J4.36
// RGB LED blue connected to J4.37 (PWM)
// RGB LED green connected to J4.38 (PWM)
// RGB LED red (jumper up) or LCD backlight (jumper down) connected to J4.39 (PWM)
// buzzer connected to J4.40 (PWM)
enum TExaSmode{
GRADER,
LOGICANALYZER
};
// ************TExaS_Init*****************
// Initialize grader, test low, middle, and high level
// functions, print the grade to the UART, and return.
// Inputs: Grading or Logic analyzer
// 4-digit number from edX
// Outputs: none
void TExaS_Init(enum TExaSmode mode, uint32_t edXcode);
// ************TExaS_Stop*****************
// Stop the transfer if in LOGICANALYZER mode. Unlike
// past labs, this grader completes its process in the
// initialization function, so this function has no
// effect if in GRADER mode.
// Inputs: none
// Outputs: none
void TExaS_Stop(void);
// ************TExaS_Task*****************
// Toggle the corresponding bit of the logic analyzer.
// When TExaS_Init() is called in LOGICANALYZER mode,
// these seven bits are sent through the UART at 10kHz.
// Unlike past labs, these functions are not graded,
// and this lab has no timing requirements.
// Inputs: none
// Outputs: none
void TExaS_Task0(void);
void TExaS_Task1(void);
void TExaS_Task2(void);
void TExaS_Task3(void);
void TExaS_Task4(void);
void TExaS_Task5(void);
void TExaS_Task6(void);

118
Lab5_4C123/eDisk.c Normal file
View File

@ -0,0 +1,118 @@
// eDisk.c
// Runs on TM4C123
// Mid-level implementation of the solid state disk device
// driver. Below this is the low level, hardware-specific
// flash memory interface. Above this is the high level
// file system implementation.
// Daniel and Jonathan Valvano
// August 29, 2016
/* This example accompanies the books
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Introduction to the MSP432 Microcontroller",
ISBN: 978-1512185676, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Interfacing to the MSP432 Microcontroller",
ISBN: 978-1514676585, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
#include <stdint.h>
#include "eDisk.h"
#include "FlashProgram.h"
//*************** eDisk_Init ***********
// Initialize the interface between microcontroller and disk
// Inputs: drive number (only drive 0 is supported)
// Outputs: status
// RES_OK 0: Successful
// RES_ERROR 1: Drive not initialized
enum DRESULT eDisk_Init(uint32_t drive){
// if drive is 0, return RES_OK, otherwise return RES_ERROR
// for some configurations the physical drive needs initialization
// however for the internal flash, no initialization is required
// so this function doesn't do anything
if(drive == 0){ // only drive 0 is supported
return RES_OK;
}
return RES_ERROR;
}
//*************** eDisk_ReadSector ***********
// Read 1 sector of 512 bytes from the disk, data goes to RAM
// Inputs: pointer to an empty RAM buffer
// sector number of disk to read: 0,1,2,...255
// Outputs: result
// RES_OK 0: Successful
// RES_ERROR 1: R/W Error
// RES_WRPRT 2: Write Protected
// RES_NOTRDY 3: Not Ready
// RES_PARERR 4: Invalid Parameter
enum DRESULT eDisk_ReadSector(
uint8_t *buff, // Pointer to a RAM buffer into which to store
uint8_t sector){ // sector number to read from
// starting ROM address of the sector is EDISK_ADDR_MIN + 512*sector
// return RES_PARERR if EDISK_ADDR_MIN + 512*sector > EDISK_ADDR_MAX
// copy 512 bytes from ROM (disk) into RAM (buff)
// **write this function**
return RES_OK;
}
//*************** eDisk_WriteSector ***********
// Write 1 sector of 512 bytes of data to the disk, data comes from RAM
// Inputs: pointer to RAM buffer with information
// sector number of disk to write: 0,1,2,...,255
// Outputs: result
// RES_OK 0: Successful
// RES_ERROR 1: R/W Error
// RES_WRPRT 2: Write Protected
// RES_NOTRDY 3: Not Ready
// RES_PARERR 4: Invalid Parameter
enum DRESULT eDisk_WriteSector(
const uint8_t *buff, // Pointer to the data to be written
uint8_t sector){ // sector number
// starting ROM address of the sector is EDISK_ADDR_MIN + 512*sector
// return RES_PARERR if EDISK_ADDR_MIN + 512*sector > EDISK_ADDR_MAX
// write 512 bytes from RAM (buff) into ROM (disk)
// you can use Flash_FastWrite or Flash_WriteArray
// **write this function**
return RES_OK;
}
//*************** eDisk_Format ***********
// Erase all files and all data by resetting the flash to all 1's
// Inputs: none
// Outputs: result
// RES_OK 0: Successful
// RES_ERROR 1: R/W Error
// RES_WRPRT 2: Write Protected
// RES_NOTRDY 3: Not Ready
// RES_PARERR 4: Invalid Parameter
enum DRESULT eDisk_Format(void){
// erase all flash from EDISK_ADDR_MIN to EDISK_ADDR_MAX
// **write this function**
return RES_OK;
}

91
Lab5_4C123/eDisk.h Normal file
View File

@ -0,0 +1,91 @@
// eDisk.h
// Runs on either MSP432 or TM4C123
// Mid-level implementation of the solid state disk device
// driver. Below this is the low level, hardware-specific
// flash memory interface. Above this is the high level
// file system implementation.
// Daniel and Jonathan Valvano
// August 29, 2016
/* This example accompanies the books
"Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
ISBN: 978-1466468863, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Introduction to the MSP432 Microcontroller",
ISBN: 978-1512185676, Jonathan Valvano, copyright (c) 2016
"Embedded Systems: Real-Time Interfacing to the MSP432 Microcontroller",
ISBN: 978-1514676585, Jonathan Valvano, copyright (c) 2016
Copyright 2016 by Jonathan W. Valvano, valvano@mail.utexas.edu
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
#define EDISK_ADDR_MIN 0x00020000 // Flash Bank1 minimum address
#define EDISK_ADDR_MAX 0x0003FFFF // Flash Bank1 maximum address
enum DRESULT{
RES_OK = 0, // Successful
RES_ERROR = 1, // R/W Error
RES_WRPRT = 2, // Write Protected
RES_NOTRDY = 3, // Not Ready
RES_PARERR = 4 // Invalid Parameter
};
//*************** eDisk_Init ***********
// Initialize the interface between microcontroller and disk
// Inputs: drive number (only drive 0 is supported)
// Outputs: status
// RES_OK 0: Successful
// RES_ERROR 1: Drive not initialized
enum DRESULT eDisk_Init(uint32_t drive);
//*************** eDisk_ReadSector ***********
// Read 1 sector of 512 bytes from the disk, data goes to RAM
// Inputs: pointer to an empty RAM buffer
// sector number of disk to read: 0,1,2,...255
// Outputs: result
// RES_OK 0: Successful
// RES_ERROR 1: R/W Error
// RES_WRPRT 2: Write Protected
// RES_NOTRDY 3: Not Ready
// RES_PARERR 4: Invalid Parameter
enum DRESULT eDisk_ReadSector(
uint8_t *buff, // Pointer to a RAM buffer into which to store
uint8_t sector); // sector number to read from
//*************** eDisk_WriteSector ***********
// Write 1 sector of 512 bytes of data to the disk, data comes from RAM
// Inputs: pointer to RAM buffer with information
// sector number of disk to write: 0,1,2,...,255
// Outputs: result
// RES_OK 0: Successful
// RES_ERROR 1: R/W Error
// RES_WRPRT 2: Write Protected
// RES_NOTRDY 3: Not Ready
// RES_PARERR 4: Invalid Parameter
enum DRESULT eDisk_WriteSector(
const uint8_t *buff, // Pointer to the data to be written
uint8_t sector); // sector number
//*************** eDisk_Format ***********
// Erase all files and all data by resetting the flash to all 1's
// Inputs: none
// Outputs: result
// RES_OK 0: Successful
// RES_ERROR 1: R/W Error
// RES_WRPRT 2: Write Protected
// RES_NOTRDY 3: Not Ready
// RES_PARERR 4: Invalid Parameter
enum DRESULT eDisk_Format(void);

141
Lab5_4C123/eFile.c Normal file
View File

@ -0,0 +1,141 @@
// eFile.c
// Runs on either TM4C123 or MSP432
// High-level implementation of the file system implementation.
// Daniel and Jonathan Valvano
// August 29, 2016
#include <stdint.h>
#include "eDisk.h"
uint8_t Buff[512]; // temporary buffer used during file I/O
uint8_t Directory[256], FAT[256];
int32_t bDirectoryLoaded =0; // 0 means disk on ROM is complete, 1 means RAM version active
// Return the larger of two integers.
int16_t max(int16_t a, int16_t b){
if(a > b){
return a;
}
return b;
}
//*****MountDirectory******
// if directory and FAT are not loaded in RAM,
// bring it into RAM from disk
void MountDirectory(void){
// if bDirectoryLoaded is 0,
// read disk sector 255 and populate Directory and FAT
// set bDirectoryLoaded=1
// if bDirectoryLoaded is 1, simply return
// **write this function**
}
// Return the index of the last sector in the file
// associated with a given starting sector.
// Note: This function will loop forever without returning
// if the file has no end (i.e. the FAT is corrupted).
uint8_t lastsector(uint8_t start){
// **write this function**
return 0; // replace this line
}
// Return the index of the first free sector.
// Note: This function will loop forever without returning
// if a file has no end or if (Directory[255] != 255)
// (i.e. the FAT is corrupted).
uint8_t findfreesector(void){
// **write this function**
return 0; // replace this line
}
// Append a sector index 'n' at the end of file 'num'.
// This helper function is part of OS_File_Append(), which
// should have already verified that there is free space,
// so it always returns 0 (successful).
// Note: This function will loop forever without returning
// if the file has no end (i.e. the FAT is corrupted).
uint8_t appendfat(uint8_t num, uint8_t n){
// **write this function**
return 0; // replace this line
}
//********OS_File_New*************
// Returns a file number of a new file for writing
// Inputs: none
// Outputs: number of a new file
// Errors: return 255 on failure or disk full
uint8_t OS_File_New(void){
// **write this function**
return 255;
}
//********OS_File_Size*************
// Check the size of this file
// Inputs: num, 8-bit file number, 0 to 254
// Outputs: 0 if empty, otherwise the number of sectors
// Errors: none
uint8_t OS_File_Size(uint8_t num){
// **write this function**
return 0; // replace this line
}
//********OS_File_Append*************
// Save 512 bytes into the file
// Inputs: num, 8-bit file number, 0 to 254
// buf, pointer to 512 bytes of data
// Outputs: 0 if successful
// Errors: 255 on failure or disk full
uint8_t OS_File_Append(uint8_t num, uint8_t buf[512]){
// **write this function**
return 0; // replace this line
}
//********OS_File_Read*************
// Read 512 bytes from the file
// Inputs: num, 8-bit file number, 0 to 254
// location, logical address, 0 to 254
// buf, pointer to 512 empty spaces in RAM
// Outputs: 0 if successful
// Errors: 255 on failure because no data
uint8_t OS_File_Read(uint8_t num, uint8_t location,
uint8_t buf[512]){
// **write this function**
return 0; // replace this line
}
//********OS_File_Flush*************
// Update working buffers onto the disk
// Power can be removed after calling flush
// Inputs: none
// Outputs: 0 if success
// Errors: 255 on disk write failure
uint8_t OS_File_Flush(void){
// **write this function**
return 0; // replace this line
}
//********OS_File_Format*************
// Erase all files and all data
// Inputs: none
// Outputs: 0 if success
// Errors: 255 on disk write failure
uint8_t OS_File_Format(void){
// call eDiskFormat
// clear bDirectoryLoaded to zero
// **write this function**
return 0; // replace this line
}

53
Lab5_4C123/eFile.h Normal file
View File

@ -0,0 +1,53 @@
// eFile.h
// Runs on either TM4C123 or MSP432
// High-level implementation of the file system implementation.
// Daniel and Jonathan Valvano
// August 29, 2016
//********OS_File_New*************
// Returns a file number of a new file for writing
// Inputs: none
// Outputs: number of a new file
// Errors: return 255 on failure or disk full
uint8_t OS_File_New(void);
//********OS_File_Size*************
// Check the size of this file
// Inputs: num, 8-bit file number, 0 to 254
// Outputs: 0 if empty, otherwise the number of sectors
// Errors: none
uint8_t OS_File_Size(uint8_t num);
//********OS_File_Append*************
// Save 512 bytes into the file
// Inputs: num, 8-bit file number, 0 to 254
// buf, pointer to 512 bytes of data
// Outputs: 0 if successful
// Errors: 255 on failure or disk full
uint8_t OS_File_Append(uint8_t num, uint8_t buf[512]);
//********OS_File_Read*************
// Read 512 bytes from the file
// Inputs: num, 8-bit file number, 0 to 254
// location, logical address, 0 to 254
// buf, pointer to 512 empty spaces in RAM
// Outputs: 0 if successful
// Errors: 255 on failure because no data
uint8_t OS_File_Read(uint8_t num, uint8_t location,
uint8_t buf[512]);
//********OS_File_Flush*************
// Update working buffers onto the disk
// Power can be removed after calling flush
// Inputs: none
// Outputs: 0 if success
// Errors: 255 on disk write failure
uint8_t OS_File_Flush(void);
//********OS_File_Format*************
// Erase all files and all data
// Inputs: none
// Outputs: 0 if success
// Errors: 255 on disk write failure
uint8_t OS_File_Format(void);