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.

FreeRTOS context switch time on hercules

Other Parts Discussed in Thread: TMS570LS20216

Somebody could tell me, what is the average context switching time on hercules tms570LS20216?

I could measure about 7usec @ 140MHz between the end of a task and the beginning of the next task. If I'am right its about 1000 cycles. The FreeRTOS FAQ (http://www.freertos.org/FAQMem.html#ContextSwitchTime) says that the switching time is 86 cycle in the case of cortex M port. I know that the value depends on the architecture, compiler optimisation etc.. but it is quite big difference.

Thank You Szilard

  • Szilard,

    You can measure this easily by reading the PMU cycle count register between the two points that you want to capture & logging to memory.

    If you do not have the code compiled with optimization and instead have debug on - you will get very easy to debug  code -- but with poor execution times.  So also check your build options.  You might just make sure you build the 'Release' profile for your measurement.

    Don't try to measure with a GIO pin because there is a lot of latency to read/write a GIO (maybe 22-25 cycles) so if you do that it will throw your measurement off.  I believe reading the cycle count in the PMU is just 6 cycles.

  • My question is to TI expert regarding this subject.I felt using PMU for context switching time or Interrupt Latency measurement is quite difficult in TMS570... I get too many errors when I tried to Start PMU counter inside Tick Increment ISR and stopped before the ISR called Application tick Hook. Is there any demo code that best illustrates usage of PMU other than inside the Main() function? I referred the application note available in TI site for execution time measurement using PMU...

    Thanks in Advance!
  • Sindhu,

    The PMU is best. Not sure what the error you are running into is due to. What are the details of the error and what mode is the CPU in when the instruction you are trying to use to read the PMU executes?
  • Sindhu,

    I talked to our compiler engineer. The TI 5.2 compiler now supports intrinsics to access coprocessor registers like the PMU cycle counter.
    So you can try this from C using these intrinsics:

    void __MCR(uint coproc, uint op1, uint src, uint coproc_reg1, uint coproc_reg2, uint op2)
    uint __MRC(uint coproc, uint op1, uint src, uint coproc_reg1, uint coproc_reg2, uint op2)

    You can find the information for the parameters by looking at the ARM TRM. There is a dedicated cycle counter in the PMU though so just counting cycles is very easy.
  • Hi Sindhu and Szilard,

    Were there any open issues on this thread or did the PMU work out ok.
  • I've not yet tried your suggestion Anthony... Will reply soon trying this
  • Anthony
    Can you advise which header file shall we include for __MCR and __MRC? I'm using ti-cgt-arm_5.2.3. I fail to open intrinsics.h.

    Regards
    Dong
  • Hi, I'm not able to use the PMU with Freertos on the Hercules dev. board. It works if I use it in main before I start a FreeRTOS thread. But after I've started a thread, the MCU stops in an interruptr trap I believe:

    undefEntry
            b   undefEntry

    It instantly jumps to that trap when this instruction is run:

    _pmuGetCycleCount_
    
            mrc   p15, #0, r0, c9, c13, #0

    Why is this happening?

    How to solve this?

  • Well first thing that comes to mind is privilege because you mention FreeRTOS and things working prior to starting the RTOS but failing in a thread.
    The recent versions of FreeRTOS create tasks in user mode so you don't have privilege by default. If you want a task to
    have privilege you need to create it with the xTaskCreateRestricted() API.. This shows up a lot when we have peripheral registers that have the "P" attribute...

    But... the exception you are getting is UNDEF so I don't think this is the issue.

    I'd say instead, look for an interworking issue; where the caller and callee are running with different instruction set modes.

    The UNDEF will occur when the coprocessors don't decode the coprocessor instruction as something that they can execute.
    And so if the processor is running in say Thumb2 but you are calling an ARM function directly this might be the issue.

    I don't know how the project is setup and how these files are compiled and assembled, but you should check whether the "C" is compiled
    for thumb2 and whether there are directives inside the assembly file saying to assemble for one mode or the other.

    Then the other thing you can do is try to step into the _pmuGetCycleCount_ function. Pay attention to the CPSR as you do and pay attention to what instruction set mode you are in. Then write down the hex # from a memory window for 'mrc' instruction and check to see if this hex encoding of the instruction is correct for the mode in which you are entering the call.

    If this is the issue (mismatch in instruction set) then we can look for the various solutions. I think the compiler can create automatically the correct 'shim' if it knows that it's calling ARM from Thumb2 or vice-versa but in this case because one file is written in assembly we might have some directives missing...

    -Anthony
  • Hello Anthony,

    This is what I get when stepping

    Before MRC
    CPSR 0x60000310
    EE190F1D mrc p15, #0, r0, c9, c13, #0

    After MRC / In trap

    CPSR 0x6000039B
    EAFFFFFE b undefEntry

    From the description of CPSR I understand that CPU is using not (not added in edit) Thumb2 in User mode before instruction. I don't know how to find out if my MRC instruction is Thumb. It's in Undef mode in the trap.

    In main

    CPSR 0x6000039F

    Which means System mode 

    Haven't tried xTaskCreateRestricted yet

  • Oh, sorry, I looked at the wrong bit. It's not using Thumb2.
    So then maybe it's the privilege as was your initial thought. I will try that tomorrow.
  • Hmm. It might be a matter of privilege after all, I just found this fine print in the CPU TRM under the PMU section:

    "If the EN bit in the USEREN Register is not set, any attempt to access a performance monitor
    register or a validation register from User mode causes an Undefined instruction exception."

    Maybe the reasoning is to make the coprocessor just act like its not there if you don't have privilege ..

    Anyway you might try also setting that bit so you can access in user mode.
  • Hi, I added this to _pmuInit_ but still throws the exception
    ; User mode access to performance monitor and validation registers
    mov r0, #1
    mcr p15, #0, r0, c9, c14, #0 ; Write USEREN Register
  • This did the trick. Now I can read the cyclecounter in user mode. Thanks for the help!

    Added four lines in top of this function.
    _pmuInit_
    ; User mode access to performance monitor and validation registers mov r0, #1 mcr p15, #0, r0, c9, c14, #0 ; Write USEREN Register mov r0, #0x8000000f mcr p15, #0, r0, c9, c14, #2 ; Something to do with interrupts