English 中文(简体)
如何适当计算时间超支,以便将32倍高分辨率的时间转换为64倍高分辨率的时间
原标题:How to properly count timer overflows to convert a 32-bit high-resolution timer into a 64-bit high-resolution timer

这是一个困难的种族状况问题,我试图纠正这一问题。 我拥有一个32轨道核心时间,即一个PIC32MZ微型控制器(datasheet/,在100 MHz。

该系统拥有多种任务(校对),该法典应当能够随时从任何任务中召唤。

每2千2千米/秒=42.9秒。 我愿安全地把它变成64个截面。

有一个处理计票超支问题的独立实体。 它看着这样的情况:

static volatile uint32_t rollover_count = 0;

void isr_core_timer_overflow()
{
    rollover_count++;
}

这一概念还将涉及8个微型控制器,从8个轨道反向改为16个轨道或32个轨道反转器。

Here is my proposed solution:

// For 32-bit mcus such as PIC32
uint64_t get_counts()
{
    uint32_t count1 = ReadCoreTimer();

    // No critical section needed because we are reading a 32-bit value, and
    // turning off interrupts doesn t stop the core timer from counting
    // anyway.
    uint32_t rollover_count_copy = rollover_count;

    uint32_t count2 = ReadCoreTimer();

    if (count2 < count1)
    {
        // rollover just occurred between reading count1 and count2, so manually
        // account for it; note: rollover_count will be incremented
        // by the rollover ISR, so I don t need to update it
        rollover_count_copy++;
    }

    uint64_t total_count = ((uint64_t)rollover_count_copy << 32) | count2;

    return total_count;
}

部分我认为,我do需要一个关键部分,但我可以总结一下原因。 在核心时间流出时,国际职工会的超额流动将会发生,也许我需要暂时停止。

如果我打断了警卫人员,以保护一个关键部门,那么,我可能会认为:

// For 32-bit mcus such as PIC32
uint64_t get_counts()
{
    uint32_t count1 = ReadCoreTimer();

    // back up the interrupt state
    // - Note: the `__builtin_*` functions are part of the XC32 compiler, and 
    //   are documented in DS50002799C (MPLAB® XC32 C/C++ Compiler User s Guide
    //   for PIC32M MCUs; XC32 Compiler for PIC32M) p195, p265 (the assembly 
    //   code output for the functions is around here), etc.
    unsigned int isr_state = __builtin_get_isr_state();
    __builtin_disable_interrupts();  // critical section start

    uint32_t rollover_count_copy = rollover_count;
    uint32_t count2 = ReadCoreTimer();

    // restore the interrupt state
    __builtin_set_isr_state(isr_state); // critical section end

    if (count2 < count1)
    {
        // rollover just occurred between reading count1 and count2, so manually
        // account for it
        rollover_count_copy++;
    }

    uint64_t total_count = ((uint64_t)rollover_count_copy << 32) | count2;

    return total_count;
}

或将<代码>count1改为关键部分,以阻止<代码>rollover_count在当时从国际会计准则的增减中删除:

// For 32-bit mcus such as PIC32
uint64_t get_counts()
{

    unsigned int isr_state = __builtin_get_isr_state();
    __builtin_disable_interrupts();  // critical section start

    uint32_t count1 = ReadCoreTimer();
    uint32_t rollover_count_copy = rollover_count;
    uint32_t count2 = ReadCoreTimer();

    __builtin_set_isr_state(isr_state); // critical section end

    if (count2 < count1)
    {
        rollover_count_copy++;
    }

    uint64_t total_count = ((uint64_t)rollover_count_copy << 32) | count2;

    return total_count;
}

什么是正确的? 你们会提出什么解决办法? 我的第一项做法是否有问题?

References

  1. 我的八点“AVR”解决办法十多年来一直徒劳地运作,是

  2. PIC32 Peripheral Libraries for MPLAB C32 Compiler -也载有<编码>UpdateCoretimer(<>> > 代码/code>。

  3. rel=“nofollow noreferer”>PIC32MZ datasheet

  4. https://www.microchip.com/en-us/tools-resources/develop/mplab-xc-compilers/xc32 。 - “MPLAB XC32 Compiler Documentation”和“MPLAB XC32 C32 C++”下载 Compileruser s Guide for PIC32M MCUs”.

    1. Direct link: MPLAB® XC32 C/C++ Compiler User s Guide for PIC32M MCUs--XC32 Compiler for PIC32M--DS50002799C.pdf - contains the documentation for the __builtin_* functions.

Related

  1. Timer rollover handling - related, but not a duplicate
问题回答

我在实际生产法典中为类似的制度做了确切的工作。

几个问题......

  1. You increment rollover_count_copy but never advance rollover_count
  2. The change to rollover_count must be done in the critical section (i.e. interrupts disabled)
  3. You don t want to read the timer twice. You want to have a global that keeps track of the "old" timer value.
  4. For PIC*, it doesn t do much instruction reordering, so using volatile on globals under the critical section is sufficient (vs. using barriers).
  5. Assuming that once you enter an ISR, the system is "single level" and can t be stacked (i.e. a second interrupt can not interrupt_ an ISR) ...
  6. ... If you add a global that is set when within an ISR, you can speed up get_counts by not changing the interrupt flag(s) when called from an ISR. (i.e.) In an ISR, interrupts are already disabled.
  7. The save/restore of interrupt context needs to be done only if called from base/task level.

这里略微重复你的职能。 说明:

#include <stdint.h>

// fake definitions
#ifdef __linux__
uint32_t ReadCoreTimer(void);
uint32_t __builtin_get_isr_state(void);
void __builtin_set_isr_state(uint32_t);
void __builtin_disable_interrupts(void);
#endif

volatile int in_isr = 0;                // 1=within ISR
volatile uint32_t old_timer = 0;        // previous timer value
volatile uint32_t rollover_count = 0;   // rollover count

#define INTERRUPTS_CANT_BE_STACKED  1

// For 32-bit mcus such as PIC32
uint64_t
get_counts()
{
    unsigned int isr_state;
    int isrnow = in_isr;

    // back up the interrupt state
    // - Note: the `__builtin_*` functions are part of the XC32 compiler, and
    // are documented in DS50002799C (MPLAB® XC32 C/C++ Compiler User s Guide
    // for PIC32M MCUs; XC32 Compiler for PIC32M) p195, p265 (the assembly
    // code output for the functions is around here), etc.
    if (! isrnow) {
        isr_state = __builtin_get_isr_state();
        __builtin_disable_interrupts();     // critical section start
    }

    uint32_t rollover_count_copy = rollover_count;
    uint32_t curcount = ReadCoreTimer();

    if (curcount < old_timer) {
        // rollover just occurred between reading count1 and count2, so manually
        // account for it
        rollover_count = ++rollover_count_copy;
    }

    // save the current timer value for rollover detection on the _next_ call
    old_timer = curcount;

    // restore the interrupt state
    if (! isrnow)
        __builtin_set_isr_state(isr_state); // critical section end

    uint64_t total_count = ((uint64_t) rollover_count_copy << 32) | curcount;

    return total_count;
}

// some_ISR -- example ISR routine
void
some_ISR(void)
{

    in_isr = INTERRUPTS_CANT_BE_STACKED;

    get_counts();

    in_isr = 0;
}

// main -- example of task level function
int
main(void)
{

    get_counts();

    return 0;
}




相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...

热门标签