Building an Array of #define Directives - c

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;
...
}

Related

Usage of Xilinx built-in UART function #define XUartPs_IsReceiveData (BaseAddress )

So I am trying to use this built-in UART function (from the Vitis SDK from Xilinix) to determine if there is a valid byte to read over UART. I created this function to return 1 if there was a byte to read or 0 if there wasn't
u32 UartHasMessage(void){
if(XUartPs_IsReceiveData(&XUartPs_Main)){
return 1;
}
else{
return 0;
}
}
However, even when there is a byte to read over UART, this function always returns false.
The weird behavior I am experiencing is when I step through the code using the debugger, I call UartHasMessage() to check if there is a byte to read, and it returns false, but in the next line I call a function to read a byte over UART and that contains the correct byte I sent over the host.
u32 test - UartHasMessage();
UartGetByte(&HostReply);
How come this UartHasMessage always returns false, but then in the next line I am able to read the byte correctly?
Caveat: Without some more information, this is a bit speculative and might be a comment, but it is too large for that.
The information below comes from the Xilinx documentation on various pages ...
XUartPs_RecvByte will block until a byte is ready. So, no need to call XUartPs_IsReceiveData directly (I think that XUartPS_RecvByte calls it internally).
A web search on XUartPs_Main came up with nothing, so we'd need to see the definition you have.
Most Xilinx documentation uses UART_BASEADDRESS:
#define UART_BASEADDR XPAR_XUARTPS_0_BASEADDR
I found a definition:
#define XPAR_XUARTPS_0_BASEADDR 0xE0001000
You might be better off using a more standard method, such as calling the XUartPs_LookupConfig function to get the configuration table entry which has all relevant values.
I'm guessing that you created the XUartPS_Main definition.
But, based on what you posted, (needing &XUartPS_Main instead of XUartPS_Main), it is linked/loaded at the exact address of the UART register bank. Let's assume that address is (e.g.) 0x10000. So, we might have:
u32 XUartPS_Main __attribute__(at(0x10000));
The at is an extension that some build systems support (e.g. arm) that forces the variable to be loaded at a given address. So, let's assume we have that (even if the mechanism is slightly different (e.g.):
__attribute__((section(".ARM.__at_0x10000")))
The definition of XUARTPS_SR_OFFSET is:
#define XUARTPS_SR_OFFSET 0x002CU
Offsets are [typically] byte offsets.
Given:
#define XUartPs_IsReceiveData(BaseAddress) \
!((Xil_In32((BaseAddress) + XUARTPS_SR_OFFSET) & \
(u32)XUARTPS_SR_RXEMPTY) == (u32)XUARTPS_SR_RXEMPTY)
Now if the definition of XUartPS_Main uses u32 [as above], we may have a problem because XUARTPS_SR_OFFSET will be treated as a u32 index and not a byte offset. So, it will access the wrong address.
So, try:
XUartPs_IsReceiveData((unsigned char *) &XUartPs_Main)
But, if it were me, I'd rework things to use Xilinx's standard definitions.
UPDATE:
Hi so XUartPs_main is defined as static XUartPs XUartPs_Main; I use it in a variety of functions such as a function to send bytes over uart and I call it by its address like I did with this function, all my other functions work as expected except this one. Is it possible it is something to do with the way the fifo works? –
29belgrade29
No, not all the API functions are the same.
The struct definition is [I synthesized this from the API doc]:
typedef struct {
u16 DeviceId; // Unique ID of device.
u32 BaseAddress; // Base address of device (IPIF)
u32 InputClockHz;
} XUartPs;
Somewhere in your code you had to initialize this with:
XUartPs_Main = XUartPs_ConfigTable[my_device_id];
Or, with:
XUartPs_Main = *XUartPs_LookupConfig(my_device_id);
If an API function is defined as (e.g.):
void api_dosomething(XUartPs_Config *cfg,...)
Then, you call it with:
api_dosomething(&XUartPs_Main,...);
So, most functions probably take such a pointer.
But, XUartPs_IsReceiveData does not want a pointer to a XUartPs_Config struct. It wants a base address. This is:
XUartPs_Main.BaseAddress
So, you want:
XUartPs_IsReceiveData(XUartPs_Main.BaseAddress)

How to prohibit compiler to precompute product of constant values

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

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]);

C - Why compare constants with & instead of switch/if?

