Part Number: PROCESSOR-SDK-AM335X
Other Parts Discussed in Thread: SYSBIOS
Hello,
I ran into this problem with processor_sdk_rtos_am335x_6_03_00_106.
Specifically BIOS 6.76, XDC 3.55 and GNUC 7.3.1
When calling "BIOS_exit()" is doesn't. Other tasks continue to run.
I was able to verify this with the program below. Only the core mainline is included, all other support files are readily available in packages.
The process is as follows:
- Create a two tasks
- A task A whose job is is wait for a bit, post a message to a mailbox in the other task
- A task B to get the mailbox message and react to it, then loop back to get another message
- Task A waits, then sends the message to task B. Then waits some more
- Task B sees the message and prints a message, then waits for another message
- Task A sends a "shutdown" message to Task B
- Task B sees the message, can do whatever cleanup it needs and acknowledges is. Then waits for another message
- Task A sees the acknowledgement and registers an "System_atexit" fuction them calls BIOS_exit() (at line 67)
The registered function does not execute completely. Sometimes it executes partially before SYSBIOS issues an ASSERT().
After extensive investigation, what is happening is:
The system scheduler does NOT get stopped. It is still handing out time to task B, and Task B enters the Mailbox_pend() call. Which then commences to fail, as Mailbox_pend() calls Semaphore_pend(), and Semaphore_pend asserts because the thread type is not a "task" thread.
Therefore, I have to conclude this is a defect, because the scheduler is handing time slices to Trask B, but has set it's thread type to something other than a thread. It should STOP handing out time slices to that or any other task.
NOTE: This behavior is NOT occurring with the following packages: BIOS 6.46.05.55, XDC 3.32.02.25, TI compiler 17.3.0 STS. I have tested extensively using this same code, and different packages.
(Of course I can't "insert code" because this site is still broken. So I pasted it, and lost all the formatting. I am NOT going to waste time cleaning it up)
/*
* ======== main.c ========
*/
#include <xdc/std.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Mailbox.h>
#include <ti/sysbios/knl/Semaphore.h>
#include "soc_AM335x.h" /* Hardware addresses for this Sitara */
#include "cp15.h"
#include <UARTStdio.h>
typedef enum MESSAGE_TYPES
{
MSG_INIT=0,
MSG_SHUTDOWN
} MESSAGE_TYPES;
typedef struct MsgObj {
unsigned char msgId;
} MSG_OBJ;
void PeriodicTaskInit(void);
void PeriodicMailboxInit(void);
Semaphore_Handle semShutdownComplete;
static char PeriodicTaskName[] = "PeriodicTask";
Mailbox_Handle mPeriodicMailbox;
void TaskPeriodic(UArg a0, UArg a1);
void MMUConfigure(void);
void callme_when_sysbios_exits(int status) {
UARTprintf("Cleaning up\n");
Semaphore_delete(&semShutdownComplete);
UARTprintf("Deleted Semaphore\n");
Mailbox_delete(&mPeriodicMailbox);
UARTprintf("Deleted Mailbox\n");
}
/*
* ======== taskFxn ========
*/
Void taskFxn(UArg a0, UArg a1) {
MSG_OBJ msg;
msg.msgId = MSG_INIT;
UARTprintf("enter taskFxn()\n");
Task_sleep(5000);
UARTprintf("posting INIT to other task\n");
Mailbox_post(mPeriodicMailbox,&msg, BIOS_WAIT_FOREVER);
Task_sleep(5000);
UARTprintf("posting SHUTDOWN to other task\n");
msg.msgId = MSG_SHUTDOWN;
Mailbox_post(mPeriodicMailbox,&msg, BIOS_WAIT_FOREVER);
Semaphore_pend(semShutdownComplete, BIOS_WAIT_FOREVER);
System_atexit(callme_when_sysbios_exits);
UARTprintf("Halting BIOS\n");
BIOS_exit(0);
UARTprintf("exit taskFxn()\n");
}
/*
* ======== main ========
*/
Int main()
{
Task_Handle task;
Error_Block eb;
MMUConfigure();
UARTStdioInit();
UARTprintf("enter main()\n");
Semaphore_Params sem_params;
Semaphore_Params_init(&sem_params);
sem_params.mode = Semaphore_Mode_COUNTING;
semShutdownComplete = Semaphore_create(1, &sem_params, NULL);
Error_init(&eb);
task = Task_create(taskFxn, NULL, &eb);
if (task == NULL) {
UARTprintf("Task_create() failed!\n");
BIOS_exit(0);
}
PeriodicTaskInit();
BIOS_start(); /* does not return */
return(0);
}
void PeriodicTaskInit(void)
{
Task_Params taskParams;
Task_Handle task;
Error_Block eb;
PeriodicMailboxInit();
Task_Params_init(&taskParams);
taskParams.priority = 14;
taskParams.instance->name = PeriodicTaskName;
UARTprintf("\nCreating task: %s...", PeriodicTaskName);
Error_init(&eb);
task = Task_create(TaskPeriodic, &taskParams, &eb);
if (task == NULL)
{
BIOS_exit(0);
}
UARTprintf("Task_Handle_name()= %s\n",Task_Handle_name(task));
return;
}
void PeriodicMailboxInit(void)
{
Error_Block eb;
Error_init(&eb);
mPeriodicMailbox = Mailbox_create(sizeof(MSG_OBJ), 50, NULL, &eb);
if (mPeriodicMailbox == NULL)
{
BIOS_exit(0);
}
}
void TaskPeriodic(UArg a0, UArg a1) {
MSG_OBJ msg;
Task_Handle handle;
handle = Task_self();
while(1) {
if (Mailbox_pend(mPeriodicMailbox, &msg, 1) == TRUE) { //wait for a message or 1 timer tick
switch(msg.msgId)
{
case MSG_INIT:
UARTprintf("Task Started %x\n", handle);
break;
case MSG_SHUTDOWN :
UARTprintf("Periodic: MSG_SHUTDOWN. Cleaning up TaskPeriodic...OK\n");
Semaphore_post(semShutdownComplete);
break;
default:
break;
}
} else {
/// Do other things...
}
}
}
#define RGN_L2_WBWA (0x08)
void MMUConfigure(void) {
unsigned int * tableBase;
unsigned int * base;
tableBase = CP15GetTableBase();
/* based on a 1Meg Page, there are 4096 pages = 4Gig
* page 0x44e is Periph registers, and entry # 1102 in the list, (X 4 bytes = 4408 bytes, or 0x1138 ) */
base = tableBase + (SOC_CM_PER_REGS >> 20) ; // 0x44e;
/* AP [1:0] are bits [11,10] so 0xC00 + 0x10 for NX, and 0x02 for Valid Segment */
*base = ((SOC_CM_PER_REGS & 0xfff00000) | 0x0c12); /* ?? | 0x1e0e 0x0c12); */
/* Now compute the offset for the GPIO2 register, as it is not enabled by default either */
base = tableBase + (SOC_GPIO_2_REGS >> 20) ; // 0x481;
*base = ((SOC_GPIO_2_REGS & 0xfff00000) | 0x0c12); /* ?? | 0x1e0e 0x0c12); */
/* Now compute the offset for the Network CPSW module, as it is not enabled by default either */
base = tableBase + (SOC_CPSW_SS_REGS >> 20) ; // 0x4A1;
*base = ((SOC_CPSW_SS_REGS & 0xfff00000) | 0x0c12); /* ?? | 0x1e0e 0x0c12); */
/* Set TTB0 value. We use only TTB0 here (N = 0) */
CP15Ttb0Set(((unsigned int )tableBase) | RGN_L2_WBWA);
}