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.

SYS/BIOS project exception in memset

Other Parts Discussed in Thread: AM3358, SYSBIOS

Good morning,

I am seeing a strange exception in my SYS/BIOS project that I have been unable to remedy how ever can easily turn it on and off but would like to understand why it is happening.

The setup is a beaglebone black based board (AM3358, 512MB DDR3 etc) and the versions of various bits are as follows:

  • CCS v6.1.1.00022
  • Compiler GNU v4.8.4 (Linaro)
  • XDCtools version 3.31.0.24
  • SYS/BIOS 6.42.3.35

I have been getting this exception is strange places for a few days and depending on how its built it does or doesn't happen so I need to get to the bottom of it so it doesn't keep coming back to haunt us.

The exception occurs in code running in the programs idle loop and I think I have tracked it down to always happening either in or soon after a memset() and at the moment this piece of code causes it:

	       {
#define MAX_FILE_SIZE (1024*60)
                    unsigned char file_counter = 0;
                    unsigned char pkt_counter = 0;
                    unsigned char buffer[MAX_FILE_SIZE + 512] = {0,0};
                    WORD br;
                    FIL mobile_file;
                    FRESULT res;
                    buffer[0] = 0;
                    buffer[1] = 0;
                    oxts_stdout("SCom cfg req received.", "");

In this case I can see when stepping through the assembly that the initialization of the array 'buffer' triggers a memset() which causes the exception.  If i don't initialize it and just zero the first two bytes below (this code is in above from my testing) it works fine and doesn't crash.

After this piece of code it reads a series of files into &buffer[3] and sends them over a serial link to another processor this is using the FatFs library which also uses memset().  A couple of days ago it was crashing in the FatFs library at a memset() but after a lot of playing around it stopped and now it runs that code fine but not this bit?

With either build the buffer is at address 0x800e9dfc which is perfectly valid and I have tryed playing around with the stack which is currently at ~10MB with no joy.

I am running the code with a XDS100v2 debugger, hardware the same as the BBB.

Any help or suggestions would be appreciated and if someone could suggest a good source for getting any information about an exception in this processor/kernel that would be useful

Many thanks

  • More information:

    I tried zeroing the buffer with a for loop as follows

    #define MAX_FILE_SIZE (1024*60)
    {
       unsigned char buffer[MAX_FILE_SIZE + 512];
       {
          for(int i = 0; i < MAX_FILE_SIZE + 512; i++)
             buffer[i] = 0;
       }
    

    this also crashes, I monitored the value of i and this changes ie it doesn't always crash at a particular point.  I also noted that depending whether you just run the code or put a break point at the for loop (to see where i was in memory for example) makes a big difference as to where it crashes.  If the break point was there i was in the region of 0x2900 and if you didn't it was around 0x2400.  By changing i when the break point is hit or by lowering the size of the buffer you can make it go through the for loop but it crashes soon after.  the magic number to stop it crashing is bringing the buffer down to 572+512, creating a seperate 2 byte buffer does then crash it.  

    This screams stack overflow or corruption however:

    1. One of the files that gets read into he buffer is 1243 so we are over writing the same memory we are setting to 0's later with no issues but initializing it with 0's is an issue.
    2. The stack has been excessively set at 100MB to make sure this isn't the case.

    To simplify this further I put the following at the start of the idle loop:

    #define MAX_FILE_SIZE (1024*60)
    {
       unsigned char buffer[MAX_FILE_SIZE + 512];
       {
          for(int i = 0; i < MAX_FILE_SIZE + 512; i++)
             buffer[i] = 0;
       }
    }

    and it crashes in it the first time it runs so i cannot be related to any of my other code around it.  I put the same bit in a serial hardware interrupt and in main and it ran it fine so this is specific to idle functions.  Does anybody have any clue as to what is happening?

    Many thanks

    Sean

  • Hi Sean,

    Here are some suggestions:

    - If you disable interrupts while running this code, would it still crash? Just want to eliminate the fact that something asynchronous is inserting itself into the flow. Which also leads to the question: when you do this experiment in your last post, is there anything else (e.g. other Tasks, interrrupt handler) running in the system?
    - Use the RTOS Object View (ROV) to verify that Hwi stack and Task stacks are correctly sized and there is no overflow. Here's a little YouTube introduction video that shows how to launch it and inspect the Task module's Detailed tab with shows stack peak usage.
    - Are you running with optimization turned on? Just be aware that stepping thru optimized code is tricky and you basically have to rely on the disassembly view at all times.
    - Note that Idle functions are run in a special Task called the Idle Task that has its own stack. So again make sure you are sizing all Hwi and Task stacks correctly in ROV.
    - What type of exception are you getting? Do you see any error message? Is it always the same?

    Best regards,
    Vincent
  • Good afternoon Vincent,

    Thank you for you reply it has defiantly helped me in the right direction.  I have tasks turned off and the sys/bios manual states the following:

    7.5.1 System Stack You can configure the size of the System stack, which is used as the stack for hardware interrupts and software interrupts (and by the Idle functions if Task is disabled).

    Hence why I has set the program stack to 100MB to rule out stack overflow but I can see on the ROV tool that it does indeed have a separate stack and when the code has crashed it has overflowed.

    So now my question is how do I increase it.  The manual says to do this 'Task.idleTaskStackSize = 1024;' but I get an error that Task is not defined, this is quite reasonable as I have them disabled but how then do I change the Idle loops stack?

    I have enabled the Task module so the above command works and I don't get any crashes but can it be changed without enabling the task module just to do it?

    Also whilst I am on here could you tell me what the BIOS.cpuFreq.lo = 1000000000;  command is used for as when I set it to 1GHz my code wont debug it just gets an exception straight away however 900000000 is fine.  I seem to remember reading somewhere this was just for information is that correct?

    Many thanks

    Sean

  • Hi Sean,

    If you disable tasking by setting BIOS.taskEnabled to false in your .cfg file (is this how you did it?), the idle loop should run in the context of main() and use the system stack. If you select Task->Detailed tab in ROV is should say "No data to display". Are you not seeing this?

    BIOS.cpuFreq is used by SYS/BIOS to convert timer ticks into real-time units. It is important to set it correctly as it is sometimes used for sanity checking.

    Best regards,
    Vincent
  • Hi Vincent,

    In the graphical setup it was not ticked and i don't believe there was any mention of it in the script view.  Besides if it was not disable then I would not get the error that task was unrecognized when i tried to change the idle loop stack size surely?

    The Task detailed tab showed the information about the idle loop only.

    So it seems that the idle loop was still using its own stack with tasks disabled, however i can just leave the tasks enabled and it works like this.

    If BIOS.cpuFreq is important then please can you advice why i might get an exception before main when i set it correctly?  

    Also is there any more inormation any where regarding exactly what t is used for?  The cpu timers would not use the cpu freq as they run from the 24MHz crystal.

    Many thanks

    Sean

  • Hi Sean,

    To rule out any graphical rendering issue, you can put

    BIOS.taskEnabled = false;

    directly into your .cfg script file. I generally prefer to hand-edit the .cfg file just to be sure.

    What type of exception are you seeing? Is there any error message? I don't know what specifically could be giving you the exception, maybe you can try to debug this using CCS and narrow down on the function call that is causing the exception.

    Perhaps not in your particular case, but some platforms that are using ti.sysbios.timers.timer64.Timer for instance are leveraging BIOS.cpuFreq to compute the default Timer frequencies (you can look at ti/sysbios/timers/timer64/Timer.xs in you are curious). In general, there could also be software layers built on top of SYSBIOS that relies on the CPU frequency, so if cpuFreq is set incorrectly they could be affected and may throw an exception.

    Best regards,

    Vincent

  • Good morning Vincent,

    Regarding the cpu frequency the gel file sets it up differently if I don't use the gel file and just rely on by boot code to setup the memory and clocks it works fine.  So I guess SYS/BIOS must see that the cpu frequency is not as expected and error out.

    I am quite happy to keep tasks enables as I will probably make use of them at some point as the application matures so I am not going to investigate further.  It seems to me that the fact task was unrecognized shows that they were correctly disabled and the idle loop was still using its own separate stack.

    The code that caused the issue is now also in a swi so I am not in a position to repeat the issue without back tracking so I am not going to investigate further at this time.

    Many thanks for you help with this.

    Sean

  • Hi Sean,

    You are welcome. Regarding frequency check, I think you are correct. There is indeed one that is performed in the module ti.sysbios.timers.dmtimer.Timer, and it can be turned off by setting

    Timer.checkFrequency = false;

    in the .cfg file. I see the code is sanity-checking the Timer frequency against the Timestamp frequency, which is based on the CPU frequency retrieved using BIOS_getCpuFreq().

    Anyway, good luck in your project!

    Best regards,

    Vincent