How to prohibit compiler to precompute product of constant values - c

I'm trying to write a current controller using a ATmega328.
For the control algorithm I need to convert the desired current into that value, the ADC would measure if the desired current flows. So instead of controlling the current it's more a kind of "controlling" the measured ADC value.
Nevertheless it is necessary to convert the desired current in it's equivalent ADC-value.
Therefore I have defined all parameter included in the measurement chain:
#define CTRL_SHUNT_GAIN (20UL) // 20mV/A -> R=0.02Ohm (A->mV)
#define ADC_REF_VOLTAGE (1100UL) // mV
#define CTRL_ADC_V2ADC 1024UL/ADC_REF_VOLTAGE // 1024=U_ADCref (mV->ADC)
#define CTRL_ADC_ADC2V ADC_REF_VOLTAGE/1024UL // 1024=U_ADCref (ADC->mV)
// conversion
#define CTRL_I2ADC(cur) ((int16_t)((int32_t)cur*CTRL_SHUNT_GAIN*CTRL_ADC_V2ADC/1000UL))
In the code later I call the control algorith and handover the (converted) desired value, the last ADC measurement and a pointer to the controller structure, containing the gains and so on.
outputA = controlAlgorithm(CTRL_I2ADC(desA), adcSampling.values[0], &ctrlA);
The problem I have is, that the compiler precalculates the right part of the multiplication (CTRL_SHUNT_GAIN*CTRL_ADC_V2ADC/1000UL), which - correctly - yields zero (20*1024/1100/1000=0). But i.e. let cur be 8000 mA, this conversion should provide 8000*20*1024/1100/1000=148.
So my question ist, how to tell the compiler, not to precompute the "constant" part of the multiplication.
Or do I need to define all the stuff in an other way?
Edit
inside controlAlgorith I produce a debug output:
// computes output value depending on input error in mA
int16_t controlAlgorithm(int16_t des, int16_t act, controller_t *ctrl){
int32_t ctrlOut;
// debug output
uart0SendInt(des);
uart0SendString("\t");
uart0SendInt(act);
uart0SendString("\t");
...
}
calling it like this:
outputB = controlAlgorithm(desB, adcSampling.values[1], &ctrlB);
outputB = controlAlgorithm(CTRL_I2ADC(desB), adcSampling.values[1], &ctrlB);
gives me the output:
8000 50
32 50

Related

Building an Array of #define Directives

