Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

volatile

misra

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.

like image 365
m4l490n Avatar asked Aug 06 '15 15:08

m4l490n


2 Answers

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);
    }
}
like image 63
ecatmur Avatar answered Sep 18 '22 11:09

ecatmur


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.

like image 37
too honest for this site Avatar answered Sep 21 '22 11:09

too honest for this site