Alrighty, for some reason it will build with the large memory model and not small, but I'm working on a small part of a larger project so there could very well just be other things elsewhere in code making that necessary. I do have to include effs thin pic24 library because someone else on the project needs that. But my current setup is: I've changed the settings to be for large code and large data models, I linked to libsalvolmcc30l-t.a, and I changed salvocfg.h to match what you posted. There seems to be
slightly more sanity now to what it's doing, but it's still not behaving properly.
I'm running two tasks, I'll refer to them as the primary and secondary task because the primary has a priority 0, and secondary a priority of 5 (for testing purposes only). The secondary is a infinite loop that increments a count and then calls os_yield(). The primary task is running some code to interact with what is essentially a command prompt on a chip connected to the pic via uart. In my code the 'command prompt' on the other chip is simply referred to as the monitor. For testing purposes I've thrown in a couple of calls to os_delay in the primary task in arbitrary places to make sure that everything is working. The primary task starts executing first and calls os_delay(), since there are no other eligible tasks the secondary task runs, and then the primary task resumes. But when I call os_delay from the primary task again the secondary task will not execute, the scheduler keeps getting called, but the secondary task never resumes execution. The primary task then resumes after the delay expires but does not finish before the whole program restarts spontaneously (gotta love magical restarts).
Here's the important bits of my code, please note that each call to usb_print() simply prints out to putty. The results I get from putty come after the code snippet.
- Code: Select all
//*******************************************************
// salvocfg.h
//*******************************************************
#define OSUSE_LIBRARY TRUE
#define OSLIBRARY_TYPE OSL
#define OSLIBRARY_CONFIG OST
#define OSEVENTS 2
#define OSEVENT_FLAGS 0
#define OSMESSAGE_QUEUES 0
#define OSTASKS 9
//*******************************************************
// main.c
//*******************************************************
int main(void)
{
OSInit();
//make sure SD card is off
csk_sd_pwr_off();
csk_sd_close();
InitializeTasksAndQueues();
char * msg = "initialized\r";
usb_print(msg, 12);
char* schedMsg = "Scheduling\r";
for (;;)
{
// Get and print the state of the secondary task
uint8 taskState = OSGetStateTask(P_BUSY_FUNC);
taskState += 48;
usb_print((char*)&taskState, 1);
usb_print(schedMsg, 11);
OSSched();
}
return 0;
}
void InitializeTasksAndQueues()
{
initRPP();
OSCreateTask(payloadTest, P_PAYLOAD_TEST, 0);
OSCreateTask(busyFunc, P_BUSY_FUNC, 5);
//Timer 2 setup (system heartbeat that dives the soft clock)
T2CON = 0; //Clear the timer
TMR2 = 0; //reset the counter to 0
PR2 = TIMER2_PERIOD; // //Set the period FCY * desired period
IPC1bits.T2IP = 1;
IFS0bits.T2IF = 0; //clear the interrupt flag
IEC0bits.T2IE = 1; //Enable the interrupt
T2CONbits.TON = 1;
}
// Secondary task
void busyFunc()
{
int i = 0;
while(true)
{
char* busyMsg = "busy";
usb_print(busyMsg, 4);
int eligible = OSAnyEligibleTasks();
if(eligible) // Never resolves to true
{
char* msg = "task available\r";
usb_print(msg, 15);
OS_Yield();
}
if(i == 20)
{
char* carReturn = "\r";
usb_print(carReturn, strlen(carReturn));
OS_Yield();
}
i++;
}
}
void __attribute__((__auto_psv__, __interrupt__)) _T2Interrupt(void)
{
// drive the salvo heartbeat
OSTimer();
//Clear the interrupt flag
IFS0bits.T2IF = 0;
}
//*******************************************************
// payloadSystem.c
//*******************************************************
// Primary task
/**
* @brief Driver for testing. Simply calls the payload_init function which attempts
* sending an echo and setting some of the vdip's settings.
*/
void payloadTest(void)
{
while(true)
{
char* msg = "in payload interface\r";
usb_print(msg, strlen(msg));
OS_Delay(10); // Arbitrary delay to test salvo functionality
payload_init();
}
}
/**
* @brief Initializes the usb monitor
*/
void payload_init()
{
monitor_init();
}
//*******************************************************
// usbMonitorInterface.c
//*******************************************************
/**
* @brief Sends an echo to make sure we are properly synched and sets the
* appropriate initial settings for the usb monitor.
*
* @return true if synch and setting initialization is successful, otherwise
* return false
*/
uint8 monitor_init()
{
char* msg = "In init function\r";
usb_print(msg, strlen(msg));
// Initial state of the monitor after restart
monitorState.isSynced = false;
monitorState.commandSet = ECS;
monitorState.numericalMode = BINARY;
monitorState.isPortSet = false;
char* msg2 = "attempting echo\r";
usb_print(msg2, strlen(msg2));
if(monitor_echo())
{
char* successMsg = "echo success in monitor_init()\r";
usb_print(successMsg, strlen(successMsg));
monitorState.isSynced = true;
}
else
{
char* failureMsg = "echo failure\r";
usb_print(failureMsg, strlen(failureMsg));
return false;
}
return false;
}
/**
* @brief Sends an echo to the monitor, and if an echo is received back then it
* returns true
*
* @return true (1) if echo is successful, else false (0)
*/
uint8 monitor_echo()
{
//debug messages
char* msg = "In echo cmd\r";
usb_print(msg, 12);
OS_Delay(100);
// Create monitor echo cmd
static char echo[] = {'e', '\r'};
// Write out the cmd, then read from uart1
serial_write((uint8*)(echo), 2); // Write echo to monitor
monitorBuffDataLen = serial_read(aMonitorBuff, 2); // Read back from monitor
// If 'e' was sent back, then the echo was successful
if(aMonitorBuff[0] == 'e')
{
char* success = "echo successful in monitor_echo()\r";
usb_print(success, strlen(success));
return true;
}
else
{
return false;
}
}
The output I get is as follows:
initialized
5Scheduling
in payload interface
0Scheduling
busybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusy
0Scheduling
In init function
attempting echo
In echo cmd
3Scheduling
2Scheduling
2Scheduling
2Scheduling
2Scheduling
2Scheduling
2Scheduling
2Scheduling
2Scheduling
2Scheduling
2Scheduling
2Scheduling
1Scheduling
1Scheduling
1Scheduling
1Scheduling
1Scheduling
1Scheduling
1Scheduling
1Scheduling
1Scheduling
1Scheduling
1Scheduling
1Scheduling
1Scheduling
1Scheduling
0Scheduling
0Scheduling
0Scheduling
0Scheduling
0Scheduling
0Scheduling
0Scheduling
0Scheduling
0Scheduling
0Scheduling
0Scheduling
0Scheduling
in serial write
successfully cleared buff
successful Tx: e
in serial read: e
leaving read function
echo successful in monitor_echo()
initialized
5Scheduling
in payload interface
0Scheduling
busybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusybusy
As you can see a few lines from the end it prints 'initialized' again, which means the the program completely restarted, but the primary task hasn't finished because it should have printed 'echo success in monitor_init()\r' and it's also in a loop anyway so it should just start over. And in the large chunk where it's repeatedly printing 'Scheduling' it should have resumed the secondary task that would print 'busy' 20 times. And printing the result of OSGetStateTask(P_BUSY_FUNC) which is called just before printing 'Scheduling' just appears to be decrementing for no reason, even though the task should be in the eligible state that whole time (or at the very least it should be stuck in just one state, not changing). If I double the delay at that point it will start the number that OSGetStateTask(P_BUSY_FUNC) returns at 6 and then decrement to 0, instead of starting at 3.
I've been tearing through salvo's documentation thinking maybe I'm just misunderstanding how salvo is supposed to be interacted with, but to my understanding this all should be valid and should be switching between tasks just fine. I don't know why it won't execute the secondary task after the second time my primary task calls os_delay, and I have no earthly clue what could be causing the whole program to restart before the primary task fully finishes.