Best way to pass data from interrupt

willywortel wrote on Thursday, March 19, 2009:

I use the pic32.

I’ve setup the ADC to capture automatically and store the ADC data during the ADC interrupt in a structure.
This works, no problem.

Now I need the ADC data (structure) available to some variety of tasks. What is the best way to do this?
The tasks do not need the data periodically, more randomly.
Was thinking to use sendQueueFromIsr to send the structure to a queue.

Then i thought to create a function that only peeks and returns a variable from the structure.
So a task that need an information just calls the right function.

But I don’t know if this solution is safe, anyone? Or are there better ways?

This is the data that gets filled during the interrupt and that i need to have available to the other tasks:

         xAdcData.usBATT_24     = ADC1BUF0;
         xAdcData.usTEMP        = ADC1BUF1;
         xAdcData.usCURR        = ADC1BUF2;

willywortel wrote on Thursday, March 19, 2009:

Or is it safe to do just this: (it could be called by multiple tasks)

unsigned portSHORT getPowerVoltage(void)
    return xAdcData.usBATT_24;

edwards3 wrote on Thursday, March 19, 2009:

Your data is 24bits (although your function only returns 16?) and the word size of your microcontroller is 32 bits. As long as you only ever write to the 32bit value in one go then you are safe. So in the interrupt fill the 24bit value byte by byte as you are, then copy this as a single 32bit value into a 32bit variable. Your function can then just return the 32bit value.

The other but less desirable alternative is to use a critical section something like:

unsigned long getPowerVoltage(void)
    unsigned long returnedValue;


    return returnedValue;

This second solution is ok if your tasks only read the value occasionally. Don’t use it if they continuously read the value.

willywortel wrote on Thursday, March 19, 2009:

Thanks for the reply.

I did not show that the structure variables are also defined as portSHORT. I did this
because the resolution of the ADC is 10bits.

But if i understand correctly, i can better make it 32bit variables (unsigned int for example),
and then i will have to do it like this:

for the interrupt, where the variables gets filled:
xAdcData.usCURR     = ADC1BUF0;

for the return, where the data gets read out by some tasks:
return xAdcData.usCURR;

where xAdcData.usCURR is a 32 bit variable. Can i then be sure that there will not be any

Just to make sure, a portSHORT will that too be an atomic read instruction? or only 32bit lengths?

willywortel wrote on Thursday, March 19, 2009:

When i go into disassembly listing, then i see 4 instructions that gets executed
when using portLONG (32bit) (when writing in the interrupt) :

lui         v1,0xa000
lui         v0,0xbf81
lw          v0,-28560(v0)
sw          v0,31072(v1)

and 5 when using portSHORT(16bit)

lui         v0,0xa000
addiu       v1,v0,31072
lui         v0,0xbf81
lw          v0,-28544(v0)
sh          v0,4(v1)

And when reading, the return uses 3 instructions with portLONG:

lui         v0,0xa000
lw          v0,31072(v0)
andi        v0,v0,0xffff

And 4 instructions when portSHORT:

lui         v0,0xa000
addiu       v0,v0,31072
lhu         v0,6(v0)
andi        v0,v0,0xffff

But in all cases, i`m not that good with asm, I see the address from the variable only once.
So can I than say it is an atomic instruction?