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.

AM3359: Jitter in HWI using SYS/BIOS 6.73

Part Number: AM3359

Tool/software:

Hi,

I've been trying to do some system optimization on a design I inherited. This is an EtherCAT design that uses distributed clocks, and so there is a periodic 1ms interrupt provided by the PRU (sync0 interrupt) that is instantiated as a HWI. I notice some strange behavior with it though. This design has a number of tasks, and with all the tasks enabled, I see approximately 10us of jitter in this interrupt. Now if I disable most tasks and leave only the essential ones, I see jitter values of ~1-2us. I am confused why having additional tasks adds jitter to a HWI. I thought this interrupt should preempt everything, and regardless of how many tasks there are, it should just be a single context switch from whatever task was running to the ISR right? Am I missing something with how SYS/BIOS works?

Thanks,

Keith

  • Hi Keith,

    Please give me some time to check this internally. I do understand your concern and I will get back to you by Tuesday.

    Regards,

    Aaron 

  • Thanks Aaron, appreciate your help on the previous topic as well, it has already helped immensely.

  • Thank you for your patience Keith.

    Regards,

    Aaron

  • Hi Keith,

    There is an option to configure HWI priority and maskSetting. Can you modify the registerInterrupt API to use the priority argument?

    Regards,

    Aaron

  • Hi Aaron,

    So I already did that actually. I modified where the Sync0 interrupt gets registered in osdrv_pruss.c. See blow code snippet:

    Hwi_Params_init(&hwiParams);
    hwiParams.arg = pruEvtoutNum;
    if(pruEvtoutNum == 20)
    {
    hwiParams.priority = 2;
    hwiParams.maskSetting = Hwi_MaskingOption_ALL;
    }
    else
    {
    hwiParams.priority = pruEvtoutNum;
    hwiParams.maskSetting = Hwi_MaskingOption_LOWER;
    }

    Essentially just added the priority = 2 (is that the highest possible priority?) as well as the mask all option. And then left the rest of the HWIs alone. I was able to reduce some of the HWI jitter by playing with the sys/bios settings. This is what I have right now. Is there any further optimization there that I can do? I am at ~+/-5us of jitter on this HWI

    var Defaults = xdc.useModule('xdc.runtime.Defaults');
    var Main = xdc.useModule('xdc.runtime.Main');
    var Memory = xdc.useModule('xdc.runtime.Memory')
    var SysMin = xdc.useModule('xdc.runtime.SysMin');
    var System = xdc.useModule('xdc.runtime.System');
    var Text = xdc.useModule('xdc.runtime.Text');
     
    var BIOS = xdc.useModule('ti.sysbios.BIOS');
    var Clock = xdc.useModule('ti.sysbios.knl.Clock');
    var Swi = xdc.useModule('ti.sysbios.knl.Swi');
    var Task = xdc.useModule('ti.sysbios.knl.Task');
    var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
    var Hwi = xdc.useModule('ti.sysbios.family.arm.a8.intcps.Hwi');
    var Mmu = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');
    var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
    var Timer = xdc.useModule('ti.sysbios.timers.dmtimer.Timer');
    var Load = xdc.useModule('ti.sysbios.utils.Load');
    var ti_sysbios_hal_Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
    var HeapBuf = xdc.useModule('ti.sysbios.heaps.HeapBuf');
    var Cache = xdc.useModule('ti.sysbios.hal.Cache');
    var ti_sysbios_family_arm_a8_Cache = xdc.useModule('ti.sysbios.family.arm.a8.Cache');
    
    var ti_sysbios_hal_Timer = xdc.useModule('ti.sysbios.hal.Timer');
    /* 
     * Program.argSize sets the size of the .args section. 
     * The examples don't use command line args so argSize is set to 0.
     */
    Program.argSize = 0x0;
    
    /*
     * Uncomment this line to globally disable Asserts.
     * All modules inherit the default from the 'Defaults' module.  You
     * can override these defaults on a per-module basis using Module.common$. 
     * Disabling Asserts will save code space and improve runtime performance.
    Defaults.common$.diags_ASSERT = Diags.ALWAYS_OFF;
     */
    
    /*
     * Uncomment this line to keep module names from being loaded on the target.
     * The module name strings are placed in the .const section. Setting this
     * parameter to false will save space in the .const section.  Error and
     * Assert messages will contain an "unknown module" prefix instead
     * of the actual module name.
    Defaults.common$.namedModule = false;
     */
    
    /*
     * Minimize exit handler array in System.  The System module includes
     * an array of functions that are registered with System_atexit() to be
     * called by System_exit().
     */
    System.maxAtexitHandlers = 1;       
    
    /* 
     * Uncomment this line to disable the Error print function.  
     * We lose error information when this is disabled since the errors are
     * not printed.  Disabling the raiseHook will save some code space if
     * your app is not using System_printf() since the Error_print() function
     * calls System_printf().
    Error.raiseHook = null;
     */
    
    /* 
     * Uncomment this line to keep Error, Assert, and Log strings from being
     * loaded on the target.  These strings are placed in the .const section.
     * Setting this parameter to false will save space in the .const section.
     * Error, Assert and Log message will print raw ids and args instead of
     * a formatted message.
    Text.isLoaded = false;
     */
    
    /*
     * Uncomment this line to disable the output of characters by SysMin
     * when the program exits.  SysMin writes characters to a circular buffer.
     * This buffer can be viewed using the SysMin Output view in ROV.
    SysMin.flushAtExit = false;
     */
    
    /*
     * The BIOS module will create the default heap for the system.
     * Specify the size of this default heap.
     */
    //BIOS.heapSize = 16000;
    //BIOS.heapSize = 24000;
    BIOS.heapSize = 0x10000;
    
    /* System stack size (used by ISRs and Swis) */
    //Program.stack = 0x2000;
    //Program.stack = 0x3000;
    //Program.stack = 0x4000;
    Program.stack = 0x10000;
    
    /* Circular buffer size for System_printf() */
    //SysMin.bufSize = 0x200;
    SysMin.bufSize = 0x400;
    
    System.SupportProxy = SysMin;
    
    Mmu.enableMMU = false;
    
    
    Swi.common$.namedInstance = true;
    
    BIOS.libType = BIOS.LibType_Custom;
    BIOS.customCCOpts = "--endian=little -mv7A8 --abi=eabi --neon --float_support=vfpv3 -q -ms --opt_for_speed=2  --program_level_compile -o3";
    BIOS.assertsEnabled = false;
    Program.sectionsExclude = ".*";
    Hwi.fiqStackSize = 0;
    Clock.tickPeriod = 1000;
    ti_sysbios_hal_Hwi.dispatcherSwiSupport = true;
    ti_sysbios_hal_Hwi.dispatcherAutoNestingSupport = true;
    ti_sysbios_hal_Hwi.initStackFlag = true;
    ti_sysbios_hal_Hwi.checkStackFlag = false;
    BIOS.logsEnabled = false;
    BIOS.swiEnabled = true;
    Task.initStackFlag = true;
    Task.checkStackFlag = false;
    ti_sysbios_hal_Hwi.dispatcherTaskSupport = true;
    
    var SEM_LCD_STARTParams = new Semaphore.Params();
    SEM_LCD_STARTParams.instance.name = "SEM_LCD_START";
    Program.global.SEM_LCD_START = Semaphore.create(0, SEM_LCD_STARTParams);
    
    var SEM_HEATER_CONTROLParams = new Semaphore.Params();
    SEM_HEATER_CONTROLParams.instance.name = "SEM_HEATER_CONTROL";
    Program.global.SEM_HEATER_CONTROL = Semaphore.create(0, SEM_HEATER_CONTROLParams);
    
    var task3Params = new Task.Params();
    task3Params.instance.name = "Task_HEARTBEAT";
    task3Params.priority = 2;
    Program.global.Task_HEARTBEAT = Task.create("&Task_Heartbeat", task3Params);
    
    var semaphore4Params = new Semaphore.Params();
    semaphore4Params.instance.name = "SEM_HEARTBEAT";
    Program.global.SEM_HEARTBEAT = Semaphore.create(null, semaphore4Params);
    
    var semaphore5Params = new Semaphore.Params();
    semaphore5Params.instance.name = "SEM_LED_TASK";
    Program.global.SEM_LED_TASK = Semaphore.create(null, semaphore5Params);
    
    var TasK_LCD_DISPLAYParams = new Task.Params();
    TasK_LCD_DISPLAYParams.instance.name = "Task_LCD_DISPLAY";
    TasK_LCD_DISPLAYParams.priority = 1;
    Program.global.Task_LCD_DISPLAY = Task.create("&Task_LCD_Display", TasK_LCD_DISPLAYParams);
    
    var Task_HC_HEATER_CONTROLParams = new Task.Params();
    Task_HC_HEATER_CONTROLParams.instance.name = "Task_HC_HEATER_CONTROL";
    Task_HC_HEATER_CONTROLParams.priority = 4;
    Program.global.Task_HC_HEATER_CONTROL = Task.create("&Task_HEATER_CONTROL", Task_HC_HEATER_CONTROLParams);
    
    var Task_100MSParams = new Task.Params();
    Task_100MSParams.instance.name = "Task_100MS";
    Task_100MSParams.priority = 3;
    Program.global.Task_100MS = Task.create("&Clock_100ms", Task_HC_HEATER_CONTROLParams);
    
    var semaphore6Params = new Semaphore.Params();
    semaphore6Params.instance.name = "SEM_100MS_TASK";
    Program.global.SEM_100MS_TASK = Semaphore.create(0, semaphore6Params);
    
    var SEM_ECATParams = new Semaphore.Params();
    SEM_ECATParams.instance.name = "SEM_ECAT";
    Program.global.SEM_ECAT = Semaphore.create(0, SEM_ECATParams);
    
    var SEM_ADC_ANALParams = new Semaphore.Params();
    SEM_ADC_ANALParams.instance.name = "SEM_ADC";
    Program.global.SEM_ADC_ANAL = Semaphore.create(0, SEM_ADC_ANALParams);
    
    
    Clock.tickSource = Clock.TickSource_TIMER;
    
    Task.idleTaskStackSize = 8192;
    Task.defaultStackSize = 16384;
    
    
    BIOS.cpuFreq.lo = 800000000;
    
    Clock.timerId = 0;
    
    Timer.intFreq.lo = 32768;
    Timer.intFreq.hi = 0;
    
    Load.swiEnabled = false;
    Load.hwiEnabled = false;
    Load.taskEnabled = false;
    
    Clock.swiPriority = 0;
    

  • Hi Keith,

    Can you try a higher number (say 15) as the priority. For SYS/BIOS, 15 is the highest priority. Also change the priorities of other tasks accordingly.

    Regards,

    Aaron

  • Hi Aaron,

    That would seem to contradict this

    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/733318/rtos-am3356-hwi_create-hwi_params-priority

    Which is correct? Out of curiosity I tried changing to a priority of 15 and it does not seems to have an affect on the jitter. So it would seem it is not a priority issue. As a note, previously the driver was setting the priority to the pruEvtoutNum which was 20. As far as task priorities, those should not matter right? The HWI should always take priority over those regardless of priority right?

  • Hi Keith,

    Sorry for the confusion. Yes you are right.

    Give me some time to go through this.

    Regards,

    Aaron

  • Hi Keith,

    Can you try with a different maskSetting as it can affect the priority?

    Regards,

    Aaron