7

Given the following code:

static volatile float32_t tst_mtr_dutycycle;
static volatile uint8_t tst_mtr_direction;
static volatile uint32_t tst_mtr_update;

void TST_MTR_Task(void)
{
    if (tst_mtr_update == 1U)
    {
        tst_mtr_update = 0;

        MTR_SetDC(tst_mtr_dutycycle, tst_mtr_direction);
    }
}

I found problems with MISRA C 2012 Rule-13.2 and I decided to make some research. I found here (http://archive.redlizards.com/docs/misrac2012-datasheet.pdf) that:

there shall be no more than one read access with volatile-qualified type within one sequence point

The thing here is that I haven't been able to find an example or explanation that makes clear why there shall be no more than one read access with volatile-qualified type within one sequence point.

I need to find a solution for the violating code but is not really clear to me what to do.

I know now that there shall be no more than one read access with volatile-qualified type within one sequence point. The question is, why? and I need to know why in order to implement a solution and to explain everybody here why I am changing the code.

Regards.

m4l490n
  • 1,592
  • 2
  • 25
  • 46

2 Answers2

7

The justification for the rule is:

(Required) The value of an expression and its persistent side effects shall be the same under all permitted evaluation orders

If more than one volatile-qualified variable is read between sequence points, then it is unspecified which is read first. Reading a volatile variable is a side effect.

The solution is to explicitly order the reads:

void TST_MTR_Task(void)
{
    if (tst_mtr_update == 1U)
    {
        tst_mtr_update = 0;

        float32_t dutycycle = tst_mtr_dutycycle;
        uint8_t direction = tst_mtr_direction;
        MTR_SetDC(dutycycle, direction);
    }
}
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • 1
    Perfect!! Thanks! This answer may help me with other issues as well. I was missing the side effects part of the rule. – m4l490n Aug 06 '15 at 16:11
  • There is something that is not very clear to me. Why is reading a volatile variable a side effect? – m4l490n Aug 06 '15 at 16:38
  • 2
    @m4l490n because that's what `volatile` is for - it specifies that writes and reads can't be cached or reordered. An example would be a hardware register, where reads can return different values on successive reads, and result in arbitrary actions occurring. – ecatmur Aug 06 '15 at 16:49
  • 2
    @ecatmur: actually, the standard does not say this. It only refers to reordering by the compiler with regard to the abstract machine. Caching and buffering or reordering by the external hardware is not covered, unless the program itself gets correct values. This is one reason `volatile` is not enough when using threads or multiprocessors with interrupts. Here atomics come into the game, which include barriers/fences and other system-wide synchronization. – too honest for this site Aug 06 '15 at 22:34
3

There are no sequence points between fetching the arguments of a function call. So the order they are fetched is undefined by the standard. OTOH, the compiler has to maintain the order of accesses to volatile objects, so this is a contradiction.

Fetch the variables to non-volatile temps and use those for the function call:

float32_t t1 = tst_mtr_dutycycle;
uint8_t t2 = tst_mtr_direction;
MTR_SetDC(t1, t2);

Note this is actually an issue for standard C and not just related to MISRA-compliance.

As you appear to have multiple problems regarding standard compliance, you might want to keep the standard under your pillow.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52