I have some microcontroller code that uses some header files where GPIO pins are defined like this:
#define PA3 GPIO(GPIO_PORTA, 3)
Using the IDE, I can navigate to the implementation of GPIO and I find this:
#define GPIO(port, pin) ((((port)&0x7u) << 5) + ((pin)&0x1Fu))
Where pin is defined as:
const uint8_t pin
and port is an enum defined as:
enum gpio_port { GPIO_PORTA, GPIO_PORTB, GPIO_PORTC, GPIO_PORTD, GPIO_PORTE }
I would like to create an array of all the GPIO defins (PA3, PA4, etc.) that can be indexed by an integer passed over a serial port.
I tried the following:
GPIO knavePinList[] = {PA3, PA4, PA21, PB4, PHY_RESET_PIN, PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9};
But this obviously doesn't work as GPIO is not a recognized C-type, but in fact a macro. While trying to build, I receive this error message:
unknown type name 'GPIO'
Is it even possible for me to declare an array of macros? If so, how would I note the type for what I'm working with?
Thanks.
#define statements perform text replacement, they have no inherent type. As you noted, GPIO is not a valid type, it's a macro that appears to calculate pin numbers/addresses (actually GPIO is undefined, while GPIO(a,b) is the macro).
If you want to store an array of many of these, then you need to know what actual type they all evaluate to. Given that the GPIO macro returns a sum of a port and a pin value, where port is an enum, whose underlying type is int (technically, it's an implementation specific integral type - see What is the underlying type of a c++ enum?) and pin is a uint8_t, the actual type of your array values would also be an integer type - which one specifically depends on your implementation and the range of possible values.
The array you post is perfectly legal, I think you have not tested it. Anyway, it is best to ask with a testable example, (see How to create a Minimal, Complete, and Verifiable example) but the code:
GPIO knavePinList[] = {PA3, PA4, PA21, PB4, PHY_RESET_PIN, PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9};
will produce a perfectly legally initialized array of integers, with the bitwise values of the constants you have expanded from the macros. Try to use
cpp source.c | more
to see how the array declaration is actually expanded. By the way, you have another, different problem in your code... you are using the same identifier, GPIO, to indicate the GPIO macro name, and the type of the array elements, so when the macro processor encounters it, it sees no parameters, which is not how you have #defined it, and complaints about a two parameter macro GPIO called with no parameters at all.
You have to test your code... and send 1. what you expect... and 2. what you get instead... because the error should be evident, if you had simply stopped to read it.
A solution to your problem is to rename the macro GPIO to GPIO_BITS for example... and then change all the definitions:
#define GPIO_BITS(port, pin) ((((port)&0x7u) << 5) + ((pin)&0x1Fu))
...
#define PA3 GPIO_BITS(GPIO_PORTA, 3)
so when you encounter the array definition, the type name is not tried to expand as a macro.
No, you cannot create an array of macros like that.
If you want to execute a particular macro based on an input, you will need to use an if-else or switch statement. If the input is an integer, you could do something like:
switch( input )
{
case 0: PA3; break;
case 1: PA4; break;
case 2: PA21; break;
...
}

Average from error prone measurement samples without buffering

I got a µC which measures temperature with of a sensor with an ADC. Due to various circumstances it can happen, that the reading is 0 (-30°C) or a impossible large Value (500-1500°C). I can't fix the reasons why these readings are so bad (time critical ISRs and sometimes a bad wiring) so I have to fix it with a clever piece of code.
I've come up with this (code gets called OVERSAMPLENR-times in a ISR):
#define OVERSAMPLENR 16 //read value 16 times
#define TEMP_VALID_CHANGE 0.15 //15% change in reading is possible
//float raw_tem_bed_value = <sum of all readings>;
//ADC = <AVR ADC reading macro>;
if(temp_count > 1) { //temp_count = amount of samples read, gets increased elsewhere
float avgRaw = raw_temp_bed_value / temp_count;
float diff = (avgRaw > ADC ? avgRaw - ADC : ADC - avgRaw) / (avgRaw == 0 ? 1 : avgRaw); //pulled out to shorten the line for SO
if (diff > TEMP_VALID_CHANGE * ((OVERSAMPLENR - temp_count) / OVERSAMPLENR)) //subsequent readings have a smaller tollerance
raw_temp_bed_value += avgRaw;
else
raw_temp_bed_value += ADC;
} else {
raw_temp_bed_value = ADC;
}
Where raw_temp_bed_value is a static global and gets read and processed later, when the ISR got fired 16 times.
As you can see, I check if the difference between the current average and the new reading is less then 15%. If so I accept the reading, if not, I reject it and add the current average instead.
But this breaks horribly if the first reading is something impossible.
One solution I though of is:
In the last line the raw_temp_bed_value is reset to the first ADC reading. It would be better to reset this to raw_temp_bed_value/OVERSAMPLENR. So I don't run in a "first reading error".
Do you have any better solutions? I though of some solutions featuring a moving average and use the average of the moving average but this would require additional arrays/RAM/cycles which we want to prevent.
I've often used something what I call rate of change to the sampling. Use a variable that represents how many samples it takes to reach a certain value, like 20. Then keep adding your sample difference to a variable divided by the rate of change. You can still use a threshold to filter out unlikely values.
float RateOfChange = 20;
float PreviousAdcValue = 0;
float filtered = FILTER_PRESET;
while(1)
{
//isr gets adc value here
filtered = filtered + ((AdcValue - PreviousAdcValue)/RateOfChange);
PreviousAdcValue = AdcValue;
sleep();
}
Please note that this isn't exactly like a low pass filter, it responds quicker and the last value added has the most significance. But it will not change much if a single value shoots out too much, depending on the rate of change.
You can also preset the filtered value to something sensible. This prevents wild startup behavior.
It takes up to RateOfChange samples to reach a stable value. You may want to make sure the filtered value isn't used before that by using a counter to count the number of samples taken for example. If the counter is lower than RateOfChange, skip processing temperature control.
For a more advanced (temperature) control routine, I highly recommend looking into PID control loops. These add a plethora of functionality to get a fast, stable response and keep something at a certain temperature efficiently and keep oscillations to a minimum. I've used the one used in the Marlin firmware in my own projects and works quite well.

How to determine the size of a PIM within an AUTOSAR Runnable?

How can I determine the size of a PIM (Per Instance Memory) in c from inside a Runnable (without looking it up in the generated RTE and adding a fix value)?
Situation:
Runnable Foo has access to two PIMs Pim1 and Pim2. In the example the data from Pim1 shall be copied to Pim2.
Not only because of security and safety I need to check the size of both PIMs in order NOT to overwrite illegal data areas.
I know that the size of the PIM is configured in the SW-C description (SWCD). But as the SWCD may be changed after code implementation and in order to keep the code of the Runnable more generic, the size checking should not be based on fix values.
I also considered the problem of the sizeof for an array:
How to find the 'sizeof'(a pointer pointing to an array)?
For the PIMs the following code is generated by the RTE-Generator:
In Rte_Type.h
typedef uint8 Rte_DT_DtImplRec1_0;
typedef uint16 Rte_DT_DtImplRec1_1;
typedef struct
{
Rte_DT_DtImplRec1_0 var1;
Rte_DT_DtImplRec1_1 var2;
Rte_DT_DtImplRec1_2 var3;
} DtImplRec1;
typedef uint8 Rte_DT_DtImplAry1_0;
typedef Rte_DT_DtImplAry1_0 DtImplAry1[5];
In Rte.c
VAR(DtImplRec1, RTE_VAR_DEFAULT_RTE_PIM_GROUP) Rte_FOO_Pim1;
VAR(DtImplAry1, RTE_VAR_DEFAULT_RTE_PIM_GROUP) Rte_FOO_Pim2;
In Rte_FOO.h
#define Rte_Pim_Pim1() (&Rte_FOO_Pim1)
#ifdef RTE_PTR2ARRAYBASETYPE_PASSING
# define Rte_Pim_Pim2() (&((*RtePim_Pim2())[0]))
#else
# define Rte_Pim_Pim2() RtePim_Pim2()
#endif
#define RtePim_Pim2() (&Rte_FOO_Pim2)
Note that the define for array PIMs might also be changing, depending on the RTE_PTR2ARRAYBASETYPE_PASSING “switch”.
The following “access” is generated for the FOO template:
DtImplRec1 *Rte_Pim_Pim1(void);
Rte_DT_DtImplAry1_0 *Rte_Pim_Pim2(void)
The code for the Foo-Runnable may look like this:
FUNC(void, FOO_CODE) Foo(void)
{
DtImplRec1 *pim1 = Rte_Pim_Pim1();
Rte_DT_DtImplAry1_0 *pim2 = Rte_Pim_Pim2();
uint8 sizeOfPim1a = sizeof(Rte_Pim_Pim1()); /* always returns 4 as the size of the pointer */
uint8 sizeOfPim1b = sizeof(*Rte_Pim_Pim1()); /* evaluates to 6 */
uint8 sizeOfPim1c = sizeof(DtImplRec1); /* evaluates to 6 */
uint8 sizeOfPim1d = sizeof(Rte_FOO_Pim1); /* evaluates to 6 */
uint8 sizeOfPim2a = sizeof(Rte_Pim_Pim2()); /* always returns 4 as the size of the pointer */
uint8 sizeOfPim2b = sizeof(*Rte_Pim_Pim2()); /* evaluates to 1 */
uint8 sizeOfPim2c = sizeof(Rte_DT_DtImplAry1_0); /* evaluates to 1: sizeof(uint8) */
uint8 finalSize = MIN(sizeOfPim1b, sizeOfPim2b);
memcpy( pim2, pim1, finalSize ); /* (use of) memcpy is not the topic here */
}
To make my problem more "visible", here is a Callback-Runnable example for writing a DID via diagnostics:
FUNC(Std_ReturnType, FOO_CODE)
DataServices_Data_FFFF_WriteData(P2CONST(uint8, AUTOMATIC, RTE_APPL_DATA) Data, Dcm_OpStatusType OpStatus, P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, RTE_APPL_DATA) ErrorCode)
{
Std_ReturnType ret = E_NOT_OK;
#define sizeOfPim1 (5) /* how to determine the PIM size here if we do not know anything about it here? (PIM structure can change without modifying the code here) */
#define sizeOfDidFFFF (5) /* This is even another problem: How to determine the size of a DID. I will create another discussion thread for this question. */
/* Instead of this if-condition, an assert during compile-time would also be appropriate */
if( sizeOfPim1 == sizeOfDidFFFF )
{
/* We have to make sure that we do not copy more bytes as of the size of Pim1 */
memcpy( Rte_Pim_Pim1(), Data, sizeOfPim1 ); /* (use of) memcpy is not the topic here */
ret = E_OK;
}
return ret;
}
I don't have here any AUTOSAR environment to test this, so, please, if you try any of this, just let me know if it works. Besides, I am not an expert and it is quite a long time I don't write AUTOSAR code, so I will probably be missing something. I also don't want to publicize any RTE generator from any vendor, so I will cite only the standard.
Use sizeof(DtImplAry1)
You define that type and give it as input to the RTE generator, so you know the name. If your SWC doesn't make explicit use of that type the RTE generator could not include it in your .h, but you could add it manually to you SWC arxml. I think all tools out there allow to do this without having to edit the arxml by hand, just look for the option to include additional SWC types in your tool.
Use Instance API to access SWC data
The standard specifies a variable of type Rte_CDS_FOO to hold all pointers to PIMs of the SWC (among other things) if you enable the API (look for it in your tool).
Besides, a variable Rte_Inst_FOO should be available to you, declared as extern in your header. You could do sizeof(*Rte_Inst_FOO->Pim_Pim2).
EDIT: reply to some of your comments
I guess the reason you don't find the CDS is because of this (from Specification of RTE, 4.2.2, 5.4 RTE Data Structures):
The [CDS and Instance handler] definitions only apply to RTE generators operating in compatibility mode – in this mode the instance handle and the component data structure have to be defined even for those (object-code) software components for which multiple instantiation is forbidden to ensure compatibility.
Also,
[SWS_Rte_03793] If a software component does not support multiple instantiation,the name of the component data instance shall be Rte_Inst_cts, where cts is the component type symbol of the AtomicSwComponentType. (SRS_Rte_00011)
So, when the RTE-generator adheres to this compatibility mode, those variables must be there. If you are using a vendor specific solution, well, try to tag the question with that vendor name also, hopefully somebody can answer.
Assert at compile time
I am not going to ask why you are doing this, but IMHO I think it does not sound right, does it makes sense for the receiving buffer to be smaller that the data to copy?. Maybe it is better to assert at compile time if the buffer is smaller than your struct. Or you could define your array instead to be a struct and cast it if needed (if your are following MISRA rules, maybe you will have problems with it, just check). Just for reference, compile time assertions can use sizeof.
You have several problems here:
a) your sizeof(*pim1) returns 6 because of padding, because you start with an uint8, the second is uint16, and I guess the 3rd ist also uint16.
That's, why you should rather sort them by type size/alignment .. biggest to smallest
uint32
uint16
uint8
Even though, the elements might not be ordered anymore, but it also decreases finally the gaps in memory created by the linker.
b) the pim2 is an array, you can not get the array len/size from the pointer.
But, you should have the Rte definition of DtImplAry1.
typedef uint8 Rte_DT_DtImplAry1_0;
typedef Rte_DT_DtImplAry1_0 DtImplAry1[5]; // <-- taken in through Rte_Foo_Type.h (includes Rte_Type.h
uint32 ary_len = sizeof(DtImplAry1) / sizeof(DtImplAry1[0]);

