I'm trying to move every declaration of the following macro into another memory segment. It works fine without the section attribute. Any ideas on why I can't use it here, and how I could make it work?
#define RINGBUFFER_DECLARE_MEMB(var, sz) \
uint8_t var ## __buf[sz] __attribute__((section(".rambss"))); \
struct ring_buffer var __attribute__((section(".rambss")))
device.h:91:29: error: section attribute not allowed for
'__iso_buf__buf'
RINGBUFFER_DECLARE_MEMB(__iso_buf, BUF_SIZE_ISOLATED);
Stupid me, the problem was that the macro was used in a structure defenition:
struct a {
RINGBUFFER_DECLARE_MEMB(umama, 3);
};
Which is ofcourse not allowed
Related
I am trying to simulate generics in C by having some preprocessor definitions for a matrix type. Here is an excerpt of that:
#define __matrix_struct(TYPE) \
struct { \
uint32_t sz; \
TYPE **ptr; \
}
#define __matrix_t(TYPE) matrix_ ## TYPE
#define __matrix_ptr_t(TYPE) __matrix_t(TYPE) *
#define __matrix_typedef(TYPE) typedef __matrix_struct(TYPE) __matrix_t(TYPE)
#define __matrix_allocator_name(TYPE) TYPE ## _matrix_alloc
#define __matrix_allocator(TYPE) \
__matrix_ptr_t(TYPE) __matrix_allocator_name(TYPE) (uint32_t sz) { \
uint32_t i; \
__matrix_ptr_t(TYPE) m = (__matrix_ptr_t(TYPE)) malloc(sizeof(__matrix_t(TYPE))); \
m->ptr = (TYPE **) malloc(sz * sizeof(TYPE *)); \
for (i = 0; i < sz; ++i) { \
m->ptr[i] = (TYPE *) calloc(sz, sizeof(TYPE)); \
} \
return m; \
}
#define __matrix_deallocator_name(TYPE) TYPE ## _matrix_free
#define __matrix_deallocator(TYPE) \
void __matrix_deallocator_name(TYPE) (__matrix_ptr_t(TYPE) m) { \
uint32_t i; \
for (i = 0; i < m->sz; i++) { \
free(m->ptr[i]); \
} \
free(m->ptr); \
free(m); \
}
#define matrix_alloc_ptr(TYPE, SIZE) __matrix_allocator_name(TYPE) (SIZE)
#define matrix_dealloc_ptr(TYPE, PTR_NAME) __matrix_deallocator_name(TYPE) (PTR_NAME)
In another file, byte_matrix.h, I am trying to define a matrix of uint8_t values, as follows:
#include "matrix.h"
typedef uint8_t byte;
__matrix_typedef(byte);
__matrix_allocator(byte)
__matrix_deallocator(byte)
When I try to compile, I get the following errors:
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_alloc':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: multiple definition of `byte_matrix_alloc'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: first defined here
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_free':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: multiple definition of `byte_matrix_free'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: first defined here
I cannot understand why it would point to times to the same line and complain about that definition, since every header I wrote has include guards. Could you please explain this to me? Also if you know of a better approach to my problem, please let me know. Thanks.
Also I need to compile with -std=c99 if that matters in this case.
A quick fix would be to add static to your function definitions. This will create a static copy of these functions in each compilation unit which references the header. If you want the functions to be inlined every time, this is the way to go.
An alternative way to do it would be to keep function declarations in a .h file, and actual definitions in a single .c file. This approach will avoid duplication, and the compiler will not inline them (unless your linker supports link time optimization).
The reason is that you are including this header file in multiple compilation units. After the preprocessor does all the textual replacements, you end up with actual separate function definitions inside your .c files. And if you don't specify that you want them to be static, they are by default extern, which means that now the compiler doesn't know how to differentiate them if some other part of the code wants to call them.
This is what you basically do whenever you create a header file: you create a list of declarations which will be included in many compilation units, but there is always a single extern definition in a single .c file.
Another way (relative to the proposed by Groo) is to create two macros.
__matrix_allocator_declare with just prototype of function -- for h-file(s)
__matrix_allocator_define with function body -- for one (selected by you) c-file
This way requires to handle two macros and to not forget add function-body macro in some file, but (and it is more important for embedded applications on small microcontrollers) it guarantees that only one function instance will consume memory.
So I have some code that is throwing me an error and I am not sure why. I am using a macro to generate myself a string array and an enum that I can use to access the string array in a intuitive way. My compiler is complaining about my macro but the rest of my code seems to work as if the macro successfully created the enum which has me quite confused.
The macro is as follow
#define FOR_EACH_PHASE(PHASE) \
PHASE(init) \
PHASE(framerate) \
PHASE(priority) \
PHASE(time) \
PHASE(powersave) \
PHASE(performance) \
PHASE(response)
#define GENERATE_ENUM(ENUM) AI_phase_##ENUM,
#define GENERATE_STRING(STRING) "AI_phase_"#STRING,
typedef enum PHASE_ENUM PHASE_ENUM_t;
enum PHASE_ENUM {
FOR_EACH_PHASE(GENERATE_ENUM)
END
};
static const char* PHASE_STRINGS[] = {
FOR_EACH_PHASE(GENERATE_STRING)
};
Lines such as these seems to compile without error
struct phase_profile* set_defaults;
set_defaults = AI_phases_get_name(PHASE_STRINGS[AI_phase_framerate]);
But the compiler is giving me the following error for each line of my FOR_EACH_PHASE macro
error: 'performance' undeclared (first use in this function)
Any ideas from anyone that knows more about this than me?
Cheers
I don't have the required reputation to comment so I am posting this as an answer.
I believe you need this:
https://www.codeproject.com/Articles/32000/Improving-C-Enums-Adding-Serialization-Inheritance
I use it for some years now and it is fine!
I am attempting to make a section of code a bit more generic for a microcontroller that I am currently programming for.
What I want is a specific macro, formed from other tokens via concatenation. The problem is that one of the tokens is defined as a specific memory address (i.e. a register) and thus "garbage" is substituted mid-way. The following snippet illustrates the problem:
#include <stdio.h>
#include <stdint.h>
// The actual final token that I want (because I want the value of 10)
#define I_DRINK_BEER 10
// This line is the problematic line!
// It us defined in the microcontroller-specific header
// If this line is not defined, it works perfectly as desired.
#define DRINK (*(uint32_t*) (0x8000))
#define ACTION DRINK
#define INDIRECT(who,action,what) who ## action ## what
#define TOKEN_PASTE(who,action,what) INDIRECT(who,action,what)
#define CONSUMPTION(who,what) TOKEN_PASTE(who,ACTION,what)
int main(void)
{
printf("Value = %d\n", CONSUMPTION(I_,_BEER));
return 0;
}
If the line "#define DRINK ..." is commented out, the program compiles and executes as desired:
damien#damien-desktop:~$ gcc -o test test_macro_expansion.c
damien#damien-desktop:~$ ./test
Value = 10
But the inclusion of the offending line substitutes the complete address that makes the pre-processor complain:
test_macro_expansion.c: In function ‘main’:
test_macro_expansion.c:21:1: error: pasting "I_" and "(" does not give a valid preprocessing token
test_macro_expansion.c:21:1: error: pasting ")" and "_BEER" does not give a valid preprocessing token
test_macro_expansion.c:21:28: error: expected ‘)’ before ‘_BEER’
Is there a way I can tell the pre-processor not to substitute a particular token any further?
Why??
Before this seems a little esoteric, I have a timer for some particular functionality that is assigned to timer/counter "TCC0" in one project and "TCD1" in another project. It happens to be defined in as the base address of the register block for each timer, respectively. So, I have in my config header:
#define PERIPHERAL_TIMER TCC0
Which, works well in the main, because the registers of the timer can be referenced easily, for example:
value = PERIPHERAL_TIMER.CCA;
Deep in the toolchain, TCC0 is defined:
#define TCC0 (*(TC0_t *) 0x0800) /* Timer/Counter C0 */
The problem is that I have other macros defined in that have the TCC0) as part of the the name that I need elsewhere, for example:
// Note the TCC0 in the function argument!
EventSystem_SetEventSource(EVSYS_CHMUX_TCC0_OVF_gc);
Hence, I would like to define the symbol
// Conceptually what I want!
#define EVENT_SOURCE(timer) EVSYS_CHMUX_ ## timer ## _OVF_gc
// The "PERIPHERAL_TIMER" gets expanded to the address, not the token that I want
#define PERIPHERAL_EVENT EVENT_SOURCE(PERIPHERAL_TIMER)
I hope this clears up why I am asking the question.
#define DRINK (*(uint32_t) (0x8000)). this line has an error which is as UNDEFINED Symbol uint .
Well, the simplest, easiest workaround that solves this particular issue is:
// It was this...
// #define PERIPHERAL_TIMER TCC0
// And is now this
#define PERIPHERAL_TIMER_SUFFIX C0
So the macros can be easily defined:
// Conceptually what I want - modified, but be sure to use
// indirect substitution as required.
#define EVENT_SOURCE(timer) EVSYS_CHMUX_TC ## timer ## _OVF_gc
And PERIPHERAL_TIMER can still be defined for direct register access:
// Don't forget, you'll need to use indirect substitution
#define PERIPHERAL_TIMER TC ## PERIPHERAL_TIMER_SUFFIX
// Registers can still be access as:
value = PERIPHERAL_TIMER.CCA;
NOTE: Indirect substitution in this post refers to the technique in this answer.
I have a doubt about a syntax used in linux kernel code. I have an intuition of what it does but I want to know it more formally. I am using kernel v3.5.4
In file /include/linux/sched.h the following is defined
struct task_struct {
volatile long state;
//some more data members
};
and in file /include/linux/init_task.h file the following is defined:
#define INIT_TASK(tsk) {
.state = 0, \
//some more initializations
}
I am confused about two things:
a) I feel it is used for initialization but can anyone suggest some good read for this type of initialization for structures.
b) I do not understand how the following initialization works. Like how this #define and the corresponding task_struct structure are related.
[EDIT]
I noticed the following things also:
c) Is \ at the end of every line necessary.
d) There are many parts of kernel doe wrapped in #ifdef #endif. If you want to initialize a data member wrapped in #ifdef #endif can we use this form of initialization. I mean can we use #ifdef #endif inside INIT_TASK() like this
#define INIT_TASK(tsk) {
.state = 0, \
//some more initializations
#ifdef CX
.tickets = 5, \
#endif
}
struct task_struct whatever = INIT_TASK(someTsk);
This results in the following code:
struct task_struct whatever = { .state = 0 };
which is valid C syntax to initialize fields in a struct via their name instead of their position. Doing so makes the code safe against struct members that are not added at the last position.
Regarding the backslashes: Yes, they are necessary so the preprocessor knows that the macro continues on the next line.
No, you cannot use #ifdef inside a macro.
I am attempting to alter an IAR specific header file for a lpc2138 so it can compile with Visual Studio 2008 (to enable compatible unit testing).
My problem involves converting register definitions to be hardware independent (not at a memory address)
The "IAR-safe macro" is:
#define __IO_REG32_BIT(NAME, ADDRESS, ATTRIBUTE, BIT_STRUCT) \
volatile __no_init ATTRIBUTE union \
{ \
unsigned long NAME; \
BIT_STRUCT NAME ## _bit; \
} # ADDRESS
//declaration
//(where __gpio0_bits is a structure that names
//each of the 32 bits as P0_0, P0_1, etc)
__IO_REG32_BIT(IO0PIN,0xE0028000,__READ_WRITE,__gpio0_bits);
//usage
IO0PIN = 0x0xAA55AA55;
IO0PIN_bit.P0_5 = 0;
This is my comparable "hardware independent" code:
#define __IO_REG32_BIT(NAME, BIT_STRUCT)\
volatile union \
{ \
unsigned long NAME; \
BIT_STRUCT NAME##_bit; \
} NAME;
//declaration
__IO_REG32_BIT(IO0PIN,__gpio0_bits);
//usage
IO0PIN.IO0PIN = 0xAA55AA55;
IO0PIN.IO0PIN_bit.P0_5 = 1;
This compiles and works but quite obviously my "hardware independent" usage does not match the "IAR-safe" usage.
How do I alter my macro so I can use IO0PIN the same way I do in IAR? I feel this is a simple anonymous union matter but multiple attempts and variants have proven unsuccessful. Maybe the IAR GNU compiler supports anonymous unions and vs2008 does not.
Thank you.
Ok folks here's what ended up working for me:
#define __IO_REG32_BIT(NAME, BIT_STRUCT)\
volatile union\
{\
unsigned long NAME;\
BIT_STRUCT NAME##_bit;\
} NAME##_type;
__IO_REG32_BIT(IO0PIN,__gpio0_bits);
#define IO0PIN IO0PIN_type.IO0PIN
#define IO0PIN_bit IO0PIN_type.IO0PIN_bit
Now I can use the following in my code for unit testing:
IO0PIN = 0xFFFFFFFF;
IO0PIN_bit.P0_5 = 1;
And the preprocessor will replace it with:
IO0PIN_type.IO0PIN = 0xFFFFFFFF;
IO0PIN_type.IO0PIN_bit.P0_5 = 1;
The usual way of doing this is with a macro that just casts the desired address to the appropriate type:
#define __IO_REG32_BIT(NAME, BIT_STRUCT) \
typedef volatile union \
{ \
unsigned long NAME##_value: \
BIT_STRUCT NAME##_bit; \
} NAME##_type
__IO_REG32_BIT(IO0PIN, __gpio0_bits);
#define IO0PIN (*(IO0PIN_type *)0xE0028000)
Now IO0PIN can be used just as you described. However, note that I had to rename the internal field and type name to avoid conflicting with the macro name IO0PIN. You can of course rename things to your liking.
I know this isn't an answer but I don't have enough reputation to edit the question. I hope this might be helpful for clarification. If you take all of the macros out of the picture, what Alan_m wants to end up with is an anonymous union like the following:
volatile union {
u32 IO0PIN;
u16 IO0PIN_bit;
};
That can be referenced like this:
void test( void )
{
IO0PIN = 0x0xAA55AA55;
IO0PIN_bit.P0_5 = 0;
}
This works O.K. with the IAR compiler but causes a compiler error on the VC++ compiler
error C2646: global anonymous unions
must be declared static
Note that this is from VS2005 so it might be slightly different than VS2008.
I would imagine all of Alan_m's code is already written to IAR standards and would have to be modified to use named unions which he wants to avoid.