|
|
View previous topic :: View next topic |
Author |
Message |
EM
Joined: 17 Jul 2011 Posts: 4
|
RTOS Task not executing |
Posted: Sun Jul 17, 2011 2:35 pm |
|
|
Hello,
The last RTOS task listed will not run no matter which of the tasks I list last. All other task work as expected. One thing I noticed is that the last task memory locations are not consecutive like the others per the .SYM file. If I delete some of the unused variables (I stripped the use of them out to list here) then the last task memory locations move up and are consecutive and I get a different operating behavior. I need the extra variables in the final code, any ideas? I am using the latest PCW 4.122 compiler.
Part of the .SYM file:
052-058 @TASKINFO1_2_2_0_0
059-05F @TASKINFO2_2_2_0_0
060-066 @TASKINFO3_2_2_0_0
067-06D @TASKINFO4_2_2_0_0
06E-06F,0A0-0A4 @TASKINFO5_2_2_0_0
Code: |
#include "rtos.h"
#include <string.h>
#include <stdlib.h>
unsigned int16 adc_reading;
unsigned int16 gp_high_side;
unsigned int16 gp_low_side;
unsigned int16 temp_c;
unsigned int16 supply_volts;
unsigned char adc_channel;
unsigned char string1[10], duty_cycle_pwm;
unsigned int16 initial_resistance_setting, final_resistance_setting;
unsigned int16 resistance, current;
unsigned char under_voltage_alarm, over_current_alarm, excessive_resistance_alarm, over_temp_alarm;
unsigned char present_switch, previous_switch, switch_pressed, switch_toggled;
unsigned char power_on;
unsigned int16 timeout_cntr;
unsigned char temp;
unsigned char print_variable;
#use rtos(timer=0,minor_cycle=5ms)
#task(rate=40ms, max=1ms)
void startup();
#task(rate=1s, max=5ms)
void display();
#task(rate=40ms, max=1ms)
void switches();
#task(rate=40ms, max=1ms)
void Get_adc_readings();
#task(rate=40ms, max=1ms)
void control_gp();
void startup()
{
timeout_cntr = 0;
}
void display()
{
printf("%Lu0mO ",resistance);
}
void switches()
{ // the first part debounces the switch and gives present state and toggled state
present_switch = input(POWER_SW); // get switch value
if (previous_switch == present_switch) {
if (!present_switch) { // switch is pressed
if (!switch_pressed) // if it was not pressed
switch_toggled = true; // then set that it toggled states
else // else it did not toggle states
switch_toggled = false;
switch_pressed = true; // set the current switch state
}
else { // switch is released
switch_pressed = false; // set the current switch state
}
}
previous_switch = present_switch; // save switch history
if(switch_toggled) {
switch_toggled = false;
if(!power_on) {
power_on = true;
duty_cycle_pwm = 255;
set_pwm1_duty(duty_cycle_pwm); // turn on glow plug
}
else {
power_on = false;
duty_cycle_pwm = 0;
set_pwm1_duty(duty_cycle_pwm); // shut off glow plug
}
}
}
void Get_adc_readings()
{
adc_reading = 0;
}
void control_gp()
{
set_pwm1_duty(duty_cycle_pwm);
}
void main()
{
setup_adc_ports(sAN0 | sAN1 | sAN2 | sAN3 | sAN4 | sAN8 | VSS_VDD);
setup_adc(ADC_CLOCK_DIV_16); //1us Tad * 11 = 11us conversion rate
// setup_spi(SPI_SS_DISABLED);
// setup_lcd(LCD_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_2(T2_DIV_BY_4,255,1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(0);
// setup_comparator(NC_NC_NC_NC);
setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_PLL_ON,0);
power_on = false;
switch_pressed = false;
previous_switch = false;
switch_toggled = false;
duty_cycle_pwm = 0; // start with the glow plug on
set_pwm1_duty(duty_cycle_pwm);
adc_channel = 0;
set_adc_channel(adc_channel); // start with channel 0
delay_us(100); // adc settle time
initial_resistance_setting = 100;
final_resistance_setting = 100;
rtos_run(); // start the operating system
}
|
|
|
|
Sergeant82d
Joined: 01 Nov 2009 Posts: 55 Location: Central Oklahoma
|
|
Posted: Sun Jul 17, 2011 2:38 pm |
|
|
Off the top of my head, I would guess it is a problem with memory banking. You might look into setting specific memory addresses for different variables, etc., and see if that helps. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Jul 17, 2011 4:00 pm |
|
|
I try to minimize the use of multiple threads in my projects because they often create difficult to find problems. When you take care most projects can be set up single threaded, especially in a simple processor like the PIC where the project at hand is always of manageable size. Please note, I do like the concept of threads and use them in my larger Linux projects, but I've seen lot of starting programmers to use threads when there was no need to. Don't create threads because you can, but only when you must.
Many more people adhere to the above design philosophy and that is one of the reasons the RTOS functionality is used in few projects. Consequently the RTOS is not well tested and you might very well have found a bug in the CCS code.
One good hint I can give you is to use less global variables. Use local variables whenever you can for two reasons:
1) From a local variable it is directly visible that it is only being used within this single function. This reduction of scope makes it for you (and other programmers) much easier to understand the code when you have to look at it again in another year or so.
2) The compiler will deduct from the variable scope that it is possible to re-use the same memory inside another function. This will save you precious RAM memory.
Another hint: Functions are designed with the feature to accept parameters and return a value. Use this feature! It will make your code more modular and is one of the most important software design issues.
Giving more hints to your particular problem is difficult because you posted an incomplete program and didn't even mention your processor type. |
|
|
EM
Joined: 17 Jul 2011 Posts: 4
|
|
Posted: Sun Jul 17, 2011 4:02 pm |
|
|
Thanks for the reply, I tried something along the lines of what you said, I reordered the task definitions and the variable definitions like this:
Code: |
#include "rtos.h"
#include <string.h>
#include <stdlib.h>
#use rtos(timer=0,minor_cycle=5ms)
#task(rate=40ms, max=1ms)
void startup();
#task(rate=1s, max=5ms)
void display();
#task(rate=40ms, max=1ms)
void switches();
#task(rate=40ms, max=1ms)
void Get_adc_readings();
#task(rate=40ms, max=1ms)
void control_gp();
unsigned int16 adc_reading;
unsigned int16 gp_high_side;
unsigned int16 gp_low_side;
unsigned int16 temp_c;
unsigned int16 supply_volts;
unsigned char adc_channel;
unsigned char string1[10], duty_cycle_pwm;
unsigned int16 initial_resistance_setting, final_resistance_setting;
unsigned int16 resistance, current;
unsigned char under_voltage_alarm, over_current_alarm, excessive_resistance_alarm, over_temp_alarm;
unsigned char present_switch, previous_switch, switch_pressed, switch_toggled;
unsigned char power_on;
unsigned int16 timeout_cntr;
unsigned char temp;
unsigned char print_variable;
|
and now all of the tasks work but some of the variables do not hold the right content. I think I will stop using the RTOS and go back to the old loop code because the time I would have saved using the RTOS has been spent and then some on debugging the memory issue. I will send the stuff to CCS to see if there is a bug or if it is me. Thanks again. |
|
|
EM
Joined: 17 Jul 2011 Posts: 4
|
|
Posted: Sun Jul 17, 2011 4:20 pm |
|
|
Quote: | I try to minimize the use of multiple threads in my projects because they often create difficult to find problems. When you take care most projects can be set up single threaded, especially in a simple processor like the PIC where the project at hand is always of manageable size. Please note, I do like the concept of threads and use them in my larger Linux projects, but I've seen lot of starting programmers to use threads when there was no need to. Don't create threads because you can, but only when you must. |
I agree and I tried to minimize the number of threads but I also used more threads so the code would be more modular and easy to understand.
Quote: |
One good hint I can give you is to use less global variables. Use local variables whenever you can for two reasons:
1) From a local variable it is directly visible that it is only being used within this single function. This reduction of scope makes it for you (and other programmers) much easier to understand the code when you have to look at it again in another year or so.
2) The compiler will deduct from the variable scope that it is possible to re-use the same memory inside another function. This will save you precious RAM memory. |
I agree and I usually do, but this is my first full RTOS program and I used globals to share data across the tasks instead of a bunch of queues. But looking at it again, your right I can make a lot of them locals.
Quote: |
Another hint: Functions are designed with the feature to accept parameters and return a value. Use this feature! It will make your code more modular and is one of the most important software design issues. |
I thought I did. Did I miss some?
Quote: | Giving more hints to your particular problem is difficult because you posted an incomplete program and didn't even mention your processor type. |
Sorry my first post to this site. The chip is a PIC16F1936, the listing above is the full program except for RTOS.H which is here:
Code: |
#include "16F1936.h"
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES WDT_SW //No Watch Dog Timer, enabled in Software
#FUSES NOPUT //No Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOCLKOUT //I/O function on OSC2
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOWRT //Program memory not write protected
#FUSES NOVCAP //VCAP pin disabled
#FUSES PLL //4X HW PLL enabled
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES BORV25 //Brownout reset at 2.5V
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(int=8000000)
#define VSNSH PIN_A0
#define VSNSL PIN_A1
#define ISNS1 PIN_A2
#define ISNS2 PIN_A3
#define TEMP_SENSOR PIN_A5
#define POWER_LED PIN_A6
#define GLOWPLUG_LED PIN_A7
#define POWER_SW PIN_B0
#define POWER_SUPPLY PIN_B2
//#define GLOW_PLUG PIN_C2
#define TXMTR PIN_C6
#define RCVR PIN_C7
#use rs232(baud=19200,parity=N,xmit=TXMTR,rcv=RCVR,bits=8)
|
Thank you for taking the time to answer my question and all of the helpful hints. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|