Forward error correction using Reed-Solomon Erasure Correction

I have the task of encoding and decoding some bytes of sound using parity checksum method and Reed-Solomon Erasure Correction.
I've done my encoding for first method(parity checksum) but need help completing the second method which is detection by Reed-Solomon Erasure Correction.
So far I know that, RS code adds t symbols to k symbols of data. So it is able to locate and correct up to t/2 symbols or if the error locations are known so called erasures. It can correct up to t. For this task I have to use Galois field GF(28) to represent each symbol as a byte. Operation addition and subtraction are based on XOR. So over all I have to employ Reed-Solomon codes that are capable of correction up to t=3 erasures. The computation of a single Reed Solomon code in now as follow
C0 | C1 |........| Ck-1 | Ck | Ck+1 | Ck+2
so the code bytes can be viewed as vector c=[c0,c1,...,ck+2]
and a single code C is computed from k bytes of data as follow
d=[d0,d1,...,dk-1], so my encoding and decoding process require the following Vandermonde matrix F
1 1 12 13 ... 1k-1
1 2 22 23 ... 2k-1
...
1 k+2 (k+2)2 (k+2)3 ... (k+2)k-1
1 k+3 (k+3)2 (k+3)3 ... (k+3)k-1
so a simple matrix vector multiplication using F & D we get C=F.D.
so far what I did for encoding is as follow :
#else
void fox_encode(Buffer* bufin, Buffer* bufout, FoxEncData* algorithm_data){
// Your encoder for Task 2.C.3 goes in here !!!
while (bufin->size >= 1){
guint8 databyte = bufin->data[0]; //Pick up a byte from input buffer
buffer_push_byte (bufout, databyte); //Send it 3 times
buffer_push_byte (bufout, databyte);
buffer_push_byte (bufout, databyte);
buffer_pop (bufin, 1); //Remove it from the input buffer
}
}
#endif
I need code to complete this code for encoding and decoding my fox_encode and fox_decode class using Reed-Solomon Erasure Correction. Any Help will be appreciated to complete this task as soon as possible.
Thanks in advance
You can take look at my RS(255,255-k) C-implementation which is available from my homepage.
It handles both errors and erasures and corrects any byte error/erasure patterns bounded by:
(2*errorCount + erasureCount) <= k.
There is now a good tutorial on Wikiversity which details how to handle both erasures and errors.
Here is an outline of what you need to implement for the erasures decoding process:
Compute the syndromes. Then check if it's all 0 coefficients, the message does not need correction, else continue.
Call the Forney algorithm with the syndrome and the erasures positions as input to compute the erasure magnitude polynomial (ie, the values to subtract from message polynomial to get the original message back).
Subtract message - erasure_magnitude_polynomial to recover your original message (if within Singleton bound).
Apart from the Forney algorithm which can be a bit involving, all the other parts are very simple and straightforward. Indeed, the most difficult parts such as Berlekamp-Massey algorithm and Chien search are only necessary when you want to decode errors, and Forney syndromes computation is only necessary if you want to correct both erasures and errors (ie, errata) -- although I have read some paper which describe that Forney syndromes computation can be bypassed, but I never seen such a code.

