Program to control an accelerometer, motors and a rangefinder using the ScmRTOS ported to mbed. (Work in progress and buggy)
Revision 0:9b057566f9ee, committed 2010-11-01
- Comitter:
- jberry
- Date:
- Mon Nov 01 20:39:01 2010 +0000
- Commit message:
Changed in this revision
diff -r 000000000000 -r 9b057566f9ee Hexacopter/Command_handler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/Command_handler.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,91 @@ +#pragma once +#ifndef COMMAND_HANDLER_H +#define COMMAND_HANDLER_H +#include <messages.h> +#include <processes.h> + +//DigitalOut led2(LED2); +extern BusOut leds; +template<> OS_PROCESS void Command_handler::Exec() //serial stream handling process +{ + //led2 = 0; + char RX_Command[100] = ""; + RX_Command[99] = '\0'; + + for(;;) + { + + //RX_channel.pop(temp); + for(byte i = 0; i<100; i++) + { + RX_channel.pop(RX_Command[i]); + leds = 0x4; + if(i == 99) + { + RX_Command[i] = '\0'; + } + //pc.putc(RX_Command[i]); + if(RX_Command[i] == '\0') //keep popping chars until a delimiter is found + break; + } + //led2 = !led2; + TX_channel.write(RX_Command, strlen(RX_Command)+1); //output the command for debugging + TX_channel.push('\n'); + //char temp = 0; + //TX_channel.pop(temp); + //OUT->putc(temp); + //OUT->printf(RX_Command); + + if (strstr(RX_Command,"SER:") != NULL) //check for Serv: in the command - this will indicate that the command is destined for the servo process + { + SER_channel.write(RX_Command, strlen(RX_Command)+1); + //Servo_Command_Event.Signal(); + } + + else if (strstr(RX_Command,"PIN") != NULL) //check for PING in the command - this will indicate that the command is destined for the PING process + { + + PING_MESSAGE = 0; + PING_MESSAGE.send(); + } + + else if (strstr(RX_Command,"PIC") != NULL) //check for PING in the command - this will indicate that the command is destined for the PING process + { + + PING_MESSAGE = 1; + PING_MESSAGE.send(); + } + + else if (strstr(RX_Command, "MOT:") != NULL) //check to see if incoming motor control command + { + MOT_channel.write(RX_Command, strlen(RX_Command)+1); + + } + else if (strstr(RX_Command, "MO2:") != NULL) //this command will deal with both motors + { + MOT_channel.write(RX_Command, strlen(RX_Command)+1); + + } + + else if (strstr(RX_Command, "ACR") != NULL) //check to see if incoming motor control command + { //OS::message<byte> ACCELEROMETER_MESSAGE; //if message is a zero, then return acceleration once, if a 1 then continually return acceleration data + + ACCELEROMETER_MESSAGE = 1; + ACCELEROMETER_MESSAGE.send(); //send the message + + } + else if (strstr(RX_Command, "ACC") != NULL) //check to see if incoming motor control command + { //OS::message<byte> ACCELEROMETER_Message; //if message is a zero, then return acceleration once, if a 1 then continually return acceleration data + + ACCELEROMETER_MESSAGE = 0; + ACCELEROMETER_MESSAGE.send(); //send the message + + } + leds = 0x4; + } + +} + + +#endif +
diff -r 000000000000 -r 9b057566f9ee Hexacopter/Motor_control.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/Motor_control.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,224 @@ +#pragma once +#ifndef MOTOR_CONTROL_H +#define MOTOR_CONTROL_H +#include <cmath> +#include <processes.h> + + +//Motor_controller M_cont_process; +enum direction{CLOCKWISE,ANTICLOCKWISE}; + //PwmOut Out1(p23); //motor1 + //PwmOut Out2(p24); + //PwmOut Out3(p25); + //PwmOut Out4(p26); + +class motor_control +{ + public: + motor_control(PinName OUT1, PinName OUT2) + :Out1(OUT1),Out2(OUT2),Output(&Out1) + { + //Output = &Out1; + set_direction(CLOCKWISE); + SPEED = 0.0; + Out1.pulsewidth_ms(1); // pulsewidth should be 1ms + Out1.write(0.0); //set initial duty cycle to 0 (i.e. off) + Out2.write(0.0); //set initial duty cycle to 0 (i.e. off) + + + + + } + + void set_direction(direction D) + { + if( D == CLOCKWISE ) + { + *Output = 0; + Output = &Out2; + } + else + { + *Output = 0; + Output = &Out1; + } + DIR = D; + //set_speed(get_speed()); + } + + direction get_direction() + { + return DIR; + } + + void set_speed(float speed) + { + SPEED = speed; + if(speed >= -1 && speed < 0) + { + if(get_direction() == CLOCKWISE) //ALLOW SOME TIME for the motor to change direction + { + *Output = 0; + //wait_ms(500); + } + + set_direction(ANTICLOCKWISE); + *Output = speed; + } + else if(speed >= 0 && speed <= 1) + { + if(get_direction() == CLOCKWISE) //ALLOW SOME TIME for the motor to change direction + { + *Output = 0; + //wait_ms(500); + } + + set_direction(CLOCKWISE); + *Output = speed; + } + + } + float get_speed() + { + return SPEED; + } + + void speed_inc() + { + if( (get_speed() + 0.1) <= 1) + set_speed(SPEED + 0.1); + else if( get_speed() + 0.1 > 1) + set_speed(1); + } + + void speed_dec() + { + if( (get_speed() - 0.1) >= 0) + set_speed(SPEED - 0.1); + else if( get_speed() - 0.1 < 0) + set_speed(0); + + } + + void change_direction() + { + if (get_direction() == CLOCKWISE) + set_direction(ANTICLOCKWISE); + else + set_direction(CLOCKWISE); + } + + + private: + //int PIN1,PIN2; + direction DIR; + PwmOut Out1; + PwmOut Out2; + PwmOut* Output; + + + float SPEED; + + }; + + +char MOT_Return_chars[100]; //defined in accelerometer.h +char Motor_command[100] = ""; +byte Motor_number = 0; + +extern BusOut leds; +template<> OS_PROCESS void Motor_controller::Exec() //motor control handling process +{ + Motor_command[99] = '\0'; + motor_control Motor1(p23,p24); + motor_control Motor2(p25,p26); + motor_control *M = &Motor1; + float motor_percentage = -1, motor_direction = 0.5, motor_strength = 0; //motor direction is a float from 0-1 which indicates the relative strength of one motor to the other the strength is the PWM output of the strongest motor as dictated by direction + direction PREV_DIR = CLOCKWISE; + + + + + char* pEND, *pEND2; + +//MOT_channel + for (;;) + { + + //OS::message<byte> MOTOR_message; + for(byte i = 0; i<100; i++) + { + MOT_channel.pop(Motor_command[i]); //if data is available, pop, else wait + leds = 0x5; + if(Motor_command[i] == '\0') //keep popping chars until a delimiter is found + break; + else if(Motor_command[i] != '\0' && i == 99) + Motor_command[i] = '\0'; + + } + + //sprintf(MOT_Return_chars, "a command was received.\n"); + //TX_Channel.write(MOT_Return_chars, strlen(MOT_Return_chars)+1); //output the command for debugging + //TX_Channel.write(Motor_command, strlen(Motor_command) +1); + + //which motor? + //if (strlen(Servo_Command) >= 20 && strstr(Servo_Command,":Calibrate")) + if(strstr(Motor_command, "MOT:") != NULL) + { + Motor_number = strtod(1+strstr(Motor_command, ":"), &pEND); + // motor_percentage = -1; + + //sprintf(output_chars, "motor number is: %d\n", Motor_number); + //TX_Channel.write(output_chars, strlen(output_chars)+1); //output the command for debugging + + + if(Motor_number < 2) // valid conversion + { + if(Motor_number == 0) + M = &Motor1; + else + M = &Motor2; + motor_percentage = strtod(1+pEND, &pEND2); + //sprintf(output_chars, "percentage is: %f\n", motor_percentage); + //TX_Channel.write(output_chars, strlen(output_chars)+1); //output the command for debugging + M->set_speed(motor_percentage*(-1)); + } //end valid conversion check + } //end single MOT: command + + + else if(strstr(Motor_command, "MO2:") != NULL) + { + motor_direction = strtod(&Motor_command[4], &pEND); + if(motor_direction >= -1 && motor_direction <= 1) + { + motor_strength = strtod(1+pEND, &pEND2); + if(motor_strength >= -1 && motor_strength <= 1) + { + //sprintf(output_chars, "Motor direction is: %f Motor strength is:%f\n", motor_direction, motor_strength); + //TX_Channel.write(output_chars, strlen(output_chars)+1); //output the command for debugging + if(motor_direction < 0) + { + Motor1.set_speed(motor_strength); + Motor2.set_speed(motor_strength*abs(motor_direction)*2); + } + else if(motor_direction>0) + { + Motor2.set_speed(motor_strength); + Motor1.set_speed(motor_strength*abs(motor_direction)*2); + + } + } + } + + } + leds = 0x5; + } + + + +} + + + +#endif +
diff -r 000000000000 -r 9b057566f9ee Hexacopter/Mutexes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/Mutexes.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,14 @@ + +#pragma once +#ifndef MUTEXES_H +#define MUTEXES_H + +//---------------------------------------------------------------------- +//This file defines the mutexes that are in use in this program + +OS::TMutex Serial_Mutex; //this Mutex is used to selectively give access to the serial port +OS::TMutex XB_Mutex; //this Mutex is used to selectively give access to the XBEE serial port +OS::TMutex Ser_out_Mutex; //serial output mutex + + +#endif \ No newline at end of file
diff -r 000000000000 -r 9b057566f9ee Hexacopter/PING_rangefinder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/PING_rangefinder.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,203 @@ +#pragma once +#ifndef PING_RANGEFINDER_H +#define PING_RANGEFINDER_H + +#include <processes.h> +#include <Mutexes.h> +#include <channels.h> +#define PINGPIN p22 + + +//DigitalOut led3(LED3); //these LEDs are used to indicate when an interrupt occurs. +//DigitalOut led4(LED4); +//byte count = 0; + +class rangefinder { +public: + rangefinder() + :Pinterrupt(PINGPIN), PingPin(PINGPIN) + { + //led3 = ~(led4 = 0); + + time = 0; + enable_flag = false; + set_interrupts(); + PingPin.mode(PullDown); + //Pinterrupt.mode(PullDown); + // Pinterrupt.mode(PullUp); + PingPin.output(); //set pingpin as output + PingPin = 0; + } + + void ping() { + T.reset(); //reset the timer to 0 + set_interrupts(); + enable_flag = false; + PingPin.output(); //set as output + PingPin = 0; //output initiation sequence of 0 1 0 to the rangefinder + wait_us(2); + PingPin = 1; + wait_us(5); + PingPin = 0; + wait_us(1); + //printf("now waiting for input.\n"); + PingPin.input(); //set as input + wait_us(10); + //set_interrupts(); + enable_flag = true; + wait_ms(25); //more than required for maximum distance measurement + + + + //T.start(); //begin timing the length of time for an interrupt to occur + } + void set_interrupts() + { + Pinterrupt.fall(this, &rangefinder::set_time); + Pinterrupt.rise(this, &rangefinder::start_timing); + } + void disable_interrupts() + { + Pinterrupt.fall(NULL); + Pinterrupt.rise(NULL); + + } + void start_timing() { OS::TISRW ISRW; + if(enable_flag == true) + { + T.start(); + //led3 = !led3; + //count++; + } + + //printf("start_timing called.\n"); + } + + void set_time() { OS::TISRW ISRW; + if(enable_flag == true) + { + T.stop(); + //led4 = !led4; + //disable_interrupts(); + //enable_flag = false; + //printf("set_time being called...\n"); + time = T.read_us(); + //count++; + } + //printf("value stored in time %f: \n", time); + + //PingPin.output(); + //PingPin = 0; + //printf("PING:%f\n",get_time()); + + } + + + + float get_time() { + //disable_interrupts(); + return time/2.0; + + } + + +private: + Timer T; + float time; //time in us + InterruptIn Pinterrupt; + DigitalInOut PingPin; + bool enable_flag; + //Ticker TICKER;// send_ticker; + + +}; + + + + + + + + + + +extern BusOut leds; + +template<> OS_PROCESS void PING_PROC::Exec() //Output stream handling process +{ + byte M = 0; + rangefinder PING; + + +char PIN_Return_chars[100]; //defined in accelerometer.h + + for(;;) + { + if(PING_MESSAGE.wait(80)) //length of time to wait also determines how rapidly to ticker ping + { leds = 0x2; + M = PING_MESSAGE; //read the message that was destined for this process + PING_MESSAGE.reset(); + + if(M == 0) //then ping! command was sent + { + { + //OS::TISRW ISRW; //this is a critical section as timing is involved + //this will not work though as it disables interrupts. + PING.ping(); + } + + { + //TCritSect cs; + sprintf(PIN_Return_chars, "PING:%f\n", PING.get_time()); // + } + //Ser_out_Mutex.Lock(); + //if(TX_Channel.get_free_size() > strlen(Return_chars)+1) + TX_channel.write(PIN_Return_chars, strlen(PIN_Return_chars)+1); //output the ping result + //Ser_out_Mutex.Unlock(); + + + } + } + if(M == 1) //ticker ping + { + { + //OS::TISRW ISRW; //this is a critical section as timing is involved + PING.ping(); + } + //Sleep(2); + { + //TCritSect cs; + sprintf(PIN_Return_chars, "PING:%f\n", PING.get_time()); //"PING:%f\n" + } + //Ser_out_Mutex.Lock(); + //if(TX_Channel.get_free_size() > strlen(Return_chars)+1) + TX_channel.write(PIN_Return_chars, strlen(PIN_Return_chars)+1); //output the result + //Ser_out_Mutex.Unlock(); + //TX_flag.Signal(); + + } + + //PING_MESSAGE.reset(); + + leds = 0x2; + + } +} + + + #endif + + //void enable_ticker() { + // TICKER.attach_us(this, &rangefinder::ping, TX_RATE); //call ping() every 40 ms + //send_ticker.attach_us(this, &rangefinder::send_data, TX_RATE); //send the data out every 40 ms + //} + //void disable_ticker() { + //printf("ticker should now be detached.\n"); + // TICKER.detach(); + //send_ticker.detach(); + //} + + + + +
diff -r 000000000000 -r 9b057566f9ee Hexacopter/Servo_Control.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/Servo_Control.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,89 @@ +#pragma once +#ifndef SERVO_CONTROL_H +#define SERVO_CONTROL_H +//#include <processes.h> +#include "Servo.h" + +#define SERVO_PIN p21 +extern BusOut leds; +template<> OS_PROCESS void Servo_control::Exec() //serial stream handling process +{ + Servo Servo_object(SERVO_PIN); + char Servo_Command[100] = ""; + Servo_Command[99] = '\0'; + float servo_position = 0, range = 0, degrees = 0; + char *pEnd; + //char output_chars[50] = ""; + + for (;;) + { + + //Servo_Command_Event.Wait(); + for(byte i = 0; i<100; i++) + { + SER_channel.pop(Servo_Command[i]); + leds = 0x6; + if(Servo_Command[i] == '\0') //keep popping chars until a delimiter is found + break; + else if(Servo_Command[i] != '\0' && i == 99) + Servo_Command[i] = '\0'; + + } + + //sprintf(output_chars, "a servo command was received:\n"); + //TX_Channel.write(output_chars, strlen(output_chars)+1); //output the command for debugging + //TX_Channel.write(Servo_Command, strlen(Servo_Command)+1); //output the command for debugging + + if(strlen(Servo_Command) > 6) + { + + if (strlen(Servo_Command) >= 20 && strstr(Servo_Command,":Calibrate")) + { //Serv:Calibrate:range:degrees + + range = strtod(&Servo_Command[15], &pEnd); + if (range >= 0 && range <= 1 && pEnd - &Servo_Command[15] != 0) + { + const char* deg = strstr(strstr(strstr(Servo_Command,":"),":"),":"); + degrees = strtod(deg+1, &pEnd); + if (degrees >= -360 && range <= 360 && (pEnd - deg) != 0) + { + //printf("Received command: Serv:Calibrate:%f:%f. \n", range, degrees); + Servo_object.calibrate(range,degrees); + } + } + + } + + else + { + servo_position = strtod(&Servo_Command[4], &pEnd); //&Servo_Command[5] + + //sprintf(output_chars, "servo position is %f\n", servo_position); + //TX_Channel.write(output_chars, strlen(output_chars)+1); //output the command for debugging + + if (servo_position >= 0 && servo_position <= 1 && (pEnd - &Servo_Command[4]) != 0) //the magic number 4 relates to the position in the string where the actual data should start + { + Servo_object = servo_position; + } + else if (servo_position == -1) //sweep the position through range + { + for(float p=0; p<1.0; p += 0.1) + { + Servo_object = p; + Sleep(200); + } + + } + } + } + leds = 0x6; + } + + + +} + + + +#endif +
diff -r 000000000000 -r 9b057566f9ee Hexacopter/accelerometer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/accelerometer.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,197 @@ +#pragma once +#ifndef ACCELEROMETER_H +#define ACCELEROMETER_H + +#include <processes.h> +#include <Mutexes.h> +#include <channels.h> +#define X_axis p28 +#define Y_axis p27 + +//DigitalOut led3(LED3); //these LEDs are used to indicate when an interrupt occurs. +//DigitalOut led4(LED4); + + +class accelerometer { +public: + accelerometer() + :X_int(X_axis), + Y_int(Y_axis) + //X_input(X_axis), + //Y_input(Y_axis) + { + //led3 = led4 = 0; + X_time = Y_time = 0; + //enable_flag = false; + enable_X_rising_flag = enable_X_falling_flag = enable_Y_rising_flag = enable_Y_falling_flag = false; + X_int.mode(PullDown); + Y_int.mode(PullDown); + //Y_input.mode(PullDown); + //X_input.mode(PullDown); + X_timer.reset(); + Y_timer.reset(); + set_interrupts(); + enable_X_rising_flag = enable_Y_rising_flag = true; + } + + + void set_interrupts() + { + X_int.fall(this, &accelerometer::set_X_time); + X_int.rise(this, &accelerometer::start_X_timing); + Y_int.fall(this, &accelerometer::set_Y_time); + Y_int.rise(this, &accelerometer::start_Y_timing); + } + + void start_X_timing() + { + OS::TISRW ISRW; + if(enable_X_rising_flag == true) + { + X_timer.start(); + enable_X_falling_flag = true; + //printf("In start_x_time().\n"); + + } + + + } + void start_Y_timing() + { + OS::TISRW ISRW; + if(enable_Y_rising_flag == true) + { + Y_timer.start(); + enable_Y_falling_flag = true; + + } + + + } + + void set_X_time() { + if(enable_X_falling_flag == true) + { + OS::TISRW ISRW; + X_timer.stop(); + X_time = X_timer.read_us(); + X_timer.reset(); + // led3 = !led3; + //printf("In set_x_time().\n"); + + + } + } + + + void set_Y_time() { + if(enable_Y_falling_flag == true) + { + OS::TISRW ISRW; + Y_timer.stop(); + Y_time = Y_timer.read_us(); + Y_timer.reset(); + // led4 = !led4; + + + } + } + + float get_X_time() + { + return X_time; + } + + float get_Y_time() + { + return Y_time; + } + + +private: + Timer X_timer; + Timer Y_timer; + float X_time; //time in us + float Y_time; + InterruptIn X_int; + InterruptIn Y_int; + //DigitalIn X_input; + //DigitalIn Y_input; + bool enable_X_rising_flag; + bool enable_X_falling_flag; + bool enable_Y_rising_flag; + bool enable_Y_falling_flag; +}; + + + + + + + + +extern BusOut leds; + +char ACC_Return_chars[100] = ""; + + +//typedef OS::process<OS::pr2, 1400> Accelo_proc; +template<> OS_PROCESS void Accelo_proc::Exec() //Output stream handling process +{ + + accelerometer ACC; + + byte M = 0; + for(;;) + { + if(ACCELEROMETER_MESSAGE.wait(70)) //length of time to wait also determines how rapidly to return accelerometer data + { leds = 0x2; + M = ACCELEROMETER_MESSAGE; //read the message that was destined for this process + ACCELEROMETER_MESSAGE.reset(); + + if(M == 0) //then return x and y data once + { + sprintf(ACC_Return_chars, "ACC_X:%f\nACC_Y:%f\n", ACC.get_X_time(), ACC.get_Y_time()); // ready return string + //if(!Ser_out_Mutex.IsLocked()) + { + //Ser_out_Mutex.Lock(); + //if(TX_Channel.get_free_size() > strlen(Return_chars)+1) + TX_channel.write(ACC_Return_chars, strlen(ACC_Return_chars)+1); //output the data! + //Ser_out_Mutex.Unlock(); + } + + + + } + } + if(M == 1) //ticker + { + + { + //TCritSect cs; + sprintf(ACC_Return_chars, "ACC_X:%f\nACC_Y:%f\n", ACC.get_X_time(), ACC.get_Y_time()); // ready return string //"ACC_X:%f\nACC_Y:%f\n" + } + //if(!Ser_out_Mutex.IsLocked()) + { + //Ser_out_Mutex.Lock(); + //if(TX_Channel.get_free_size() > strlen(Return_chars)+1) + TX_channel.write(ACC_Return_chars, strlen(ACC_Return_chars)+1); //output the data! + //Ser_out_Mutex.Unlock(); + } + //TX_flag.Signal(); + + } + + leds = 0x2; + + + } +} + + + #endif + + + + +
diff -r 000000000000 -r 9b057566f9ee Hexacopter/channels.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/channels.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,17 @@ +#pragma once +#ifndef CHANNELS_H +#define CHANNELS_H + +//-------------------------------------------------------------------------------------------- +//define the channels that are going to be used in the program + // command channel + +OS::channel<char, 100> RX_channel; +OS::channel<char, 100> SER_channel; +OS::channel<char, 100> MOT_channel; +OS::channel<char, 100> TX_channel; + + + + +#endif \ No newline at end of file
diff -r 000000000000 -r 9b057566f9ee Hexacopter/event_flags.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/event_flags.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,18 @@ +#pragma once +#ifndef EVENT_FLAGS_H +#define EVENT_FLAGS_H + +//--------------------------------------------------------------------------- +// +// Event Flags to test +// +OS::TEventFlag ef; +//OS::TEventFlag RX_flag; //this signals the command_handler process +//OS::TEventFlag TX_flag; //signals the serial_out process +OS::TEventFlag timerEvent; +//OS::TEventFlag Servo_Command_Event; //signals the servo_control process that there is a new command + + + + +#endif \ No newline at end of file
diff -r 000000000000 -r 9b057566f9ee Hexacopter/messages.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/messages.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,17 @@ +//----------------------------------------------------------------- +//file containing the os::message list used in the program + +#pragma once +#ifndef MESSAGES_H +#define MESSAGES_H + +//-------------------------------------------------------------------------------------------- +//define the channels that are going to be used in the program + // command channel + +OS::message<byte> PING_MESSAGE; //if message is a zero, then PING once, if a 1 then Ticker ping +OS::message<byte> ACCELEROMETER_MESSAGE; //if message is a zero, then return acceleration once, if a 1 then continually return acceleration data +//OS::message<float> MOTOR_message; + + +#endif \ No newline at end of file
diff -r 000000000000 -r 9b057566f9ee Hexacopter/processes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/processes.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,105 @@ +#pragma once + +#ifndef PROCESSES_H +#define PROCESSES_H +#include <event_flags.h> +//#include <Servo_Control.h> + +// Process types +// + +/* +typedef OS::process<OS::pr0, 1400> PING_PROC; +typedef OS::process<OS::pr1, 1000> TProc2; +typedef OS::process<OS::pr2, 3000> Accelo_proc; +typedef OS::process<OS::pr3, 1000> Servo_control; +typedef OS::process<OS::pr4, 3000> Command_handler; +typedef OS::process<OS::pr5, 1000> Motor_controller; +typedef OS::process<OS::pr6, 4000> Serial_Out; +*/ + +typedef OS::process<OS::pr0, 2000> PING_PROC; +typedef OS::process<OS::pr1, 1400> TProc2; +typedef OS::process<OS::pr2, 3000> Accelo_proc; +typedef OS::process<OS::pr3, 2000> Servo_control; +typedef OS::process<OS::pr4, 3000> Command_handler; +typedef OS::process<OS::pr5, 2000> Motor_controller; +typedef OS::process<OS::pr6, 4000> Serial_Out; + +//typedef OS::process<OS::pr3, 300> TProc4; + +//--------------------------------------------------------------------------- +// +// Process objects +// +PING_PROC PING_PROCESS; +TProc2 Proc2; +Accelo_proc Accelerometer_process; +Servo_control Servo_process; +Command_handler Com_Handler; +Serial_Out Serial_Out_Proc; +Motor_controller M_cont_process; + +//--------------------------------------------------------------------------- + + + +// IO Pins +// +//DigitalOut led1(LED1); +//DigitalOut led2(LED2); + + +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +//extra declarations + + + + + + + + +BusOut leds(LED1, LED2, LED3, LED4); + + +//--------------------------------------------------------------------------- +template<> OS_PROCESS void TProc2::Exec() +{ + for(;;) + { + Sleep(500); //suspend process + //printf("e\n"); + //led1 = !led1; + //leds = 0x1; + } +} + +//--------------------------------------------------------------------------- + + + +void OS::SystemTimerUserHook() +{ + static int cnt=0; + if (++cnt == 2000) + { + cnt = 0; + //led2.write(1); + timerEvent.SignalISR(); + } +} + +//--------------------------------------------------------------------------- +void OS::IdleProcessUserHook() +{ + __WFI(); //sleep the ucontroller and wait for interrupt +} +//----------------------------------------------------------------------------- + +#endif + +
diff -r 000000000000 -r 9b057566f9ee Hexacopter/serial.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/serial.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,97 @@ +#ifndef SERIAL_H +#define SERIAL_H +#include <channels.h> +#include <Mutexes.h> +#include <processes.h> + +#define UART1TX p9 +#define UART1RX p10 + +Serial USB(USBTX, USBRX); // tx, rx +Serial XB(UART1TX, UART1RX); // tx, rx +Serial *OUT = &USB; //intially set to USB + +extern BusOut leds; + void USB_serial() //signal RTOS event that RXinterrupt has been asserted +{ + OS::TISRW ISRW; + leds = 0x7; + //char count = 0; + //led3 = !led3; + char temp = 0; + + //leds = 0xa; + if(true)//!Serial_Mutex.IsLocked()) + { + //leds = 0xb; + //Serial_Mutex.Lock(); + leds = 0xc; + if(USB.readable()) + { + temp = USB.getc(); + leds = 0xd; + + if(RX_channel.get_free_size() >0 ) //only push a character onto the channel if there is free space + { + //OUT = &USB; + if(temp != '\n') + { + RX_channel.push(temp); + leds = 0xe; + } + else if(temp == '\n') + { + RX_channel.push('\0'); + } + } + else USB.getc(); //start discarding characters!*/ + leds = 0xf; + leds = 0xa; + } + leds = 0xb; + //Serial_Mutex.Unlock(); + //Serial_Mutex.Lock(); + //if(USB.writeable()) + //USB.putc(temp); + //Serial_Mutex.Unlock(); + leds = 0x1; + } + else USB.getc(); //start discarding characters! + + leds = 0x9; +} + +/*void XB_serial() +{ + //led4 = !led4; + char temp = 0; + OS::TISRW ISRW; + if(!XB_Mutex.IsLocked()) + { + XB_Mutex.Lock(); + while(XB.readable()) + { + temp = XB.getc(); + if(RX_channel.get_free_size() >0 ) //only push a character onto the channel if there is free space + { + OUT = &XB; + if(temp != '\n') + { + RX_channel.push(temp); + } + else if(temp == '\n') + { + OUT = &XB; + RX_channel.push('\0'); + } + } + else temp = XB.getc(); //otherwise, wait until another character is sent and try then + } + XB_Mutex.Unlock(); + } + + +}*/ + +#endif +
diff -r 000000000000 -r 9b057566f9ee Hexacopter/serial_out.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexacopter/serial_out.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,60 @@ +#pragma once +#ifndef SERIAL_OUT_H +#define SERIAL_OUT_H +#include <processes.h> +#include <Mutexes.h> +#include <channels.h> +#include <serial.h> +//DigitalOut led3(LED3); +extern BusOut leds; +template<> OS_PROCESS void Serial_Out::Exec() //Output stream handling process +{ + + + char temp1 = 0; + //led3 = 0; + //char buf[50] = "output process working.\n"; + for(;;) + { + //Sleep(500); + TX_channel.pop(temp1); + leds = 0x8; + //wait_ms(200); //simulate delays + //Sleep(10); + //led3 = !led3; + //OUT->printf(buf); + //if(OUT == &USB) + //{ + //Serial_Mutex.Lock(); + //XB_Mutex.Lock(); + if(OUT->writeable()) + { + OUT->putc(temp1); + + + + + + //XB_Mutex.Unlock(); + } + else + { + //TX_channel.push_front(temp1); + //OUT->printf("output is not writeable!\n"); + //Sleep(0.5); //sleep + } + //Serial_Mutex.Unlock(); + //} + + + + leds = 0x8; + + } +} + + + #endif + + +
diff -r 000000000000 -r 9b057566f9ee Servo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Servo.cpp Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,74 @@ +/* mbed R/C Servo Library + * + * Copyright (c) 2007-2010 sford, cstyles + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "Servo.h" +#include "mbed.h" + +static float clamp(float value, float min, float max) { + if(value < min) { + return min; + } else if(value > max) { + return max; + } else { + return value; + } +} + +Servo::Servo(PinName pin) : _pwm(pin) { + calibrate(); + write(0.5); +} + +void Servo::write(float percent) { + float offset = _range * 2.0 * (percent - 0.5); + _pwm.pulsewidth(0.0015 + clamp(offset, -_range, _range)); + _p = clamp(percent, 0.0, 1.0); +} + +void Servo::position(float degrees) { + float offset = _range * (degrees / _degrees); + _pwm.pulsewidth(0.0015 + clamp(offset, -_range, _range)); +} + +void Servo::calibrate(float range, float degrees) { + _range = range; + _degrees = degrees; +} + +float Servo::read() { + return _p; +} + +Servo& Servo::operator= (float percent) { + write(percent); + return *this; +} + +Servo& Servo::operator= (Servo& rhs) { + write(rhs.read()); + return *this; +} + +Servo::operator float() { + return read(); +}
diff -r 000000000000 -r 9b057566f9ee Servo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Servo.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,98 @@ +/* mbed R/C Servo Library + * Copyright (c) 2007-2010 sford, cstyles + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MBED_SERVO_H +#define MBED_SERVO_H + +#include "mbed.h" + +/** Servo control class, based on a PwmOut + * + * Example: + * @code + * // Continuously sweep the servo through it's full range + * #include "mbed.h" + * #include "Servo.h" + * + * Servo myservo(p21); + * + * int main() { + * while(1) { + * for(int i=0; i<100; i++) { + * myservo = i/100.0; + * wait(0.01); + * } + * for(int i=100; i>0; i--) { + * myservo = i/100.0; + * wait(0.01); + * } + * } + * } + * @endcode + */ +class Servo { + +public: + /** Create a servo object connected to the specified PwmOut pin + * + * @param pin PwmOut pin to connect to + */ + Servo(PinName pin); + + /** Set the servo position, normalised to it's full range + * + * @param percent A normalised number 0.0-1.0 to represent the full range. + */ + void write(float percent); + + /** Read the servo motors current position + * + * @param returns A normalised number 0.0-1.0 representing the full range. + */ + float read(); + + /** Set the servo position + * + * @param degrees Servo position in degrees + */ + void position(float degrees); + + /** Allows calibration of the range and angles for a particular servo + * + * @param range Pulsewidth range from center (1.5ms) to maximum/minimum position in seconds + * @param degrees Angle from centre to maximum/minimum position in degrees + */ + void calibrate(float range = 0.0005, float degrees = 45.0); + + /** Shorthand for the write and read functions */ + Servo& operator= (float percent); + Servo& operator= (Servo& rhs); + operator float(); + +protected: + PwmOut _pwm; + float _range; + float _degrees; + float _p; +}; + +#endif
diff -r 000000000000 -r 9b057566f9ee main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,89 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PROCESSOR: ARM Cortex-M3 +//* +//* TOOLKIT: RVCT (ARM) +//* +//* PURPOSE: Port Test File +//* +//* Version: 3.10 +//* +//* $Revision: 196 $ +//* $Date:: 2010-09-09 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** +//* mbed port by Igor Skochinsky + +#include <mbed.h> +#include <scmRTOS.h> +#include <processes.h> +#include <serial.h> +#include <Command_handler.h> +#include <event_flags.h> +#include <Servo_Control.h> +#include <serial_out.h> +#include <PING_rangefinder.h> +#include <Motor_control.h> +#include <accelerometer.h> +//--------------------------------------------------------------------------- +// + +// + + + + + +// +int main() +{ + + USB.baud(921600); + USB.attach(USB_serial); + //XB.baud(115200); + //XB.attach(XB_serial); + // configure IO pins + //led1.write(0); + //led2.write(0); + + // run + OS::Run(); +} + + + + +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +
diff -r 000000000000 -r 9b057566f9ee mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e
diff -r 000000000000 -r 9b057566f9ee scmRTOS/Common/OS_Kernel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/Common/OS_Kernel.cpp Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,115 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PURPOSE: OS Kernel Source +//* +//* Version: 3.10 +//* +//* $Revision: 256 $ +//* $Date:: 2010-01-22 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** + +#include "scmRTOS.h" + +using namespace OS; +//------------------------------------------------------------------------------ +OS::TKernel OS::Kernel; + +//------------------------------------------------------------------------------ +#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0 +void TKernel::Sched() +{ + byte NextPrty = GetHighPriority(ReadyProcessMap); + if(NextPrty != CurProcPriority) + { + TStackItem* Next_SP = ProcessTable[NextPrty]->StackPointer; + TStackItem** Curr_SP_addr = &(ProcessTable[CurProcPriority]->StackPointer); + CurProcPriority = NextPrty; + OS_ContextSwitcher(Curr_SP_addr, Next_SP); + } +} +#else +//------------------------------------------------------------------------------ +void TKernel::Sched() +{ + byte NextPrty = GetHighPriority(ReadyProcessMap); + if(NextPrty != CurProcPriority) + { + SchedProcPriority = NextPrty; + + RaiseContextSwitch(); + do + { + EnableContextSwitch(); + DUMMY_INSTR(); + DisableContextSwitch(); + } + while(!IsContextSwitchDone()); + } +} +//------------------------------------------------------------------------------ +TStackItem* OS_ContextSwitchHook(TStackItem* sp) { return OS::Kernel.ContextSwitchHook(sp); } +//------------------------------------------------------------------------------ +#endif // scmRTOS_CONTEXT_SWITCH_SCHEME +//------------------------------------------------------------------------------ +void TBaseProcess::Sleep(TTimeout timeout) +{ + TCritSect cs; + + Kernel.ProcessTable[Kernel.CurProcPriority]->Timeout = timeout; + Kernel.SetProcessUnready(Kernel.CurProcPriority); + Kernel.Scheduler(); +} +//------------------------------------------------------------------------------ +void OS::WakeUpProcess(TBaseProcess& p) +{ + TCritSect cs; + + if(p.Timeout) + { + p.Timeout = 0; + Kernel.SetProcessReady(p.Priority); + Kernel.Scheduler(); + } +} +//------------------------------------------------------------------------------ +void OS::ForceWakeUpProcess(TBaseProcess& p) +{ + TCritSect cs; + + p.Timeout = 0; + Kernel.SetProcessReady(p.Priority); + Kernel.Scheduler(); +} +//------------------------------------------------------------------------------ +
diff -r 000000000000 -r 9b057566f9ee scmRTOS/Common/OS_Kernel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/Common/OS_Kernel.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,426 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PURPOSE: OS Kernel Header. Declarations And Definitions +//* +//* Version: 3.10 +//* +//* $Revision: 256 $ +//* $Date:: 2010-01-22 #$ +//* +//* Copyright (c)c 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//***************************************************************************** + +#ifndef OS_KERNEL_H +#define OS_KERNEL_H + +#include <stddef.h> +#include <commdefs.h> +#include <usrlib.h> + +//------------------------------------------------------------------------------ + +//============================================================================== +extern "C" void OS_Start(TStackItem* sp); + +#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0 + extern "C" void OS_ContextSwitcher(TStackItem** Curr_SP, TStackItem* Next_SP); +#else + extern "C" TStackItem* OS_ContextSwitchHook(TStackItem* sp); +#endif + +//============================================================================== + +//------------------------------------------------------------------------------ +// +// +// NAME : OS +// +// PURPOSE : Namespace for all OS stuff +// +// DESCRIPTION: Includes: Kernel, +// Processes, +// Mutexes, +// Event Flags, +// Byte-wide Channels, +// Arbitrary-type Channels, +// Messages +// +namespace OS +{ + class TBaseProcess; + + INLINE inline void SetPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm |= PrioTag; } + INLINE inline void ClrPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm &= ~PrioTag; } + + //-------------------------------------------------------------------------- + // + // NAME : TKernel + // + /// Implements kernel-level operations such as + /// process management, process-level scheduling, + /// ISR-level scheduling, system timing. + // + // DESCRIPTION: + // + // + class TKernel + { + //----------------------------------------------------------- + // + // Declarations + // + + + friend class TISRW; + friend class TISRW_SS; + friend class TBaseProcess; + friend class TMutex; + friend class TEventFlag; + friend class TChannel; + friend class TBaseMessage; + + template<typename T, word size, class S> friend class channel; + template<typename T> friend class message; + + friend void Run(); + friend void WakeUpProcess(TBaseProcess& p); + friend void ForceWakeUpProcess(TBaseProcess& p); + friend inline bool IsProcessSleeping(const TBaseProcess& p); + friend inline bool IsProcessSuspended(const TBaseProcess& p); + friend inline dword GetTickCount(); + + //----------------------------------------------------------- + // + // Data + // + private: + byte CurProcPriority; + TProcessMap ReadyProcessMap; + TBaseProcess* ProcessTable[scmRTOS_PROCESS_COUNT+1]; + volatile byte ISR_NestCount; + + #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1 + byte SchedProcPriority; + #endif + + #if scmRTOS_SYSTEM_TICKS_ENABLE == 1 + volatile dword SysTickCount; + #endif + + //----------------------------------------------------------- + // + // Functions + // + public: + INLINE TKernel() + : CurProcPriority(pr0) + , ReadyProcessMap( (1 << (scmRTOS_PROCESS_COUNT + 1)) - 1) // set all processes ready + , ISR_NestCount(0) + { + } + + private: + INLINE inline void RegisterProcess(TBaseProcess* const p); + + void Sched(); + INLINE void Scheduler() { if(ISR_NestCount) return; else Sched(); } + INLINE inline void SchedISR(); + + #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1 + INLINE inline bool IsContextSwitchDone() const volatile; + #endif + INLINE void SetProcessReady (const byte pr) { TProcessMap PrioTag = GetPrioTag(pr); SetPrioTag( ReadyProcessMap, PrioTag); } + INLINE void SetProcessUnready(const byte pr) { TProcessMap PrioTag = GetPrioTag(pr); ClrPrioTag( ReadyProcessMap, PrioTag); } + + public: + INLINE inline void SystemTimer(); + #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1 + INLINE inline TStackItem* ContextSwitchHook(TStackItem* sp); + #endif + + }; // End of TKernel class definition + //-------------------------------------------------------------------------- + extern TKernel Kernel; + + //-------------------------------------------------------------------------- + // + /// BaseProcess + /// + /// Implements base class-type for application processes + // + // DESCRIPTION: + // + // + class TBaseProcess + { + friend class TKernel; + friend class TISRW; + friend class TISRW_SS; + friend class TEventFlag; + friend class TMutex; + friend class TBaseMessage; + + template<typename T, word size, class S> friend class channel; + template<typename T> friend class message; + + + friend void Run(); + friend void WakeUpProcess(TBaseProcess& p); + friend void ForceWakeUpProcess(TBaseProcess& p); + friend bool IsProcessSleeping(const TBaseProcess& p); + friend bool IsProcessSuspended(const TBaseProcess& p); + + public: + #if SEPARATE_RETURN_STACK == 0 + TBaseProcess( TStackItem* Stack, TPriority pr, void (*exec)() ); + #else + TBaseProcess( TStackItem* Stack, TStackItem* RStack, TPriority pr, void (*exec)() ); + #endif + + static void Sleep(TTimeout timeout = 0); + + protected: + TStackItem* StackPointer; + TTimeout Timeout; + TPriority Priority; + }; + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // + /// process + /// + /// Implements template for application processes instantiation + // + // DESCRIPTION: + // + // + #if SEPARATE_RETURN_STACK == 0 + + template<TPriority pr, word stack_size> + class process : public TBaseProcess + { + public: + INLINE_PROCESS_CTOR process(); + + OS_PROCESS static void Exec(); + + private: + TStackItem Stack[stack_size/sizeof(TStackItem)]; + }; + + template<TPriority pr, word stack_size> + OS::process<pr, stack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)] + , pr + , reinterpret_cast<void (*)()>(Exec) ) + { + } + + #else + + template<TPriority pr, word stack_size, word rstack_size> + class process : public TBaseProcess + { + public: + INLINE_PROCESS_CTOR process(); + + OS_PROCESS static void Exec(); + + private: + TStackItem Stack [stack_size/sizeof(TStackItem)]; + TStackItem RStack[rstack_size/sizeof(TStackItem)]; + }; + + template<TPriority pr, word stack_size, word rstack_size> + process<pr, stack_size, rstack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)] + , &RStack[rstack_size/sizeof(TStackItem)] + , pr + , reinterpret_cast<void (*)()>(Exec)) + { + } + + #endif + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // + // Miscellaneous + // + // + INLINE inline void Run(); + INLINE inline void LockSystemTimer() { TCritSect cs; LOCK_SYSTEM_TIMER(); } + INLINE inline void UnlockSystemTimer() { TCritSect cs; UNLOCK_SYSTEM_TIMER(); } + void WakeUpProcess(TBaseProcess& p); + void ForceWakeUpProcess(TBaseProcess& p); + INLINE inline void Sleep(TTimeout t = 0) { TBaseProcess::Sleep(t); } + + INLINE inline bool IsProcessSleeping(const TBaseProcess& p) + { + TCritSect cs; + if(p.Timeout) + return true; + else + return false; + } + + INLINE inline bool IsProcessSuspended(const TBaseProcess& p) + { + TCritSect cs; + if(Kernel.ReadyProcessMap & GetPrioTag(p.Priority)) + return false; + else + return true; + } + //-------------------------------------------------------------------------- + +#if scmRTOS_SYSTEM_TICKS_ENABLE == 1 + INLINE inline dword GetTickCount() { TCritSect cs; return Kernel.SysTickCount; } +#endif + +#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1 + INLINE_SYS_TIMER_HOOK void SystemTimerUserHook(); +#endif + +#if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1 + INLINE_CONTEXT_SWITCH_HOOK void ContextSwitchUserHook(); +#endif + +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// +/// Register Process +/// +/// Places pointer to process in kernel's process table +// +void OS::TKernel::RegisterProcess(OS::TBaseProcess* const p) +{ + ProcessTable[p->Priority] = p; +} +//------------------------------------------------------------------------------ +// +/// System Timer Implementation +/// +/// Performs process's timeouts checking and +/// moving processes to ready-to-run state +// +void OS::TKernel::SystemTimer() +{ + SYS_TIMER_CRIT_SECT(); +#if scmRTOS_SYSTEM_TICKS_ENABLE == 1 + SysTickCount++; +#endif + +#if scmRTOS_PRIORITY_ORDER == 0 + const byte BaseIndex = 0; +#else + const byte BaseIndex = 1; +#endif + + for(byte i = BaseIndex; i < (scmRTOS_PROCESS_COUNT + BaseIndex); i++) + { + TBaseProcess* p = ProcessTable[i]; + + if(p->Timeout > 0) + { + if(--p->Timeout == 0) + { + SetProcessReady(p->Priority); + } + } + } +} +//------------------------------------------------------------------------------ +// +/// ISR optimized scheduler +/// +/// !!! IMPORTANT: This function must be call from ISR services only !!! +// +// +#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0 +void OS::TKernel::SchedISR() +{ + byte NextPrty = GetHighPriority(ReadyProcessMap); + if(NextPrty != CurProcPriority) + { + TStackItem* Next_SP = ProcessTable[NextPrty]->StackPointer; + TStackItem** Curr_SP_addr = &(ProcessTable[CurProcPriority]->StackPointer); + CurProcPriority = NextPrty; + OS_ContextSwitcher(Curr_SP_addr, Next_SP); + } +} +#else +void OS::TKernel::SchedISR() +{ + byte NextPrty = GetHighPriority(ReadyProcessMap); + if(NextPrty != CurProcPriority) + { + SchedProcPriority = NextPrty; + RaiseContextSwitch(); + } +} +//------------------------------------------------------------------------------ +bool OS::TKernel::IsContextSwitchDone() const volatile +{ + byte cur = CurProcPriority; ///< reading to temporary vars is performed due to + byte sched = SchedProcPriority; ///< suppress warning about order of volatile access + return cur == sched; +} +//------------------------------------------------------------------------------ +TStackItem* OS::TKernel::ContextSwitchHook(TStackItem* sp) +{ + ProcessTable[CurProcPriority]->StackPointer = sp; + sp = ProcessTable[SchedProcPriority]->StackPointer; + +#if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1 + ContextSwitchUserHook(); +#endif + + CurProcPriority = SchedProcPriority; + return sp; +} +//------------------------------------------------------------------------------ +#endif // scmRTOS_CONTEXT_SWITCH_SCHEME + +//----------------------------------------------------------------------------- +/// Start Operation +INLINE inline void OS::Run() +{ + TStackItem* sp = Kernel.ProcessTable[pr0]->StackPointer; + OS_Start(sp); +} + +#include <OS_Services.h> + +#endif // OS_KERNEL_H +
diff -r 000000000000 -r 9b057566f9ee scmRTOS/Common/OS_Services.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/Common/OS_Services.cpp Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,298 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PURPOSE: OS Services Source +//* +//* Version: 3.10 +//* +//* $Revision: 256 $ +//* $Date:: 2010-01-22 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** + +#include "scmRTOS.h" + +using namespace OS; + +//------------------------------------------------------------------------------ +// +// +// TEventFlag +// +// +bool OS::TEventFlag::Wait(TTimeout timeout) +{ + TCritSect cs; + + if(Value) // if flag already signaled + { + Value = efOff; // clear flag + return true; + } + else + { + TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority]; + p->Timeout = timeout; + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + + SetPrioTag(ProcessMap, PrioTag); // put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + + Kernel.Scheduler(); + + p->Timeout = 0; + + if( !(ProcessMap & PrioTag) ) // if waked up by signal() or signal_ISR() + return true; + + ClrPrioTag(ProcessMap, PrioTag); // otherwise waked up by timeout or by + return false; // OS::ForceWakeUpProcess(), remove process from the wait map + } +} +//------------------------------------------------------------------------------ +void OS::TEventFlag::Signal() +{ + TCritSect cs; + if(ProcessMap) // if any process waits for event + { + TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout expired + // or it was waked up by OS::ForceWakeUpProcess() + + if( ProcessMap & ~Timeouted ) // if any process has to be waked up + { + SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map + ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map. + // Used to check that process waked up by signal() or signalISR() + // and not by timeout or OS::ForceWakeUpProcess() + Kernel.Scheduler(); + return; + } + } + Value = efOn; +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// +// +// TMutex +// +// +void OS::TMutex::Lock() +{ + TCritSect cs; + + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + while(ValueTag) + { + SetPrioTag(ProcessMap, PrioTag); // mutex already locked by another process, put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + + Kernel.Scheduler(); + } + ValueTag = PrioTag; // mutex has been successfully locked +} +//------------------------------------------------------------------------------ +void OS::TMutex::Unlock() +{ + TCritSect cs; + + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + if(ValueTag != PrioTag) return; // the only process that had locked mutex can unlock the mutex + ValueTag = 0; + if(ProcessMap) + { + byte pr = GetHighPriority(ProcessMap); + PrioTag = GetPrioTag(pr); + ClrPrioTag(ProcessMap, PrioTag); // remove next ready process from the wait map + SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map + Kernel.Scheduler(); + } +} +//------------------------------------------------------------------------------ +void OS::TMutex::UnlockISR() +{ + TCritSect cs; + + ValueTag = 0; + if(ProcessMap) + { + byte pr = GetHighPriority(ProcessMap); + TProcessMap PrioTag = GetPrioTag(pr); + ClrPrioTag(ProcessMap, PrioTag); // remove next ready process from the wait map + SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map + } +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +// +// +// TChannel +// +// +void OS::TChannel::CheckWaiters(TProcessMap& pm) +{ + if(pm) + { + byte pr = GetHighPriority(pm); + TProcessMap PrioTag = GetPrioTag(pr); + ClrPrioTag(pm, PrioTag); // remove next ready process from the wait map + SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map + Kernel.Scheduler(); + } +} +//------------------------------------------------------------------------------ +void OS::TChannel::Push(byte x) +{ + TCritSect cs; + + while (!Cbuf.get_free_size()) + { + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + SetPrioTag (ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + Kernel.Scheduler(); // wait until waked-up by Pop() or Read() + } + + Cbuf.put(x); + CheckWaiters(ConsumersProcessMap); +} +//------------------------------------------------------------------------------ +byte OS::TChannel::Pop() +{ + TCritSect cs; + byte x; + + while(!Cbuf.get_count()) + { + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + Kernel.Scheduler(); // wait until waked up by Push() or Write() + } + x = Cbuf.get(); + CheckWaiters(ProducersProcessMap); + return x; +} +//------------------------------------------------------------------------------ +void OS::TChannel::Write(const byte* data, const byte count) +{ + TCritSect cs; + + while(Cbuf.get_free_size() < count) + { + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + SetPrioTag(ProducersProcessMap, PrioTag); // channel has not enough space, put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + Kernel.Scheduler(); // wait until waked up by Read() or Pop() + } + + Cbuf.write(data, count); + CheckWaiters(ConsumersProcessMap); +} +//------------------------------------------------------------------------------ +void OS::TChannel::Read(byte* const data, const byte count) +{ + TCritSect cs; + + while(Cbuf.get_count() < count) + { + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + SetPrioTag(ConsumersProcessMap, PrioTag); // channel doesn't contain enough data, put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + Kernel.Scheduler(); // wait until waked up by Write() or Push() + } + + Cbuf.read(data, count); + CheckWaiters(ProducersProcessMap); +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// +// OS::message template +// +// Function-members implementation +// +// +//------------------------------------------------------------------------------ +bool OS::TBaseMessage::wait(TTimeout timeout) +{ + TCritSect cs; + + if(NonEmpty) // message alredy send + { + NonEmpty = false; + return true; + } + else + { + TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority]; + p->Timeout = timeout; + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + + SetPrioTag(ProcessMap, PrioTag); // put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + Kernel.Scheduler(); // wait until wake up + + p->Timeout = 0; + if( !(ProcessMap & PrioTag) ) // if waked up by send() or sendISR() + return true; + + ClrPrioTag(ProcessMap, PrioTag); // otherwise waked up by timeout or by + return false; // OS::ForceWakeUpProcess(), remove process from wait map + } +} +//------------------------------------------------------------------------------ +void OS::TBaseMessage::send() +{ + TCritSect cs; + + if(ProcessMap) + { + TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout expired, + // or it was waked up by OS::ForceWakeUpProcess() + if( ProcessMap & ~Timeouted ) // if any process has to be waked up + { + SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map + ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map. + Kernel.Scheduler(); + return; + } + } + + NonEmpty = true; +} +//------------------------------------------------------------------------------ +
diff -r 000000000000 -r 9b057566f9ee scmRTOS/Common/OS_Services.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/Common/OS_Services.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,467 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PURPOSE: OS Services Header. Declarations And Definitions +//* +//* Version: 3.10 +//* +//* $Revision: 256 $ +//* $Date:: 2010-01-22 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** + +#ifndef OS_SERVICES_H +#define OS_SERVICES_H + +namespace OS +{ + //-------------------------------------------------------------------------- + // + // NAME : Mutex + // + /// Binary semaphore for support of mutual exclusion + // + // DESCRIPTION: + // + // + class TMutex + { + public: + INLINE TMutex() : ProcessMap(0), ValueTag(0) { } + void Lock(); + void Unlock(); + void UnlockISR(); + + INLINE bool LockSoftly() { TCritSect cs; if(ValueTag) return false; else Lock(); return true; } + INLINE bool IsLocked() const { TCritSect cs; if(ValueTag) return true; else return false; } + + private: + TProcessMap ProcessMap; + TProcessMap ValueTag; + + }; + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // + /// Event Flag + /// + /// Intended for processes synchronization and + /// event notification one (or more) process by another + // + // DESCRIPTION: + // + // + class TEventFlag + { + public: + enum TValue { efOn = 1, efOff= 0 }; // prefix 'ef' means: "Event Flag" + + public: + INLINE TEventFlag(TValue init_val = efOff) : ProcessMap(0), Value(init_val) { } + + bool Wait(TTimeout timeout = 0); + void Signal(); + INLINE void Clear() { TCritSect cs; Value = efOff; } + INLINE inline void SignalISR(); + INLINE bool IsSignaled() { TCritSect cs; if(Value == efOn) return true; else return false; } + + private: + TProcessMap ProcessMap; + TValue Value; + }; + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // + /// TChannel + /// + /// Byte-wide data channel for transferring "raw" data + // + // DESCRIPTION: + // + // + class TChannel + { + public: + INLINE TChannel(byte* buf, byte size) : Cbuf(buf, size) { } + void Push(byte x); + byte Pop(); + void Write(const byte* data, const byte count); + void Read(byte* const data, const byte count); + + INLINE byte GetCount() const { TCritSect cs; return Cbuf.get_count(); } + + private: + TProcessMap ProducersProcessMap; + TProcessMap ConsumersProcessMap; + usr::TCbuf Cbuf; + + private: + void CheckWaiters(TProcessMap& pm); + }; + //-------------------------------------------------------------------------- + + + //-------------------------------------------------------------------------- + // + // NAME : channel + // + // PURPOSE : Data channel for transferring data + // objects of arbitrary type + // + // DESCRIPTION: + // + // + template<typename T, word Size, typename S = byte> + /// channel + /// + /// Data channel for transferring data objects of arbitrary type + class channel + { + public: + INLINE channel() : ProducersProcessMap(0) + , ConsumersProcessMap(0) + , pool() + { + } + + //---------------------------------------------------------------- + // + // Data transfer functions + // + void write(const T* data, const S cnt); + bool read (T* const data, const S cnt, TTimeout timeout = 0); + + void push (const T& item); + void push_front(const T& item); + + bool pop (T& item, TTimeout timeout = 0); + bool pop_back(T& item, TTimeout timeout = 0); + + + //---------------------------------------------------------------- + // + // Service functions + // + INLINE S get_count() const { TCritSect cs; return pool.get_count(); } + INLINE S get_free_size() const { TCritSect cs; return pool.get_free_size(); } + void flush(); + //const T& operator[](const S index) { TCritSect cs; return pool[index]; } + + + private: + TProcessMap ProducersProcessMap; + TProcessMap ConsumersProcessMap; + usr::ring_buffer<T, Size, S> pool; + + private: + void CheckWaiters(TProcessMap& pm); + }; + + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // + /// message + /// + /// Template for messages + // + // DESCRIPTION: + // + // + class TBaseMessage + { + public: + INLINE TBaseMessage() : ProcessMap(0), NonEmpty(false) { } + + bool wait (TTimeout timeout = 0); + void send(); + INLINE inline void sendISR(); + INLINE bool is_non_empty() const { TCritSect cs; return NonEmpty; } + INLINE void reset () { TCritSect cs; NonEmpty = false; } + + private: + TProcessMap ProcessMap; + bool NonEmpty; + }; + //-------------------------------------------------------------------------- + template<typename T> + class message : public TBaseMessage + { + public: + INLINE message() : TBaseMessage() { } + INLINE const T& operator=(const T& msg) { TCritSect cs; Msg = msg; return Msg; } + INLINE operator T() const { TCritSect cs; return Msg; } + + private: + T Msg; + }; + //-------------------------------------------------------------------------- +} +//------------------------------------------------------------------------------ +// +// Function-members implementation +// +//------------------------------------------------------------------------------ +void OS::TEventFlag::SignalISR() +{ + TCritSect cs; + if(ProcessMap) // if any process waits for event + { + TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout + // expired, or it was waked up by OS::ForceWakeUpProcess() + if( ProcessMap & ~Timeouted ) // if any process has to be waked up + { + SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map + ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map. + return; + } + } + Value = efOn; +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +void OS::channel<T, Size, S>::CheckWaiters(TProcessMap& pm) +{ + if(pm) + { + TProcessMap Timeouted = Kernel.ReadyProcessMap; + + SetPrioTag(Kernel.ReadyProcessMap, pm); // place all waiting processes to the ready map + ClrPrioTag(pm, ~Timeouted); // remove waiting processes from the wait map + Kernel.Scheduler(); + } +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +void OS::channel<T, Size, S>::push(const T& item) +{ + TCritSect cs; + + while(!pool.get_free_size()) + { + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + SetPrioTag(ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + Kernel.Scheduler(); + } + + pool.push_back(item); + CheckWaiters(ConsumersProcessMap); +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +void OS::channel<T, Size, S>::push_front(const T& item) +{ + TCritSect cs; + + while(!pool.get_free_size()) + { + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + SetPrioTag(ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + Kernel.Scheduler(); + } + + pool.push_front(item); + CheckWaiters(ConsumersProcessMap); +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +bool OS::channel<T, Size, S>::pop(T& item, TTimeout timeout) +{ + TCritSect cs; + + if(pool.get_count()) + { + item = pool.pop(); + CheckWaiters(ProducersProcessMap); + return true; + } + else + { + TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority]; + p->Timeout = timeout; + + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + for(;;) + { + SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + Kernel.Scheduler(); + + if(pool.get_count()) + { + p->Timeout = 0; + item = pool.pop(); + CheckWaiters(ProducersProcessMap); + return true; + } + + if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired + { // or by OS::ForceWakeUpProcess() + + p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess() + ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map + return false; + } + } + } +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +bool OS::channel<T, Size, S>::pop_back(T& item, TTimeout timeout) +{ + TCritSect cs; + + if(pool.get_count()) + { + item = pool.pop_back(); + CheckWaiters(ProducersProcessMap); + return true; + } + else + { + TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority]; + p->Timeout = timeout; + + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + for(;;) + { + SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + Kernel.Scheduler(); + + if(pool.get_count()) + { + p->Timeout = 0; + item = pool.pop_back(); + CheckWaiters(ProducersProcessMap); + return true; + } + + if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired + { // or by OS::ForceWakeUpProcess() + + p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess() + ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map + return false; + } + } + } +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +void OS::channel<T, Size, S>::flush() +{ + TCritSect cs; + pool.flush(); + CheckWaiters(ProducersProcessMap); +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +void OS::channel<T, Size, S>::write(const T* data, const S count) +{ + TCritSect cs; + + while(pool.get_free_size() < count) + { + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + SetPrioTag(ProducersProcessMap, PrioTag); // channel does not have enough space, put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + Kernel.Scheduler(); + } + + pool.write(data, count); + CheckWaiters(ConsumersProcessMap); +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +bool OS::channel<T, Size, S>::read(T* const data, const S count, TTimeout timeout) +{ + TCritSect cs; + + TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority]; + p->Timeout = timeout; + + TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority); + while(pool.get_count() < count) + { + SetPrioTag(ConsumersProcessMap, PrioTag); // channel doesn't contain enough data, put current process to the wait map + ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map + Kernel.Scheduler(); + + if(ConsumersProcessMap & PrioTag) // waked up by timer when timeout expired + { // or by OS::ForceWakeUpProcess() + + p->Timeout = 0; // non-zero if waked up by ForceWakeUpProcess() + ClrPrioTag(ConsumersProcessMap, PrioTag); // remove current process from the wait map + return false; + } + } + + p->Timeout = 0; + pool.read(data, count); + CheckWaiters(ProducersProcessMap); + + return true; +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// +// OS::message template +// +// Function-members implementation +// +// +//------------------------------------------------------------------------------ +void OS::TBaseMessage::sendISR() +{ + TCritSect cs; + + if(ProcessMap) + { + TProcessMap Timeouted = OS::Kernel.ReadyProcessMap; // Process has it's tag set in ReadyProcessMap if timeout + // expired, or it was waked up by OS::ForceWakeUpProcess() + if( ProcessMap & ~Timeouted ) // if any process has to be waked up + { + SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map + ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map. + return; + } + } + NonEmpty = true; +} +//------------------------------------------------------------------------------ +#endif // OS_SERVICES_H
diff -r 000000000000 -r 9b057566f9ee scmRTOS/Common/scmRTOS.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/Common/scmRTOS.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,58 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PURPOSE: Main RTOS header file +//* +//* Version: 3.10 +//* +//* $Revision: 256 $ +//* $Date:: 2010-01-22 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** + +#ifndef scmRTOS_H +#define scmRTOS_H + +//----------------------------------------------------------------------------- +// +// !!! The order of includes is important !!! +// +#include <stddef.h> +#include <commdefs.h> +#include <usrlib.h> +#include <OS_Target.h> + +//------------------------------------------------------------------------------ + + +#endif // scmRTOS_H +
diff -r 000000000000 -r 9b057566f9ee scmRTOS/Common/scmRTOS_defs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/Common/scmRTOS_defs.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,374 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PURPOSE: Macros And Common Definitions +//* +//* Version: 3.10 +//* +//* $Revision: 256 $ +//* $Date:: 2010-01-22 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** + +#ifndef scmRTOS_DEFS_H +#define scmRTOS_DEFS_H + +#include <commdefs.h> + +//------------------------------------------------------------------------------ + +//----------------------------------------------------------------------------- +// +// +/// Macro for Channel Type definition +// +// +#define DefineChannel(Name, Capacity) \ +class Name : public OS::TChannel \ +{ \ +public: \ + Name() : OS::TChannel(buf, sizeof(buf)) { } \ + \ +private: \ + byte buf[Capacity]; \ + \ +} +//----------------------------------------------------------------------------- +// +// Check CONFIG Macro Definitions +// +// + +//----------------- scmRTOS_SYSTIMER_NEST_INTS_ENABLE ------------------------- +#ifndef scmRTOS_SYSTIMER_NEST_INTS_ENABLE +#error "Error: Config macro scmRTOS_SYSTIMER_NEST_INTS_ENABLE must be defined!" +#endif + +#if (scmRTOS_SYSTIMER_NEST_INTS_ENABLE < 0) || (scmRTOS_SYSTIMER_NEST_INTS_ENABLE > 1) +#error "Error: scmRTOS_SYSTIMER_NEST_INTS_ENABLE must have values 0 or 1 only!" +#endif + +//----------------- scmRTOS_SYSTEM_TICKS_ENABLE ------------------------------- +#ifndef scmRTOS_SYSTEM_TICKS_ENABLE +#error "Error: Config macro scmRTOS_SYSTEM_TICKS_ENABLE must be defined!" +#endif + +#if (scmRTOS_SYSTEM_TICKS_ENABLE < 0) || (scmRTOS_SYSTEM_TICKS_ENABLE > 1) +#error "Error: scmRTOS_SYSTEM_TICKS_ENABLE must have values 0 or 1 only!" +#endif + + +//----------------- scmRTOS_SYSTIMER_HOOK_ENABLE ------------------------------ +#ifndef scmRTOS_SYSTIMER_HOOK_ENABLE +#error "Error: Config macro scmRTOS_SYSTIMER_HOOK_ENABLE must be defined!" +#endif + +#if (scmRTOS_SYSTIMER_HOOK_ENABLE < 0) || (scmRTOS_SYSTIMER_HOOK_ENABLE > 1) +#error "Error: scmRTOS_SYSTIMER_HOOK_ENABLE must have values 0 or 1 only!" +#endif + +//-------------- scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE ---------------------- +#ifndef scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE +#error "Error: Config macro scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE must be defined!" +#endif + +#if (scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE < 0) || (scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE > 1) +#error "Error: scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE must have values 0 or 1 only!" +#endif + +//----------------- scmRTOS_IDLE_HOOK_ENABLE ---------------------------------- +#ifndef scmRTOS_IDLE_HOOK_ENABLE +#error "Error: Config macro scmRTOS_IDLE_HOOK_ENABLE must be defined!" +#endif + +#if (scmRTOS_IDLE_HOOK_ENABLE < 0) || (scmRTOS_IDLE_HOOK_ENABLE > 1) +#error "Error: scmRTOS_IDLE_HOOK_ENABLE must have values 0 or 1 only!" +#endif + +//----------------- scmRTOS_CONTEXT_SWITCH_SCHEME ----------------------------- +#ifndef scmRTOS_CONTEXT_SWITCH_SCHEME +#error "Error: Config macro scmRTOS_CONTEXT_SWITCH_SCHEME must be defined!" +#endif + +#if (scmRTOS_CONTEXT_SWITCH_SCHEME < 0) || (scmRTOS_CONTEXT_SWITCH_SCHEME > 1) +#error "Error: scmRTOS_CONTEXT_SWITCH_SCHEME must have values 0 or 1 only!" +#endif + + +//----------------- scmRTOS_PRIORITY_ORDER ------------------------------------ +#ifndef scmRTOS_PRIORITY_ORDER +#error "Error: Config macro scmRTOS_PRIORITY_ORDER must be defined!" +#endif + +#if (scmRTOS_PRIORITY_ORDER < 0) || (scmRTOS_PRIORITY_ORDER > 1) +#error "Error: scmRTOS_PRIORITY_ORDER must have values 0 or 1 only!" +#endif + +//----------------- User Hooks inlining ------------------------------------ +#ifndef INLINE_SYS_TIMER_HOOK +#define INLINE_SYS_TIMER_HOOK +#endif + +#ifndef INLINE_CONTEXT_SWITCH_HOOK +#define INLINE_CONTEXT_SWITCH_HOOK +#endif + + +//----------------------------------------------------------------------------- +// +/// Priority and process map type definitions +// +// +namespace OS +{ + #if scmRTOS_PROCESS_COUNT < 8 + typedef byte TProcessMap; + #elif scmRTOS_PROCESS_COUNT < 16 + typedef word TProcessMap; + #else + typedef dword TProcessMap; + #endif + //------------------------------------------------------ +#if scmRTOS_PRIORITY_ORDER == 0 + enum TPriority { + #if scmRTOS_PROCESS_COUNT > 0 + pr0, + #endif + #if scmRTOS_PROCESS_COUNT > 1 + pr1, + #endif + #if scmRTOS_PROCESS_COUNT > 2 + pr2, + #endif + #if scmRTOS_PROCESS_COUNT > 3 + pr3, + #endif + #if scmRTOS_PROCESS_COUNT > 4 + pr4, + #endif + #if scmRTOS_PROCESS_COUNT > 5 + pr5, + #endif + #if scmRTOS_PROCESS_COUNT > 6 + pr6, + #endif + #if scmRTOS_PROCESS_COUNT > 7 + pr7, + #endif + #if scmRTOS_PROCESS_COUNT > 8 + pr8, + #endif + #if scmRTOS_PROCESS_COUNT > 9 + pr9, + #endif + #if scmRTOS_PROCESS_COUNT > 10 + pr10, + #endif + #if scmRTOS_PROCESS_COUNT > 11 + pr11, + #endif + #if scmRTOS_PROCESS_COUNT > 12 + pr12, + #endif + #if scmRTOS_PROCESS_COUNT > 13 + pr13, + #endif + #if scmRTOS_PROCESS_COUNT > 14 + pr14, + #endif + #if scmRTOS_PROCESS_COUNT > 15 + pr15, + #endif + #if scmRTOS_PROCESS_COUNT > 16 + pr16, + #endif + #if scmRTOS_PROCESS_COUNT > 17 + pr17, + #endif + #if scmRTOS_PROCESS_COUNT > 18 + pr18, + #endif + #if scmRTOS_PROCESS_COUNT > 19 + pr19, + #endif + #if scmRTOS_PROCESS_COUNT > 20 + pr20, + #endif + #if scmRTOS_PROCESS_COUNT > 21 + pr21, + #endif + #if scmRTOS_PROCESS_COUNT > 22 + pr22, + #endif + #if scmRTOS_PROCESS_COUNT > 23 + pr23, + #endif + #if scmRTOS_PROCESS_COUNT > 24 + pr24, + #endif + #if scmRTOS_PROCESS_COUNT > 25 + pr25, + #endif + #if scmRTOS_PROCESS_COUNT > 26 + pr26, + #endif + #if scmRTOS_PROCESS_COUNT > 27 + pr27, + #endif + #if scmRTOS_PROCESS_COUNT > 28 + pr28, + #endif + #if scmRTOS_PROCESS_COUNT > 29 + pr29, + #endif + #if scmRTOS_PROCESS_COUNT > 30 + pr30, + #endif + #if (scmRTOS_PROCESS_COUNT > 31) || (scmRTOS_PROCESS_COUNT < 1) + #error "Invalid Process Count specification! Must be from 1 to 31." + #endif + prIDLE + }; +#else // scmRTOS_PRIORITY_ORDER == 1 + enum TPriority { + prIDLE, + #if scmRTOS_PROCESS_COUNT > 30 + pr30, + #endif + #if scmRTOS_PROCESS_COUNT > 29 + pr29, + #endif + #if scmRTOS_PROCESS_COUNT > 28 + pr28, + #endif + #if scmRTOS_PROCESS_COUNT > 27 + pr27, + #endif + #if scmRTOS_PROCESS_COUNT > 26 + pr26, + #endif + #if scmRTOS_PROCESS_COUNT > 25 + pr25, + #endif + #if scmRTOS_PROCESS_COUNT > 24 + pr24, + #endif + #if scmRTOS_PROCESS_COUNT > 23 + pr23, + #endif + #if scmRTOS_PROCESS_COUNT > 22 + pr22, + #endif + #if scmRTOS_PROCESS_COUNT > 21 + pr21, + #endif + #if scmRTOS_PROCESS_COUNT > 20 + pr20, + #endif + #if scmRTOS_PROCESS_COUNT > 19 + pr19, + #endif + #if scmRTOS_PROCESS_COUNT > 18 + pr18, + #endif + #if scmRTOS_PROCESS_COUNT > 17 + pr17, + #endif + #if scmRTOS_PROCESS_COUNT > 16 + pr16, + #endif + #if scmRTOS_PROCESS_COUNT > 15 + pr15, + #endif + #if scmRTOS_PROCESS_COUNT > 14 + pr14, + #endif + #if scmRTOS_PROCESS_COUNT > 13 + pr13, + #endif + #if scmRTOS_PROCESS_COUNT > 12 + pr12, + #endif + #if scmRTOS_PROCESS_COUNT > 11 + pr11, + #endif + #if scmRTOS_PROCESS_COUNT > 10 + pr10, + #endif + #if scmRTOS_PROCESS_COUNT > 9 + pr9, + #endif + #if scmRTOS_PROCESS_COUNT > 8 + pr8, + #endif + #if scmRTOS_PROCESS_COUNT > 7 + pr7, + #endif + #if scmRTOS_PROCESS_COUNT > 6 + pr6, + #endif + #if scmRTOS_PROCESS_COUNT > 5 + pr5, + #endif + #if scmRTOS_PROCESS_COUNT > 4 + pr4, + #endif + #if scmRTOS_PROCESS_COUNT > 3 + pr3, + #endif + #if scmRTOS_PROCESS_COUNT > 2 + pr2, + #endif + #if scmRTOS_PROCESS_COUNT > 1 + pr1, + #endif + #if scmRTOS_PROCESS_COUNT > 0 + pr0 + #endif + #if (scmRTOS_PROCESS_COUNT > 31) || (scmRTOS_PROCESS_COUNT < 1) + #error "Invalid Process Count specification! Must be from 1 to 31." + #endif + }; +#endif //scmRTOS_PRIORITY_ORDER +} +//----------------------------------------------------------------------------- +// +// Process's constructor inlining control: default behaviour +// +#ifndef INLINE_PROCESS_CTOR +#define INLINE_PROCESS_CTOR +#endif + + +//----------------------------------------------------------------------------- + +#endif // scmRTOS_DEFS_H
diff -r 000000000000 -r 9b057566f9ee scmRTOS/Common/usrlib.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/Common/usrlib.cpp Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,140 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PURPOSE: User Suport Library Source +//* +//* Version: 3.10 +//* +//* $Revision: 256 $ +//* $Date:: 2010-01-22 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** + +#include <usrlib.h> +#include <commdefs.h> + +using namespace usr; + +//------------------------------------------------------------------------------ +// +/// Circular buffer function-member description +// +// +// +TCbuf::TCbuf(byte* const Address, const byte Size) : + buf(Address), + size(Size), + count(0), + first(0), + last(0) +{ +} +//------------------------------------------------------------------------------ +bool TCbuf::write(const byte* data, const byte Count) +{ + if( Count > (size - count) ) + return false; + + for(byte i = 0; i < Count; i++) + push(*(data++)); + + return true; +} +//------------------------------------------------------------------------------ +void TCbuf::read(byte* data, const byte Count) +{ + byte N = Count <= count ? Count : count; + + for(byte i = 0; i < N; i++) + data[i] = pop(); +} +//------------------------------------------------------------------------------ +byte TCbuf::get_byte(const byte index) const +{ + byte x = first + index; + + if(x < size) + return buf[x]; + else + return buf[x - size]; +} + +//------------------------------------------------------------------------------ +bool TCbuf::put(const byte item) +{ + if(count == size) + return false; + + push(item); + return true; +} +//------------------------------------------------------------------------------ +byte TCbuf::get() +{ + if(count) + return pop(); + else + return 0; +} +//------------------------------------------------------------------------------ +// +/// \note +/// For internal purposes. +/// Use this function with care - it doesn't perform free size check. +// +void TCbuf::push(const byte item) +{ + buf[last] = item; + last++; + count++; + + if(last == size) + last = 0; +} +//------------------------------------------------------------------------------ +// +/// \note +/// For internal purposes. +/// Use this function with care - it doesn't perform free size check. +// +byte TCbuf::pop() +{ + byte item = buf[first]; + + count--; + first++; + if(first == size) + first = 0; + + return item; +} +//------------------------------------------------------------------------------
diff -r 000000000000 -r 9b057566f9ee scmRTOS/Common/usrlib.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/Common/usrlib.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,298 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PURPOSE: User Suport Library Header +//* +//* Version: 3.10 +//* +//* $Revision: 256 $ +//* $Date:: 2010-01-22 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** + +#ifndef USRLIB_H +#define USRLIB_H + +#include <commdefs.h> + +//------------------------------------------------------------------------------ +// +// DESCRIPTON: user namespace for some useful types and functions +// +// +namespace usr +{ + //------------------------------------------------------------------------------ + // + /// The Circular Buffer + // + /// Byte-wide FIFO. + // + /// Allows to: + /// add byte, + /// get byte, + /// write bytes from array, + /// read bytes to array, + /// and some other service actions. + // + class TCbuf + { + public: + TCbuf(byte* const Address, const byte Size); + bool write(const byte* data, const byte Count); + void read(byte* const data, const byte Count); + byte get_count() const { return count; } + byte get_free_size() const { return size - count; } + byte get_byte(const byte index) const; + void clear() { count = 0; last = first; } + bool put(const byte item); + byte get(); + + private: + //------------------------------------------------------------------------------ + // + // DESCRIPTON: For internal purposes + // + void push(const byte item); ///< Use this function with care - it doesn't perform free size check + byte pop(); ///< Use this function with care - it doesn't perform count check + //------------------------------------------------------------------------------ + + private: + byte* buf; + byte size; + volatile byte count; + byte first; + byte last; + }; + //------------------------------------------------------------------------------ + + + + //----------------------------------------------------------------------- + // + /// The Ring Buffer Template + /// + /// Carries out FIFO functionality for + /// arbitrary data types + /// + /// Allows to: + /// add item to back (default), + /// add item to front, + /// get item at front (default), + /// get item from back, + /// write items from array, + /// read items to array and some other actions + // + // + // + template<typename T, word Size, typename S = byte> + class ring_buffer + { + public: + ring_buffer() : Count(0), First(0), Last(0) { } + + //---------------------------------------------------------------- + // + // Data transfer functions + // + bool write(const T* data, const S cnt); + void read(T* const data, const S cnt); + + bool push_back(const T item); + bool push_front(const T item); + + T pop_front(); + T pop_back(); + + bool push(const T item) { return push_back(item); } + T pop() { return pop_front(); } + + //---------------------------------------------------------------- + // + // Service functions + // + S get_count() const { return Count; } + S get_free_size() const { return Size - Count; } + T& operator[](const S index); + void flush() { Count = 0; Last = First; } + + private: + //-------------------------------------------------------------- + // DESCRIPTON: For internal purposes + // Use this functions with care: it don't perform + // free size and count check + // + void push_item(const T item); + void push_item_front(const T item); + T pop_item(); + T pop_item_back(); + //-------------------------------------------------------------- + + private: + S Count; + S First; + S Last; + T Buf[Size]; + }; + //------------------------------------------------------------------ +} +//--------------------------------------------------------------------------- + + +//------------------------------------------------------------------------------ +// +// The ring buffer function-member definitions +// +// +// +template<typename T, word Size, typename S> +bool usr::ring_buffer<T, Size, S>::write(const T* data, const S cnt) +{ + if( cnt > (Size - Count) ) + return false; + + for(S i = 0; i < cnt; i++) + push_item(*(data++)); + + return true; +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +void usr::ring_buffer<T, Size, S>::read(T* data, const S cnt) +{ + S nItems = cnt <= Count ? cnt : Count; + + for(S i = 0; i < nItems; i++) + data[i] = pop_item(); +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +T& usr::ring_buffer<T, Size, S>::operator[](const S index) +{ + S x = First + index; + + if(x < Size) + return Buf[x]; + else + return Buf[x - Size]; +} + +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +bool usr::ring_buffer<T, Size, S>::push_back(const T item) +{ + if(Count == Size) + return false; + + push_item(item); + return true; +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +bool usr::ring_buffer<T, Size, S>::push_front(const T item) +{ + if(Count == Size) + return false; + + push_item_front(item); + return true; +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +T usr::ring_buffer<T, Size, S>::pop_front() +{ + if(Count) + return pop_item(); + else + return Buf[First]; +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +T usr::ring_buffer<T, Size, S>::pop_back() +{ + if(Count) + return pop_item_back(); + else + return Buf[First]; +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +void usr::ring_buffer<T, Size, S>::push_item(const T item) +{ + Buf[Last] = item; + Last++; + Count++; + + if(Last == Size) + Last = 0; +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +void usr::ring_buffer<T, Size, S>::push_item_front(const T item) +{ + if(First == 0) + First = Size - 1; + else + --First; + Buf[First] = item; + Count++; +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +T usr::ring_buffer<T, Size, S>::pop_item() +{ + T item = Buf[First]; + + Count--; + First++; + if(First == Size) + First = 0; + + return item; +} +//------------------------------------------------------------------------------ +template<typename T, word Size, typename S> +T usr::ring_buffer<T, Size, S>::pop_item_back() +{ + + if(Last == 0) + Last = Size - 1; + else + --Last; + + Count--; + return Buf[Last];; +} +//------------------------------------------------------------------------------ + + +#endif // USRLIB_H
diff -r 000000000000 -r 9b057566f9ee scmRTOS/CortexM3/OS_Target.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/CortexM3/OS_Target.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,236 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PROCESSOR: ARM Cortex-M3 +//* +//* TOOLKIT: RVCT (ARM) +//* +//* PURPOSE: Target Dependent Stuff Header. Declarations And Definitions +//* +//* Version: 3.10 +//* +//* $Revision: 195 $ +//* $Date:: 2008-06-19 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** +//* Ported by Andrey Chuikin, Copyright (c) 2008-2010 + +#ifndef scmRTOS_CORTEXM3_H +#define scmRTOS_CORTEXM3_H + +#include <commdefs.h> + +//------------------------------------------------------------------------------ +// +// Compiler and Target checks +// +// +#ifndef __ARMCC_VERSION +#error "This file should only be compiled with ARM RVCT Compiler" +#endif // __ARMCC_VERSION + +#if __TARGET_ARCH_ARM != 0 || __TARGET_ARCH_THUMB != 4 +#error "This file must be compiled for ARMv7-M (Cortex-M3) processor only." +#endif + +//------------------------------------------------------------------------------ +// +// Target specific types +// +// +typedef dword TStackItem; +typedef dword TStatusReg; + +//----------------------------------------------------------------------------- +// +// Configuration macros +// +// +#define OS_PROCESS __attribute__((__noreturn__)) +#define OS_INTERRUPT +#define DUMMY_INSTR() __NOP() +#define INLINE_PROCESS_CTOR INLINE inline + +//----------------------------------------------------------------------------- +// +// Uncomment macro value below for SystemTimer() run in critical section +// +// This is useful (and necessary) when target processor has hardware +// enabled nested interrups. Cortex-M3 have such interrupts. +// +#define SYS_TIMER_CRIT_SECT() TCritSect cs + +//----------------------------------------------------------------------------- +// Separate return stack not required +#define SEPARATE_RETURN_STACK 0 + +//----------------------------------------------------------------------------- +// Software interrupt stack switching not supported in Cortex-M3 port +// because processor implements hardware stack switching. +// So, system timer isr wrapper can't be choosen at project level +// +#define scmRTOS_ISRW_TYPE TISRW + +//----------------------------------------------------------------------------- +// +// scmRTOS Context Switch Scheme +// +// The macro defines a context switch manner. Value 0 sets direct context +// switch in the scheduler and in the OS ISRs. This is the primary method. +// Value 1 sets the second way to switch context - by using of software +// interrupt. See documentation fo details. +// Cortex-M3 port supports software interrupt switch method only. +// +#define scmRTOS_CONTEXT_SWITCH_SCHEME 1 + +//----------------------------------------------------------------------------- +// +// Include project-level configurations +// !!! The order of includes is important !!! +// +#include "../scmRTOS_config.h" +#include "../scmRTOS_TARGET_CFG.h" +#include <scmRTOS_defs.h> +#include <LPC17xx.h> + +//----------------------------------------------------------------------------- +// +// The Critital Section Wrapper +// +// +#define __enable_interrupt() __enable_irq() +#define __disable_interrupt() __disable_irq() + +#define __set_interrupt_state(status) __set_PRIMASK(status) +#define __get_interrupt_state() __get_PRIMASK() + +class TCritSect +{ +public: + TCritSect () : StatusReg(__get_interrupt_state()) { __disable_interrupt(); } + ~TCritSect() { __set_interrupt_state(StatusReg); } + +private: + TStatusReg StatusReg; +}; +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// Priority stuff +// +// +namespace OS +{ +INLINE inline OS::TProcessMap GetPrioTag(const byte pr) { return static_cast<OS::TProcessMap> (1 << pr); } + +#if scmRTOS_PRIORITY_ORDER == 0 + INLINE inline byte GetHighPriority(TProcessMap pm) + { + byte pr = 0; + + while( !(pm & 0x0001) ) + { + pr++; + pm >>= 1; + } + return pr; + } +#else + INLINE inline byte GetHighPriority(TProcessMap pm) { return (31 - __clz(pm)); } +#endif // scmRTOS_PRIORITY_ORDER +} + +//----------------------------------------------------------------------------- +// +// Interrupt and Interrupt Service Routines support +// +INLINE inline TStatusReg GetInterruptState( ) { return __get_interrupt_state(); } +INLINE inline void SetInterruptState(TStatusReg sr) { __set_interrupt_state(sr); } + +INLINE inline void EnableInterrupts() { __enable_interrupt(); } +INLINE inline void DisableInterrupts() { __disable_interrupt(); } + + +namespace OS +{ + INLINE inline void EnableContextSwitch() { EnableInterrupts(); } + INLINE inline void DisableContextSwitch() { DisableInterrupts(); } +} + +#include <OS_Kernel.h> + +namespace OS +{ + //-------------------------------------------------------------------------- + // + // NAME : OS ISR support + // + // PURPOSE : Implements common actions on interrupt enter and exit + // under the OS + // + // DESCRIPTION: + // + // + class TISRW + { + public: + INLINE TISRW() { ISR_Enter(); } + INLINE ~TISRW() { ISR_Exit(); } + + private: + //----------------------------------------------------- + INLINE void ISR_Enter() + { + TCritSect cs; + Kernel.ISR_NestCount++; + } + //----------------------------------------------------- + INLINE void ISR_Exit() + { + TCritSect cs; + if(--Kernel.ISR_NestCount) return; + Kernel.SchedISR(); + } + //----------------------------------------------------- + }; + + // No software interrupt stack switching provided, + // TISRW_SS declared to be the same as TISRW for porting compability + #define TISRW_SS TISRW + +} // ns OS +//----------------------------------------------------------------------------- + +#endif // scmRTOS_CORTEXM3_H +//----------------------------------------------------------------------------- +
diff -r 000000000000 -r 9b057566f9ee scmRTOS/CortexM3/OS_Target_asm.s --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/CortexM3/OS_Target_asm.s Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,178 @@ +; ****************************************************************************** +; * +; * FULLNAME: Single-Chip Microcontroller Real-Time Operating System +; * +; * NICKNAME: scmRTOS +; * +; * PROCESSOR: ARM Cortex-M3 +; * +; * TOOLKIT: EWARM (IAR Systems) +; * +; * PURPOSE: Target Dependent Low-Level Stuff +; * +; * Version: 3.10 +; * +; * $Revision: 195 $ +; * $Date:: 2008-06-19 #$ +; * +; * Copyright (c) 2003-2010, Harry E. Zhurov +; * +; * Permission is hereby granted, free of charge, to any person +; * obtaining a copy of this software and associated documentation +; * files (the "Software"), to deal in the Software without restriction, +; * including without limitation the rights to use, copy, modify, merge, +; * publish, distribute, sublicense, and/or sell copies of the Software, +; * and to permit persons to whom the Software is furnished to do so, +; * subject to the following conditions: +; * +; * The above copyright notice and this permission notice shall be included +; * in all copies or substantial portions of the Software. +; * +; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +; * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +; * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +; * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +; * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +; * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +; * THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +; * +; * ================================================================= +; * See http://scmrtos.sourceforge.net for documentation, latest +; * information, license and contact details. +; * ================================================================= +; * +; ****************************************************************************** +; * Ported by Andrey Chuikin, Copyright (c) 2008-2010 + +; #include "scmRTOS_TARGET_CFG.h" + +; ----------------------------------------------------------------------------- +; PUBLIC FUNCTIONS +; + EXTERN OS_ContextSwitchHook + + EXPORT OS_Start + EXPORT PendSV_Handler + +; ----------------------------------------------------------------------------- +; EQUATES +; +NVIC_INT_CTRL EQU 0xE000ED04 ; Interrupt control state register. +NVIC_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception. + +NVIC_SYSPRI14 EQU 0xE000ED22 ; System priority register (priority 14). +NVIC_PENDSV_PRI EQU 0xFF ; PendSV priority value (lowest). +NVIC_SYSPRI15 EQU 0xE000ED23 ; System priority register (priority 15). +NVIC_ST_PRI EQU 0xFF ; SysTick priority value (lowest). + +NVIC_ST_CTRL EQU 0xE000E010 ; SysTick Ctrl & Status Reg. +NVIC_ST_RELOAD EQU 0xE000E014 ; SysTick Reload Value Reg. +NVIC_ST_CTRL_CLK_SRC EQU 0x00000004 ; Clock Source. +NVIC_ST_CTRL_INTEN EQU 0x00000002 ; Interrupt enable. +NVIC_ST_CTRL_ENABLE EQU 0x00000001 ; Counter mode. + +; should be the same as in scmRTOS_TARGET_CFG.h +SYSTICKFREQ EQU 100000000 +SYSTICKINTRATE EQU 1000 + +; ----------------------------------------------------------------------------- +; CODE GENERATION DIRECTIVES +; + AREA TEXT, CODE, READONLY + THUMB + +; ----------------------------------------------------------------------------- +; HANDLE PendSV EXCEPTION +; void PendSV_Handler(void) +; +; Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing +; context switches with Cortex-M3. This is because the Cortex-M3 auto-saves half of the +; processor context on any exception, and restores same on return from exception. So only +; saving of R4-R11 is required and fixing up the stack pointers. Using the PendSV exception +; this way means that context saving and restoring is identical whether it is initiated from +; a thread or occurs due to an interrupt or exception. +; +; 2) Pseudo-code is: +; a) Get the process SP, if 0 then skip (goto f) the saving part (first context switch); +; b) Save remaining regs r4-r11 on process stack; +; c) Call OS_ContextSwitchHook for save current task SP and get new task SP; +; d) Restore R4-R11 from new process stack; +; e) Perform exception return which will restore remaining context. +; f) Get SP for the first context switch (R2 hold it); +; run SysTick; goto d); +; +; 3) On entry into PendSV handler: +; a) The following have been saved on the process stack (by processor): +; xPSR, PC, LR, R12, R0-R3 +; b) Processor mode is switched to Handler mode (from Thread mode) +; c) Stack is Main stack (switched from Process stack) +; +; 4) Since PendSV is set to lowest priority in the system (by OS_Start() below), we +; know that it will only be run when no other exception or interrupt is active, and +; therefore safe to assume that context being switched out was using the process stack (PSP). +; +PendSV_Handler + CPSID I ; Prevent interruption during context switch + MRS R0, PSP ; PSP is process stack pointer + CBZ R0, nosave ; Skip register save the first time + + STMDB R0!, {R4-R11} ; Save remaining regs r4-11 on process stack + ; At this point, entire context of process has been saved + + PUSH {R14} ; Save LR exc_return value + LDR R1, =OS_ContextSwitchHook ; OS_ContextSwitchHook(); + BLX R1 + POP {R14} + +ContextRestore + ; R0 is new process SP; + LDMIA R0!, {R4-R11} ; Restore r4-11 from new process stack + MSR PSP, R0 ; Load PSP with new process SP + ORR LR, LR, #0x04 ; Ensure exception return uses process stack + CPSIE I + BX LR ; Exception return will restore remaining context +nosave + MOV R0, R2 ; R2 hold the first task SP + + LDR R1, =NVIC_ST_CTRL ; Enable and run SysTick + LDR R2, =(NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_INTEN | NVIC_ST_CTRL_ENABLE) + STR R2, [R1] + + B ContextRestore + + +; ----------------------------------------------------------------------------- +; START MULTITASKING +; void OS_Start(TStackItem* sp) +; +; Note(s) : 1) OS_Start() MUST: +; a) Setup PendSV and SysTick exception priority to lowest; +; b) Setup SysTick (reload value); +; c) Enable interrupts (tasks will run with interrupts enabled). +; +OS_Start + LDR R1, =NVIC_SYSPRI14 ; Set the PendSV exception priority (lowest) + LDR R2, =NVIC_PENDSV_PRI + STRB R2, [R1] + LDR R1, =NVIC_SYSPRI15 ; Set the SysTick exception priority (lowest) + LDR R2, =NVIC_ST_PRI + STRB R2, [R1] + + LDR R1, =NVIC_ST_RELOAD ; Setup SysTick + LDR R2, =(SYSTICKFREQ/SYSTICKINTRATE-1) + STR R2, [R1] + + MOV R2, R0 ; Save the first task stack + MOVS R0, #0 ; Set the PSP to 0 for initial context switch call + MSR PSP, R0 + + LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + + CPSIE I ; Enable interrupts at processor level +loop + B loop ; Should never get here + + + END
diff -r 000000000000 -r 9b057566f9ee scmRTOS/CortexM3/OS_Target_cpp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/CortexM3/OS_Target_cpp.cpp Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,131 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PROCESSOR: ARM Cortex-M3 +//* +//* TOOLKIT: EWARM (IAR Systems) +//* +//* PURPOSE: Target Dependent Stuff Source +//* +//* Version: 3.10 +//* +//* $Revision: 195 $ +//* $Date:: 2008-06-19 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** +//* Ported by Andrey Chuikin, Copyright (c) 2008-2010 + + +#include <scmRTOS.h> + +using namespace OS; + +//------------------------------------------------------------------------------ +// +// OS Process's constructor +// +// Performs: +// * initializing process data; +// * registering of the process in kernel; +// * preparing stack frame; +// +// +TBaseProcess::TBaseProcess(TStackItem* Stack, TPriority pr, void (*exec)()) + : StackPointer(Stack) + , Timeout(0) + , Priority(pr) +{ + Kernel.RegisterProcess(this); + + //--------------------------------------------------------------- + // + // Prepare Process Stack Frame + // + *(--StackPointer) = 0x01000000L; // xPSR + *(--StackPointer) = reinterpret_cast<dword>(exec); // Entry Point + StackPointer -= 14; // emulate "push R14,R12,R3,R2,R1,R0,R11-R4" + + // The code below can be used for debug purpose. In this case comment + // line above and uncomment block below. +/* + *(--StackPointer) = 0xFFFFFFFEL; // R14 (LR) (init value will cause fault if ever used) + *(--StackPointer) = 0x12121212L; // R12 + *(--StackPointer) = 0x03030303L; // R3 + *(--StackPointer) = 0x02020202L; // R2 + *(--StackPointer) = 0x01010101L; // R1 + *(--StackPointer) = 0x00000000L; // R0 + + // Remaining registers saved on process stack + *(--StackPointer) = 0x11111111L; // R11 + *(--StackPointer) = 0x10101010L; // R10 + *(--StackPointer) = 0x09090909L; // R9 + *(--StackPointer) = 0x08080808L; // R8 + *(--StackPointer) = 0x07070707L; // R7 + *(--StackPointer) = 0x06060606L; // R6 + *(--StackPointer) = 0x05050505L; // R5 + *(--StackPointer) = 0x04040404L; // R4 +*/ +} +//------------------------------------------------------------------------------ +// +// Idle Process +// +typedef process<prIDLE, scmRTOS_IDLE_PROCESS_STACK_SIZE> TIdleProcess; + +TIdleProcess IdleProcess; + +template<> OS_PROCESS void TIdleProcess::Exec() +{ + for(;;) + { + #if scmRTOS_IDLE_HOOK_ENABLE == 1 + IdleProcessUserHook(); + #endif + } +} +//------------------------------------------------------------------------------ +OS_INTERRUPT void OS::SysTick_Handler() +{ + scmRTOS_ISRW_TYPE ISR; + + Kernel.SystemTimer(); + +#if scmRTOS_SYSTIMER_NEST_INTS_ENABLE == 0 + DISABLE_NESTED_INTERRUPTS(); +#endif + +#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1 + SystemTimerUserHook(); +#endif +} +//------------------------------------------------------------------------------ +
diff -r 000000000000 -r 9b057566f9ee scmRTOS/CortexM3/commdefs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/CortexM3/commdefs.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,71 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PROCESSOR: ARM Cortex-M3 +//* +//* TOOLKIT: EWARM (IAR Systems) +//* +//* PURPOSE: Common Type Definitions +//* +//* Version: 3.10 +//* +//* $Revision: 195 $ +//* $Date:: 2008-06-19 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** +//* Ported by Andrey Chuikin, Copyright (c) 2008-2010 + + +#ifndef COMMONDEFS_H +#define COMMONDEFS_H + +#ifndef __IAR_SYSTEMS_ASM__ + +typedef unsigned char byte; +typedef signed char sbyte; +typedef unsigned short word; +typedef unsigned long dword; + +typedef volatile byte sfr_byte; +typedef volatile word sfr_word; +typedef volatile dword sfr_dword; + +#define INLINE _Pragma("inline=forced") + +#endif // __IAR_SYSTEMS_ASM__ + +#endif // COMMONDEFS_H + +//----------------------------------------------------------------------------- + +/*============================================================================*/ +
diff -r 000000000000 -r 9b057566f9ee scmRTOS/CortexM3/device.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/CortexM3/device.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,60 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PROCESSOR: ARM Cortex-M3 +//* +//* TOOLKIT: EWARM (IAR Systems) +//* +//* PURPOSE: Device Definitions +//* +//* Version: 3.10 +//* +//* $Revision: 196 $ +//* $Date:: 2008-06-19 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** +//* Ported by Andrey Chuikin, Copyright (c) 2008-2010 + +#ifndef DEVICE_H +#define DEVICE_H + +#include <commdefs.h> + +//------------------------------------------------------------------------------ +// Definitions for some processor registers in order to not include specific +// header file for various Cortex-M3 processor derivatives. +#define CPU_ICSR ( ( sfr_dword *) 0xE000ED04 ) // Interrupt Control State Register +#define CPU_SYSTICKCSR ( ( sfr_dword *) 0xE000E010 ) // SysTick Control and Status Register +#define CPU_SYSTICKCSR_EINT 0x02 // Bit for enable/disable SysTick interrupt + + +#endif /* DEVICE_H */
diff -r 000000000000 -r 9b057566f9ee scmRTOS/scmRTOS_TARGET_CFG.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/scmRTOS_TARGET_CFG.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,102 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PROCESSOR: ARM Cortex-M3 +//* +//* TOOLKIT: EWARM (IAR Systems) +//* +//* PURPOSE: Project Level Target Extensions Config +//* +//* Version: 3.10 +//* +//* $Revision: 196 $ +//* $Date:: 2008-06-19 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** +//* mbed port by Igor Skochinsky + +#ifndef scmRTOS_TARGET_CFG_H +#define scmRTOS_TARGET_CFG_H + +#include "device.h" + +// Define SysTick clock frequency and its interrupt rate in Hz. +#define SYSTICKFREQ 100000000 +#define SYSTICKINTRATE 1000 + +//------------------------------------------------------------------------------ +// +// System Timer stuff +// +// +namespace OS +{ +extern "C" void SysTick_Handler(); +} + +#define LOCK_SYSTEM_TIMER() ( *CPU_SYSTICKCSR &= ~CPU_SYSTICKCSR_EINT ) +#define UNLOCK_SYSTEM_TIMER() ( *CPU_SYSTICKCSR |= CPU_SYSTICKCSR_EINT ) + +//------------------------------------------------------------------------------ +// +// Context Switch ISR stuff +// +// +namespace OS +{ +#if scmRTOS_IDLE_HOOK_ENABLE == 1 + void IdleProcessUserHook(); +#endif + +#if scmRTOS_CONTEXT_SWITCH_SCHEME == 1 + + INLINE inline void RaiseContextSwitch() { *CPU_ICSR |= 0x10000000; } + + #define ENABLE_NESTED_INTERRUPTS() + + #if scmRTOS_SYSTIMER_NEST_INTS_ENABLE == 0 + #define DISABLE_NESTED_INTERRUPTS() TCritSect cs + #else + #define DISABLE_NESTED_INTERRUPTS() + #endif + +#else + #error "Cortex-M3 port supports software interrupt switch method only!" + +#endif // scmRTOS_CONTEXT_SWITCH_SCHEME + +} +//----------------------------------------------------------------------------- + +#endif // scmRTOS_TARGET_CFG_H +//----------------------------------------------------------------------------- +
diff -r 000000000000 -r 9b057566f9ee scmRTOS/scmRTOS_config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scmRTOS/scmRTOS_config.h Mon Nov 01 20:39:01 2010 +0000 @@ -0,0 +1,133 @@ +//****************************************************************************** +//* +//* FULLNAME: Single-Chip Microcontroller Real-Time Operating System +//* +//* NICKNAME: scmRTOS +//* +//* PROCESSOR: ARM Cortex-M3 +//* +//* TOOLKIT: EWARM (IAR Systems) +//* +//* PURPOSE: Project Level Configuration +//* +//* Version: 3.10 +//* +//* $Revision: 196 $ +//* $Date:: 2008-06-19 #$ +//* +//* Copyright (c) 2003-2010, Harry E. Zhurov +//* +//* Permission is hereby granted, free of charge, to any person +//* obtaining a copy of this software and associated documentation +//* files (the "Software"), to deal in the Software without restriction, +//* including without limitation the rights to use, copy, modify, merge, +//* publish, distribute, sublicense, and/or sell copies of the Software, +//* and to permit persons to whom the Software is furnished to do so, +//* subject to the following conditions: +//* +//* The above copyright notice and this permission notice shall be included +//* in all copies or substantial portions of the Software. +//* +//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +//* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//* +//* ================================================================= +//* See http://scmrtos.sourceforge.net for documentation, latest +//* information, license and contact details. +//* ================================================================= +//* +//****************************************************************************** +//* Ported by Andrey Chuikin, Copyright (c) 2008-2010 + +#ifndef scmRTOS_CONFIG_H +#define scmRTOS_CONFIG_H + +#ifndef __IAR_SYSTEMS_ASM__ +#include <commdefs.h> + +typedef word TTimeout; + +#endif // __IAR_SYSTEMS_ASM__ + +#include "device.h" +//------------------------------------------------------------------------------ +// +// Specify scmRTOS Process Count. Must be less than 31 +// +// +#define scmRTOS_PROCESS_COUNT 7 + +//----------------------------------------------------------------------------- +// +// scmRTOS System Timer +// +// Nested Interrupts enable macro. Value 1 means that interrupts are +// globally enabled within System Timer ISR (this is default for Cortex-M3). +// +// +#define scmRTOS_SYSTIMER_NEST_INTS_ENABLE 1 + +//----------------------------------------------------------------------------- +// +// scmRTOS System Timer Tick Counter Enable +// +// +#define scmRTOS_SYSTEM_TICKS_ENABLE 1 + + +//----------------------------------------------------------------------------- +// +// scmRTOS System Timer Hook +// +// +#define scmRTOS_SYSTIMER_HOOK_ENABLE 1 + +//----------------------------------------------------------------------------- +// +// scmRTOS Idle Process Hook +// +// +#define scmRTOS_IDLE_HOOK_ENABLE 1 + +//----------------------------------------------------------------------------- +// +// scmRTOS Idle Process Stack size (in bytes) +// (20 * sizeof(TStackItem)) - it's a minimum allowed value. +// +#define scmRTOS_IDLE_PROCESS_STACK_SIZE (20 * sizeof(TStackItem)) + +//----------------------------------------------------------------------------- +// +// scmRTOS Priority Order +// +// This macro defines the order of the process's priorities. Default, +// the ascending order is used. Alternatively, the descending priority +// order can be used. On some platforms the descending order is preferred +// because of performance. +// +// Default (corresponding to ascending order) value of macro is 0. +// Alternative (corresponding to descending order) value of macro is 1. +// +// On Cortex-M3 the descending order is preferred for performance reason. +// +#define scmRTOS_PRIORITY_ORDER 1 + +//----------------------------------------------------------------------------- +// +// scmRTOS Context Switch User Hook enable +// +// The macro enables/disables user defined hook called from system +// Context Switch Hook function. +// +// +#define scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE 0 + + +#endif // scmRTOS_CONFIG_H +//----------------------------------------------------------------------------- +