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.

RTOS/TI-RTOS-MCU: SYS/BIOS with C2000

Part Number: TI-RTOS-MCU
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI-RTOS

Dear,

 

We’re using Piccolo F28069 DSP in our project, which firmware platform is TI SYS/BIOS – version 6.50. The ADC ISR is 35KHz, and there will be Event post or Swi post from ADC ISR to tasks in every 20ms.

 

As I found, sometimes Event_post() or Swi_post() will take long time, which impacts the normal ADC ISR frequency - 35KHz. In this case, it’ll lose one ADC ISR. If Event or Swi is posted from task, it seems no such issue happens.

 

In bad case, Eg., Event_post() takes 45us and ADC ISR runs for 60us, Swi_post() takes 56us and ADC ISR runs for 70us, which are more longer than normal time.

 

The test code is as follows:

 

#pragma CODE_SECTION("ramfuncs");

__interrupt void adc_ISR( void )

{

  GPIO_ISR_HIGH();

 

  // Other code . . . . . .

 

  if(AC_zero_crossed) // 20ms period

{

        GPIO_POST_HIGH();

Event_post(TASK_EVENT_PFC, EVENT_ID_PFC_UTILITYZERO);

GPIO_POST_LOW();

}

 

  // Other code . . . . . .

 

  GPIO_ISR_LOW();

 

  AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;  // Clear ADCINT1 flag reinitialize for next SOC

  PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;// Clear PIE acknowledge bit for INT1

}

 