Finding position of '1's efficiently in an bit array

I'm wiring a program that tests a set of wires for open or short circuits. The program, which runs on an AVR, drives a test vector (a walking '1') onto the wires and receives the result back. It compares this resultant vector with the expected data which is already stored on an SD Card or external EEPROM.
Here's an example, assume we have a set of 8 wires all of which are straight through i.e. they have no junctions. So if we drive 0b00000010 we should receive 0b00000010.
Suppose we receive 0b11000010. This implies there is a short circuit between wire 7,8 and wire 2. I can detect which bits I'm interested in by 0b00000010 ^ 0b11000010 = 0b11000000. This tells me clearly wire 7 and 8 are at fault but how do I find the position of these '1's efficiently in an large bit-array. It's easy to do this for just 8 wires using bit masks but the system I'm developing must handle up to 300 wires (bits). Before I started using macros like the following and testing each bit in an array of 300*300-bits I wanted to ask here if there was a more elegant solution.
#define BITMASK(b) (1 << ((b) % 8))
#define BITSLOT(b) ((b / 8))
#define BITSET(a, b) ((a)[BITSLOT(b)] |= BITMASK(b))
#define BITCLEAR(a,b) ((a)[BITSLOT(b)] &= ~BITMASK(b))
#define BITTEST(a,b) ((a)[BITSLOT(b)] & BITMASK(b))
#define BITNSLOTS(nb) ((nb + 8 - 1) / 8)
Just to further show how to detect an open circuit. Expected data: 0b00000010, received data: 0b00000000 (the wire isn't pulled high). 0b00000010 ^ 0b00000000 = 0b0b00000010 - wire 2 is open.
NOTE: I know testing 300 wires is not something the tiny RAM inside an AVR Mega 1281 can handle, that is why I'll split this into groups i.e. test 50 wires, compare, display result and then move forward.
Many architectures provide specific instructions for locating the first set bit in a word, or for counting the number of set bits. Compilers usually provide intrinsics for these operations, so that you don't have to write inline assembly. GCC, for example, provides __builtin_ffs, __builtin_ctz, __builtin_popcount, etc., each of which should map to the appropriate instruction on the target architecture, exploiting bit-level parallelism.
If the target architecture doesn't support these, an efficient software implementation is emitted by the compiler. The naive approach of testing the vector bit by bit in software is not very efficient.
If your compiler doesn't implement these, you can still code your own implementation using a de Bruijn sequence.
How often do you expect faults? If you don't expect them that often, then it seems pointless to optimize the "fault exists" case -- the only part that will really matter for speed is the "no fault" case.
To optimize the no-fault case, simply XOR the actual result with the expected result and a input ^ expected == 0 test to see if any bits are set.
You can use a similar strategy to optimize the "few faults" case, if you further expect the number of faults to typically be small when they do exist -- mask the input ^ expected value to get just the first 8 bits, just the second 8 bits, and so on, and compare each of those results to zero. Then, you just need to search for the set bits within the ones that are not equal to zero, which should narrow the search space to something that can be done pretty quickly.
You can use a lookup table. For example log-base-2 lookup table of 255 bytes can be used to find the most-significant 1-bit in a byte:
uint8_t bit1 = log2[bit_mask];
where log2 is defined as follows:
uint8_t const log2[] = {
0, /* not used log2[0] */
0, /* log2[0x01] */
1, 1 /* log2[0x02], log2[0x03] */
2, 2, 2, 2, /* log2[0x04],..,log2[0x07] */
3, 3, 3, 3, 3, 3, 3, 3, /* log2[0x08],..,log2[0x0F */
...
}
On most processors a lookup table like this will go to ROM. But AVR is a Harvard machine and to place data in code space (ROM) requires special non-standard extension, which depends on the compiler. For example the IAR AVR compiler would need use the extended keyword __flash. In WinAVR (GNU AVR) you would need to use the PROGMEM attribute, but it's more complex than that, because you would also need to use special macros to to read from the program space.
I think there is only one way to do this:
Create an array out "outdata". Each item of the array can for example correspond an 8-bit port register.
Send the outdata on the wires.
Read back this data as "indata".
Store the indata in an array mapped exactly as the outdata.
In a loop, XOR each byte of outdata with each byte of indata.
I would strongly recommend inline functions instead of those macros.
Why can't your MCU handle 300 wires?
300/8 = 37.5 bytes. Rounded to 38. It needs to be stored twice, outdata and indata, 38*2 = 76 bytes.
You can't spare 76 bytes of RAM?
I think you're missing the forest through the trees. Seems like a bed of nails test. First test some assumptions:
1) You know which pins should be live for each pin tested/energized.
2) you have a netlist translated for step 1 into a file on sd
If you operate on a byte level as well as bit, it simplifies the issue. If you energize a pin, there is an expected pattern out stored in your file. First find the mismatched bytes; identify mismatched pins in the byte; finally store the energized pin with the faulty pin numbers.
You don't need an array for searching, or results. general idea:
numwires=300;
numbytes=numwires/8 + (numwires%8)?1:0;
for(unsigned char currbyte=0; currbyte<numbytes; currbyte++)
{
unsigned char testbyte=inchar(baseaddr+currbyte)
unsigned char goodbyte=getgoodbyte(testpin,currbyte/*byte offset*/);
if( testbyte ^ goodbyte){
// have a mismatch report the pins
for(j=0, mask=0x01; mask<0x80;mask<<=1, j++){
if( (mask & testbyte) != (mask & goodbyte)) // for clarity
logbadpin(testpin, currbyte*8+j/*pin/wirevalue*/, mask & testbyte /*bad value*/);
}
}

Resources