This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

PROCESSOR-SDK-AM335X: BIOS_exit() ... doesn't

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);
}

  • Hello,

    Thank you for reporting this. Our subject owner is on vacation this week. Please ping the thread if you do not get a response within a couple of business days.

    Regards,

    Nick

  • Hi Christopher,

    Thanks for posting your code. I looked at the code and it seems to me what could be happening was that your task A was preempted by task B during the exit operation. From the code you posted, I can see that your task A was created with default priority because taskParams is NULL. The default priority of a task is 1.

    task = Task_create(taskFxn, NULL, &eb);
    

    On the other hand, your talk B was created with priority 14:

    taskParams.priority = 14;
    ...
    task = Task_create(TaskPeriodic, &taskParams, &eb);

    Due to this priority setting, your task B always preempts task A whenever task B is not blocked. Although when BIOS_exit() is running, it should be out of task A context and shouldn't be preempted by task B, from what you described, it seemed task B got scheduled anyway.

    I agree that this could be a defect, but can you try to set your task A to have same or higher priority than task B and see if your problem goes away?

    Thanks and regards,

    Jianzhong

  • Jianzhong,

    Why should I continue to throw test code at it, acting like a hacking penetration test to figure out how something works, when you guys wrote this RTOS code and can just look??

    And you have the sample code to take and compile.

    Also, why does this exact same code (including the difference in task priorities) cleanly exit in the previous packages, but not this?  I've been lectured and scolded on this forum to get with the current packages.  Except they are introducing all kinds of new bugs.

    If this is a solution, it means changing the priorities of dozens of tasks... Clearly that is NOT a practical solution, tasks have priorities for a reason...

    Instead it would be necessary to modify every task to lower it's priority to below this one, before exiting BIOS to spawn the next process in the register exit call.  A rather invasive change, considering the previous packages did not have this problem.

    I don't recall seeing that is any release notes...  "Go modify EVERY task priority to the proper level or the System_atexit() register function will not complete cleanly, because the RTOS will crash"

  • Christopher,

    I agree with you that what I asked you to try is not a solution, but that can help us narrow down the problem.

    According to the release notes, BIOS 6.76.03.01 was validated against gcc-arm-none-eabi-7-2017-q4-major. Please check the Validation Information in the release notes. When you compile this version of BIOS with a different compiler, unexpected behaviors could happen. If you compile BIOS 6.76.03.01 and your test code with gcc-arm-none-eabi-7-2017-q4-major and still have the same problem, I can do some more investigations. 

    Thanks for your understanding.

    Regards,

    Jianzhong

  • Jianzhong,

    what are you talking about...?

    This compiler was PACKAGED with processor_sdk_rtos_am335x_6_03_00_106.  It contains ALL AND ONLY those packages and tools I said were used to replicate this problem.

    Again THEY ARE VALIDATED BY YOU PEOPLE AT TI.   Just Ask Frank Livingston.

    And I did NOT compile the BIOS.  It comes already compiled in the install.  As usual, I don't even see any instruction on how to compile it.  And why would I??  It's already build using THESE TOOLS which were VALIDATED BY TI.

    I did spend time repeating those tests...   Yes, the task priority DOES cause the crash in the packages that are installed with processor_sdk_rtos_am335x_6_03_00_106.

    Is there someone who understands this environment that I can communicate with??

  • Christopher,

    Thanks for doing the tests. That helps us understand the problem. Thanks also for confirming that you did not recompile BIOS. I was thinking if you use XDC configuration in your project, BIOS will be recompiled automatically. Looks like you're not doing that. 

    I'll try to build and run your test code myself later this week and see if there can be a solution. Also to let you know, we don't have a dedicated BIOS support team anymore. All BIOS related questions are supported by the product line teams.

    Thanks and best regards,

    Jianzhong

  • Jianzhong,

    The prebuild step which use the CFG file compiles "something".  That IS done by XDC...  But I have no idea what is builds.

    Then it links with files named oa8fg, aa8fg,... stuff like that. Some are in the actual project, some are referenced directly in the C:\Ti\bios_6_76... folders.

    So some of it is built INSIDE the project, some of it is linked to stuff OUTSIDE the project.

    if you use XDC configuration in your project, BIOS will be recompiled automatically.

    Is it??  Half the code it, and half the code isn't...  And the timestamps in C:\Ti\bios_6_76 have NOT changed.

    So I have no idea what "recompile the bios" means in this context.  XDC is doing stuff that isn't explained.

    The eco system does a good job of PREVENTING anyone from understanding how things are built.  

    So don't expect me to know whether XDC or the CFG file is recompiling a specific module/function or not.

    Historically, I have tried to follow the instructions to recompile the NDK, and that fails miserably.  And the only E2E reply I ever got on that was "yeah, we know something is broken..."  But nothing was fixed.

    So I do NOT recompile these packages outside of CCS, as they'll probably fail anyway.  And all that happens is whatever XDC does when I build a project in CCS

  • By the way...

    Do you see any actual question in my post??

    This is a defect.  I complain enough around here about the environment and support. So I wanted to contribute some information to help others.

    My decision was to post this information so others who may have these crashes can see what is causing it.

    And secondly, the post is to let the TI developers know how they introduced a defect with their updates.  Most likely because someone wanted to completely rewrite that code out of ego.

    I can get around it. There are a number of possible ways.

    This defect resulted in a lot more effort than expected to convert/update.