I am reading the OpenSL documentation for Android. Quoting the following document: http://mobilepearls.com/labs/native-android-api/ndk/docs/opensles/
"Callback handlers should be prepared to be called more or less frequently, to receive additional event types, and should ignore event types that they do not recognize. Callbacks that are configured with an event mask of enabled event types should be prepared to be called with multiple event type bits set simultaneously. Use "&" to test for each event bit rather than a switch case."
Checking the official specification of OpenSL (https://www.khronos.org/registry/sles/specs/OpenSL_ES_Specification_1.0.1.pdf), there are these 3 constants defined I am interested in:
SL_PREFETCHSTATUS
#define SL_PREFETCHSTATUS_UNDERFLOW ((SLuint32) 0x00000001)
#define SL_PREFETCHSTATUS_SUFFICIENTDATA ((SLuint32) 0x00000002)
#define SL_PREFETCHSTATUS_OVERFLOW ((SLuint32) 0x00000003)
If I understood correctly, the quote above says to compare using &, like this:
if(status & SL_PREFETCHSTATUS_UNDERFLOW) doSomething_1();
if(status & SL_PREFETCHSTATUS_SUFFICIENTDATA) doSomething_2();
if(status & SL_PREFETCHSTATUS_OVERFLOW) doSomething_3();
Instead of a switch case:
switch(statusCode){
case(SL_PREFETCHSTATUS_UNDERFLOW): doSomething_1(); break;
case(SL_PREFETCHSTATUS_SUFFICIENTDATA): doSomething_2(); break;
case(SL_PREFETCHSTATUS_OVERFLOW): doSomething_3(); break;
}
Now, I don't understand why that is exactly. Can anyone explain me the reason?
PS: If the constants were defined in multiples of 2, like this:
#define SL_PREFETCHSTATUS_UNDERFLOW ((SLuint32) 0x00000001)
#define SL_PREFETCHSTATUS_SUFFICIENTDATA ((SLuint32) 0x00000002)
#define SL_PREFETCHSTATUS_OVERFLOW ((SLuint32) 0x00000004)
It would make sense, but the specification defines the last constant as 0x00000003 instead of 0x00000004, so I am lost.
That comment is in reference to the event constants. What you're looking at are not event constants, but rather status constants. Event constants would be for example:
#define SL_PLAYEVENT_HEADATEND ((SLuint32) 0x00000001)
#define SL_PLAYEVENT_HEADATMARKER ((SLuint32) 0x00000002)
#define SL_PLAYEVENT_HEADATNEWPOS ((SLuint32) 0x00000004)
#define SL_PLAYEVENT_HEADMOVING ((SLuint32) 0x00000008)
#define SL_PLAYEVENT_HEADSTALLED ((SLuint32) 0x00000010)
You can see these are bitmask values and could be combined. Since they can be combined you need to compare the individual bits rather than the whole value to ensure you correctly match against the events you're interested in.
The documentation makes it clear:
Callbacks that are configured with an event mask of enabled event types should be prepared to be called with multiple event type bits set simultaneously.
This means that despite the flags not being bitwise, there still remains the possibility that multiple flags are set. The other flags being set might not necessarily be publicly-defined, but could be private, reserved or otherwise undocumented but still necessary for the system to function.
...so using a switch is not a good idea because then this fails:
SLuint32 statusCode = SL_PRIVATE_RESERVED_INTERNAL_USE_ONLY | SL_PREFETCH_STATUS_UNDERFLOW;
switch( statusCode ) {
case SL_PREFETCH_STATUS_UNDERFLOW:
// this code will never be executed
break;
}
Using & does bitwise comparison. So a & b gives a non-zero results if any of the bits are set in both a and b. That is not the same as comparing the values (for a given non-zero value of a, there are multiple values of b that can give a match).

How does this sfrw(x,x_) macro work (msp430)?

I just ran into an interesting phenomenon with msp430f5529 (TI launchpad). After trying different approaches I was able to find a solution, but I don't understand what is going on here.
This code is part of a timer interrupt service routine (ISR). The special function register (SFR) TA0IV is supposed to hold the value of the interrupt number that triggered the ISR.
1 unsigned int index;
2
3 index = TA0IV; // Gives wrong value: 19874
4 index = *((volatile unsigned int *) TA0IV_); // Correct value: 4
TA0IV is defined with macros here:
5 #define sfrw_(x,x_) volatile __MSPGCC_PERIPHERAL__ unsigned int x __asm__("__" #x)
6 #define sfrw(x,x_) extern sfrw_(x,x_)
7 #define TA0IV_ 0x036E /* Timer0_A5 Interrupt Vector Word */
8 sfrw(TA0IV, TA0IV_);
What does this part of the first macro on line 5 do?
asm("__" #x)
Why is there no "x_" on the right hand side in the macro on line 5?
Last and most important question: Why does the usual typecasting on line 4 work as expected, but the one on line 3 doesn't?
BTW I use gcc-4.7.0.
Edit: More info
9 #define __MSPGCC_PERIPHERAL__ __attribute__((__d16__))
1) The # is a preprocessor "stringify" operator. You can see the impact of this using the -E compiler switch. Google "c stringify" for details.
2) Couldn't say. It isn't required that all parameters get used, and apparently whoever wrote this decided they didn't need it.
3) I'll take a shot at this one, but since I don't have all the source code or the hardware and can't experiment, I probably won't get it quite right. Maybe close enough for what you need though.
The first thing to understand is what the asm bit is doing. Normally (ok, sometimes) when you declare a variable (foo), the compiler assigns its own 'internal' name to the variable (ie _foo). However, when interfacing with asm modules (or other languages), sometimes you need to be able to specify the exact name to use, not allowing the compiler to mangle it in any fashion. That's what this asm is doing (see Asm Labels). So when you brush aside all the #define nonsense, what you've got is:
extern volatile __MSPGCC_PERIPHERAL__ unsigned int TA0IV __asm__("__TA0IV");
Since the definition you have posted is "extern," presumably somewhere (not shown), there's a symbol named __TA0IV that's getting defined. And since accessing it isn't working right, it appears that it is getting MIS-defined.
With the caveat that I HAVEN'T TRIED THIS, I would find this to be somewhat more readable:
#define TA0IV_ 0x036E
inline int ReadInterruptNumber()
{
int retval;
asm volatile("movl (%c1), %0": "=rm" (retval) : "i" (TA0IV_));
return retval;
}
FWIW.

Resources