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.

RM46L852: Using RTI with FreeRTOS

Part Number: RM46L852
Other Parts Discussed in Thread: HALCOGEN

Hi,

I want to create a microsecond counter for my TI Hercules application.
Because I'm using FreeRTOS, it seems I can't activate the RTI module in HalCoGen.

After a bit of looking, it seems like the RTI is used by the FreeRTOS port to generate the tick ISR.


Is there a way I can still use the RTI counter 1? 
What's the best way to generate this us timer?

Best,
Gabriel

  • Update: I would still appreciate guidances, but I came up with this solution:

    uint32 const free_running_counter = rtiREG1->CNT[0].FRCx;
    uint32 const prescale_counter = rtiREG1->CNT[0].UCx;
    
    uint32_t const compare_up_counter = (1 << rtiREG1->CNT[0].CPUCx);
    uint64_t const total_counter = (free_running_counter * compare_up_counter) + prescale_counter;
    
    //                               1
    // second = counter_value * ------------
    //                            rti_freq
    uint64_t const rti_clock_frequency_MHz = (uint64_t)RTI_FREQ; //< Defined by halcogen
    uint64_t const microsecond = total_counter / rti_clock_frequency_MHz;
    

    It leverages the already-running RTI timer used by freeRTOS. 
    Not sure about how it impacts the kernel.

  • I used your great wiki to solve this problem.
    But would you suggest using the RTI using 32 bits or 64 bits?

  • The HALCoGen only enabled 1 RTI compare for freeRTOS.

    You can add other RTI compares manually to prvSetupTimerInterrupt() function.

    portRTI_CNT0_COMP1_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
    portRTI_CNT0_UDCP1_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;

    portRTI_SETINTENA_REG = 0x00000003U; 

    The RTI counter block is 64-bit wide: 32-bit prescale counter (RTIUC0 or RTIUC1) + 32-bit free running counter (RTIFRC0 or RTIFRC1)

  • >  The RTI counter block is 64-bit wide: 32-bit prescale counter (RTIUC0 or RTIUC1) + 32-bit free running counter (RTIFRC0 or RTIFRC1)

    Don't you need to also multiply the freerunning counter by the compare up counter?
    Like this:

    uint32 const free_running_counter = rtiREG1->CNT[0].FRCx;
    uint32 const prescale_counter = rtiREG1->CNT[0].UCx;
    
    uint32_t const compare_up_counter = (1 << rtiREG1->CNT[0].CPUCx);
    uint64_t const total_counter = (free_running_counter * compare_up_counter) + prescale_counter;

    You can add other RTI compares manually to prvSetupTimerInterrupt() function.

    I agree, this would probably be easier that way.
    Just configure RTI[1] to overflow at 1M Hz and just read the overflow counter.

  • The free-running clock period = (rtiREG1->CNT[0].CPUCx + 1) * RTI clock period

    Total counter = (rtiREG1->CNT[0].CPUCx + 1) * free_running_counter + prescale_counter

    I don't understand the formula in your message: compare_up_counter = (1 << rtiREG1->CNT[0].CPUCx);

  • Hi QJ,

    You're right. The bitshift was an error (that only worked because CPUCx == 2);
    Here's the final version of the code. 

        // The free running counter store the number of time the up-counter has matched with the compare up-counter.
        uint32_t const free_running_counter = rtiREG1->CNT[0].FRCx;
    
        // The up-counter value is stored in its counter register (RTIUCx).
        // RTIUCx store the number of RTICLK cycles that have elapsed since reading `free_running_counter`
        uint32_t const up_counter_value = rtiREG1->CNT[0].UCx;
    
        // The compare up-counter register store the threshold for the up-counter (which will trigger the increment)
        uint32_t const compare_up_counter_value = (rtiREG1->CNT[0].CPUCx + 1);
    
        // We can compute the total RTI tick
        uint32_t const total_rti_tick = (free_running_counter * compare_up_counter_value) + up_counter_value;

    This has been tested and seems to be precise enough.

  • This looks good. Your code follows the order of register read operations: the free running counter must be read first, then up counter.

  • Thanks again for your help QJ.