Could you please help to see this issue? Thanks!

 

 Teasir Chen

  • Hi,

    How are you creating the ISR? If you are not using Hwi, you cannot make calls into the kernel (e.g. Event_post or Swi_post).

    Todd
  • Hi Todd,

    I create the ISR using Hwi, but config the registers directly instead of .cfg file, which are as follows:

    EALLOW;
    ...
    PieVectTable.ADCINT1 = &adc_ISR; // ADC interrupt
    ....
    EDIS;

    // Enable ADC interrupt 1 in the PIE: Group 1
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Fast ADC interrupt
    // Enable the related CPU interrupt according to PIE Group
    IER = M_INT1 ;
    IFR = 0x0000;
    // Enable the PIE after initialization
    PieCtrlRegs.PIECTRL.bit.ENPIE = 1;

    Regards
    Teasir Chen
  • If you create the ISR with Hwi, you don't need the interrupt keyword. Can you show me the code where you create the Hwi? Note: you can create during runtime instead of the .cfg file.
  • Sorry Todd, I think I have created the ISR with interrupt keyword, while not Hwi of TI RTOS. I have already posted the code as above.

    Do you mean Event_post and Swi_post can't call into the kernel? But it does work in my system.
  • You're getting lucky. ISR's not managed by the kernel should not make kernel calls.
  • I have tried the Hwi of RTOS, it's good that Event_post takes much less time ( < 20us ) than before.

    But new issue found if using Hwi of the system, ADC ISR will NOT triggered in 35KHz accurately, the frequency is changed during running, Eg., 30KHz ~ 40KHz. In our application, the digital control is real time system and ADC ISR should be triggered in 35KHz accurately.

    I tried c28.Hwi and hal.Hwi, the results are same, which code in .cfg file are as follows:
    Example 1:
    var Hwi = xdc.useModule('ti.sysbios.family.c28.Hwi');
    var hwi0Params = new Hwi.Params();
    hwi0Params.instance.name = "hwi0";
    Program.global.hwi0 = Hwi.create(32, "&adc_ISR", hwi0Params);

    Example 2:
    var Hwi = xdc.useModule('ti.sysbios.family.c28.Hwi');
    var ti_sysbios_hal_Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
    var ti_sysbios_hal_Hwi0Params = new ti_sysbios_hal_Hwi.Params();
    ti_sysbios_hal_Hwi0Params.instance.name = "ti_sysbios_hal_Hwi0";
    Program.global.ti_sysbios_hal_Hwi0 = ti_sysbios_hal_Hwi.create(32, "&adc_ISR", ti_sysbios_hal_Hwi0Params);
  • Are there other interrupts that could be interfering? How are you measuring the jitter?
  • Except for CPU Timer 2 (for TI/RTOS use), there is only one ISR in the system, which is ADCINT1.

    I write test code and set one GPIO to high when enter ADCINT1, and set to low when exit this ISR. Oscillograph is used to capture the frequency. The code is written as follows:

    #pragma CODE_SECTION("ramfuncs");
    Void adc_ISR( UArg arg )
    {
    GPIO_ISR_HIGH();

    // Other code . . . . . .

    GPIO_ISR_LOW();

    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Clear ADCINT1 flag reinitialize for next SOC
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;// Clear PIE acknowledge bit for INT1
    }
  • Hi,

    So you are measuring the time from GPIO_ISR_HIGH to GPIO_ISR_HIGH...correct? What is the max/ave/min time for GPIO_ISR_HIGH to GPIO_ISR_LOW?

    Todd
  • Yes, you're right, I'm measuring time from GPIO_ISR_HIGH to GPIO_ISR_LOW. The time measured are as follows:
    max time - 14us
    average time - 7us
    min time - 6us

    The ADCINT1 is triggered in 35KHz, it should be fixed frequency. When I use interrupt keyword to config ISR directly, the interval time (GPIO_ISR_HIGH -> GPIO_ISR_HIGH) between each ISR is 28.6us, which is very accurate. But the interval time is quite unstable if I use Hwi of RTOS, which is between 18us ~ 36us.

    It seems ISR can't be triggerd on time if use Hwi of RTOS.

  • Sorry for the late reply.

    Can you disable the timer that the Clock module is using? I want to rule that out. You can add the following into the .cfg file.

    Clock.tickSource = Clock.TickSource_USER;

    Note: you lose timing (e.g. Task_sleep will sleep forever). If this is the issue, we'll look into a couple options.

    Todd
  • It's fine, Todd.

    I tried your way to disable the timer of Clock module, it's more better than before. While the gap still exist between two ADC ISR, it's about 1us ~ 2us shifted.

    I tested the code with interrupt keyword instead of OS Hwi, sometimes there is also 1us ~ 2us gap between two ADC ISR. I guess it may be caused by OS core, which disables global interrupt in some cases, Eg., context switch of task, etc. 
     
    Regards
    Teasir

  • You can take a look at the Benchmark section in the SYS/BIOS release notes to see how long interrupts can be disabled. It's in the API timing link.

    You can use zero-latency interrupts with the kernel. The kernel add no latency on these interrupts. The downside is that these interrupts cannot make a kernel call (basically the same issue as when you used the interrupt keyword). A zero-latency interrupt can cause another interrupt to run which can make kernel calls though.

    Todd
  • Additionally...if you are fine with the jitter you are seeing (~1-2us) when you had
    Clock.tickSource = Clock.TickSource_USER;

    You can still drive the tick yourself if you need timing. You configure the clock for the desired period and call Clock_tick() yourself at that period.

    Todd
  • Thanks for your good information!

    As see from benchmark, the maximum number of interrupt latency is 181 (~ 2us) during SYS/BIOS kernal context switching, which disables maskable interrupts. It means we have to accept this jitter time for ADC ISR ( < 2us) if use SYS/BIOS system.

    I can add no latency ISR with interrupt keyword, but don't know how to use zero-latency interrupt with the kernel. Could you please give me the guideline?

    Thanks
    Teasir Chen
  • This page talks about them: processors.wiki.ti.com/.../BIOS_for_the_28x

    Also there is a write-up in <bios_install_dir>docs/cdoc/index.html and navigate to ti.sysbios.family.c28.Hwi and search for "zero".

    Todd
  • In my system, ADCINT1 is in PIE group 1, which interrupt number of Hwi is 32. I tried to set Hwi.zeroLatencyIERMask to 1, it shows the error message of "Hwi 32 conflicts with IER Mask 0x1". Is there any problem to config the zero latency interrupt?

    In the config file, the code is as follows:
    var Hwi = xdc.useModule('ti.sysbios.family.c28.Hwi');
    var hwi0Params = new Hwi.Params();
    hwi0Params.instance.name = "hwi0";
    Program.global.hwi0 = Hwi.create(32, "&adc_ISR", hwi0Params);
    Hwi.zeroLatencyIERMask = 1;

  • Hi,

    My bad! For the C28 devices, you just need to set the Hwi.zeroLatencyIERMask and then use the interrupt keyword. It's on the CortexM devices we added support to call Hwi_create and specify it as a zero-latency interrupt.

    So basically go back to the interrupt keyword and set the Hwi.zeroLatencyIERMask and then don't make any kernel calls in that ISR.

    Todd
  • It's great, now my system can work well as following change:

    1. Use Zero latency interrupt for critical ISR to ensure minimal latency time, which can avoid ISR jitter
    2. Zero-latency interrupt causes another interrupt where need to call kernel
    3. Use Hwi of SYS/BIOS instead of interrupt keyword for none critical ISRs, which spends less time to post Event or Swi

    Thanks Todd for your great support, hope you have good time!

    Many Thanks
    Teasir Chen
  • Cool! Thanks for the update!