Embedded C, and AVR GCC compilation issue with multiple definitions - c

It seems that my compiler does not willing to build the firmware in stepper_motor.c and as you can see below, it throws this error, which I am unable to solve.
I have created a stepper_motor.c source where all my functions and variables are placed, and a stepper_motor.h header where all the #defines and function prototypes are. In main.c I just include the stepper_motor.h header and use the functions. As you can see from shell log data, it does not compile and tells that 4 x variables are defined multiple times. Those ones are used in ISR() routine for a timer, so they need to be also volatile.
Any information would be highly appreciated on this issue.
this is my main.c includes: --------
#include <avr/io.h>
#include <Hardware_Bay.h>
#include <util/delay.h>
#include <USART.h>
#include <string.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
#include <avr/interrupt.h>
#include <scale16.h>
#include <stepper_motor.h>
const uint8_t motor_Phases[] = {
(1 << COIL_B1), // full step
(1 << COIL_B1) | (1 << COIL_A2), // half step
(1 << COIL_A2), // full step
(1 << COIL_A2) | (1 << COIL_B2), // half step
(1 << COIL_B2), // full step
(1 << COIL_B2) | (1 << COIL_A1), // etc..
(1 << COIL_A1),
(1 << COIL_A1) | (1 << COIL_B1),
};
volatile uint8_t stepPhase = 0;
volatile uint16_t stepCounter = 0;
volatile int8_t direction = FORWARD;
ISR(TIMER0_COMPA_vect) { // Timer/Counter-0 Compare match interrupt vector enable
stepPhase += direction; // take step in right direction
stepPhase &= 0b00000111; // keep the stepPhase in range (0 - 7)
STEPPER_PORT = motor_Phases[stepPhase]; // write phase out to motor COIL-1 A/B
HALL_PORT = motor_Phases[stepPhase]; // write phase out to motor COIL-2 A/B
stepCounter ++;
}
------------------------------header file -----------------------------------------------
#ifndef STEPPER_MOTOR_H_INCLUDED
#define STEPPER_MOTOR_H_INCLUDED
#endif // STEPPER_MOTOR_H_INCLUDED
#define FORWARD 1
#define BACKWARD -1
#define TURN 200
#define MAX_DELAY 255
#define MIN_DELAY 10
#define ACCELERATION 16
#define RAMP_STEPS (MAX_DELAY - MIN_DELAY) / ACCELERATION
void stepperDrive(uint8_t number_of_steps, uint8_t delay);
void trapezoidDrive_Stepper(int16_t number_of_steps);
PS D:\Users\Arhitect\Documents\C_Programs\Physalis_Banshee\Physalis_GEO_version_3.6> make flash
avr-gcc -Wl,-Map,Physalis_GEO_version_3.6.map -Wl,--gc-sections -mmcu=atmega1284p fuse.o main.o stepper_motor.o USART.o -o Physalis_GEO_version_3.6.elf
stepper_motor.o: In function `stepperDrive':
D:\Users\Arhitect\Documents\C_Programs\Physalis_Banshee\Physalis_GEO_version_3.6/stepper_motor.c:50: multiple definition of `stepCounter'
main.o:(.bss.stepCounter+0x0): first defined here
stepper_motor.o:(.data.direction+0x0): multiple definition of `direction'
main.o:(.data.direction+0x0): first defined here
stepper_motor.o:(.rodata.motor_Phases+0x0): multiple definition of `motor_Phases'
main.o:(.rodata.motor_Phases+0x0): first defined here
stepper_motor.o: In function `stepperDrive':
D:\Users\Arhitect\Documents\C_Programs\Physalis_Banshee\Physalis_GEO_version_3.6/stepper_motor.c:50: multiple definition of `stepPhase'
main.o:(.bss.stepPhase+0x0): first defined here
make: *** [Physalis_GEO_version_3.6.elf] Error 1
PS D:\Users\Arhitect\Documents\C_Programs\Physalis_Banshee\Physalis_GEO_version_3.6>

Really the error messages tell you all you need to know - you have defined these symbols in two places - main.c and setpper_motor.c.
You have defined stepCounter at line 50 of stepper_motor.c and also as shown in main.c. Similarly for stepPase and motor_Phases.
If they are independent and should not be visible externally then
both should be declared static so that they are visible only in
their respective translation units.
If it is intended that the symbol refers to the they are the same object, then one of them needs to be declared extern to indicate to the compiler its type and name, but that it is defined elsewhere..
If they are independent but "need" to be global (because you cannot
think of a better solution), then they cannot have the same name.
If you do not reference them in main.c, then they should in any event be removed from there. It seems odd that you would define them here when they clearly relate to stepper motor control and should probably be encapsulated in stepper_motor.c.
Avoiding the use of globals in the fist place is a much better solution see https://www.embedded.com/a-pox-on-globals/

Related

How to static_assert in an expression out of function bodies in C

I am writing a macro PAGE_ALIGN in C as follows.
#include <stdio.h>
#define PAGE_ALIGN(x) ((x) & 0xfffff000U)
int main() {
printf("0x%08x\n", PAGE_ALIGN(0x12345678U));
}
Now I want to make sure that the user is passing in the correct type to PAGE_ALIGN. I use _Static_assert() to perform the assertion, and things work well.
#define PAGE_ALIGN(x) (({_Static_assert(sizeof(x) == 4); x;}) & 0xfffff000U)
However, some of my code does not use PAGE_ALIGN in functions. For example, when defining a global variable:
char a[PAGE_ALIGN(0x12345678U)];
Then I get the compile error
a.c:3:24: error: braced-group within expression allowed only inside a function
3 | #define PAGE_ALIGN(x) (({_Static_assert(sizeof(x) == 4); x;}) & 0xfffff000U)
| ^
a.c:5:8: note: in expansion of macro 'PAGE_ALIGN'
5 | char a[PAGE_ALIGN(0x12345678U)];
| ^~~~~~~~~~
Is there a way to define PAGE_ALIGN such that the macro works outside of a function?
Complete a.c:
#include <stdio.h>
#define PAGE_ALIGN(x) (({_Static_assert(sizeof(x) == 4); x;}) & 0xfffff000U)
char a[PAGE_ALIGN(0x12345678U)];
int main() {
printf("0x%08x\n", PAGE_ALIGN(0x12345678U));
}
Update: here is the motivation for this question.
I am writing an OS that deals with physical address and virtual address in 32-bit and 64-bit mode. Virtual addresses are 32 bits in 32-bit mode and 64 bits in 64-bit mode. So unsigned long is used for virtual addresses. Physical addresses are always 64 bits, so unsigned long long is used. I am writing a header file that distinguishes these different types
For example, page size macros are:
#define VA_PAGE_SIZE_4K 0x1000UL // VA for virtual address
#define PA_PAGE_SIZE_4K 0x1000ULL // PA for physical address
Then I define macros for aligning up:
#define VA_PAGE_ALIGN_UP_4K(x) (((x) + VA_PAGE_SIZE_4K - 1) & ~(VA_PAGE_SIZE_4K - 1))
#define PA_PAGE_ALIGN_UP_4K(x) (((x) + PA_PAGE_SIZE_4K - 1) & ~(PA_PAGE_SIZE_4K - 1))
Please imagine that there are other macros, such as VA_PAGE_ALIGN_UP_2M, VA_PAGE_ALIGN_UP_1G, ...
My OS has a fixed supported physical address size (say 4 GiB) and I want to need an identity map page table. So I can use the alignment macros to compute how many page table entries I need to support. Of course, there are page directories etc. due to multi-level paging.
// maximum physical memory, 4G
#define MAX_PHYS_MEM 0x100000000ULL
// number of page table entries
#define PAGE_TABLE_NELEMS (PA_PAGE_ALIGN_UP_4K(MAX_PHYS_MEM) / PA_PAGE_SIZE_4K)
// Define page table (global variable)
unsigned long page_table[PAGE_TABLE_NELEMS];
// number of page directory entries
#define PAGE_DIRECTORY_NELEMS (PA_PAGE_ALIGN_UP_2M(MAX_PHYS_MEM) / PA_PAGE_SIZE_2M)
// Define page directory (global variable)
unsigned long page_directory[PAGE_DIRECTORY_NELEMS];
// ...
However, in other code I want to make sure that PA_PAGE_ALIGN_UP_4K and VA_PAGE_ALIGN_UP_4K are not mixed. That is, PA_PAGE_ALIGN_UP_4K only used on unsigned long long and VA_PAGE_ALIGN_UP_4K only used on unsigned long. So I want to add a static assert in those macros. But adding a static assert will cause compile errors in page_table and page_directory above.
#Tavian Barnes's comment solves my problem. My updated program looks like:
#include <stdio.h>
#define PAGE_ALIGN(x) (sizeof(struct { _Static_assert(sizeof(x) == 4); int dummy; }) * 0 + ((x) & 0xfffff000U))
char a[PAGE_ALIGN(0x12345678U)];
int main() {
printf("0x%08x\n", PAGE_ALIGN(0x12345678U));
}

Is it bad practice to redefine register masks for PIC24 in order to improve readability?

I am relatively new to working with PIC chips, so this might be a novice-level question, but I am attempting to write a header file containing, among other things, the TRIS/ODC/INIT masks for all of the I/O ports.
On the PCB this chip is built into, any given component is likely to use pins from multiple ports, and there are probably a dozen or so individual components that warrant detailed commenting. For instance, interfacing with a particular SPI ADC module uses pins from ports A, D, and F.
To me, it would seem that the reader-friendly way to write this would be to organize the file by component such that, at a glance, the reader can tell what pins are being used, whether they are configured as inputs or outputs, and how they are initialized.
For instance, showing only the TRIS mask information, here is a snippet of code for a particular ADC module I am using to demonstrate what I am talking about:
#define PORTD_TRIS_MASK 0x00
#define PORTF_TRIS_MASK 0x00
// ...
// lots of hardware configuration stuff goes here
// ...
// ANALOG INPUT - THERMOCOUPLE 1
// Thermocouple ADC chip MAX31856 DNP communicates over SPI
// Accepts any type of thermocouple
// TC1_CS pulled high
// TC1_DRDY pulled high
#define TC1_MOSI LATAbits.LATA14
#define TC1_MISO PORTDbits.RD10
#define TC1_SCK LATDbits.LATD11
#define TC1_CS LATFbits.LATF6
#define TC1_DRDY PORTFbits.RF7
#define TC1_MISO_SHIFT 1<<10
#define TC1_DRDY_SHIFT 1<<7
#define PORTD_TRIS_MASK ( PORTD_TRIS_MASK | TC1_MISO_SHIFT )
#define PORTF_TRIS_MASK ( PORTF_TRIS_MASK | TC1_DRDY_SHIFT )
The above code does not throw any errors, but it does throw a warning:
HardwareProfile.h:1173:0: warning: "PORTD_TRIS_MASK" redefined
HardwareProfile.h:1029:0: note: this is the location of the previous definition
HardwareProfile.h:1174:0: warning: "PORTF_TRIS_MASK" redefined
HardwareProfile.h:1095:0: note: this is the location of the previous definition
The fact that the compiler is complaining about it suggests to me that this may not be encouraged behavior, but nothing about it seems intrinsically problematic to me. Am I missing something, or is this a reasonable way to organize code such that pin configuration details are kept near their definitions?
Alternatively, is there a more conventional way to accomplish what I want to accomplish as far as maintaining readability that is more widely used or acceptable?
Update:
Perhaps I was not clear enough in my original post. It is structured that way because there are a dozen or so such blocks of code in the header file. Supposing there are exactly 13 such blocks of code, any particular mask would be initially defined as 0x00 and redefined 13 times, the idea being that each redefinition adds the configuration information relevant to a particular block.
Update:
In response to a question about how these macros are used, they are simply used to configure all pins in a port at once. On this PIC24, each port has 16 pins, each of which has a TRIS (data direction control) register, ODC (open drain control) register, and LAT (latch) register that, if configured as an output, will need an initial value. Conventionally, writing to one bit at a time sixteen times is discouraged in favor of writing to the entire port once. For instance, consider a simplified case where there are four registers instead of sixteen. Instead of writing this:
// In source file
TRISABITS.TRISA0 = 1;
TRISABITS.TRISA1 = 1;
TRISABITS.TRISA2 = 0;
TRISABITS.TRISA3 = 0;
It is conventional (as I understand it) to write this:
// In header file
#define BIT_0_SHIFT ( 1<<0 )
#define BIT_1_SHIFT ( 1<<1 )
#define BIT_2_SHIFT ( 0<<2 )
#define BIT_3_SHIFT ( 0<<3 )
#define TRISA_MASK ( BIT_0_SHIFT | BIT_1_SHIFT | BIT_2_SHIFT | BIT_3_SHIFT )
// In source file
TRISA = TRISA_MASK;
Regarding a different question about readability, my argument in favor of this structure is that the way ports are organized on this chip is not physically meaningful. Pins on any particular port are not necessarily near each other or in order, and no individual device (e.g. external SPI module) is confined to a single port. Organizing the header file by port means that the reader needs to scroll through the entire header file to examine the configuration of a single device, while organizing the file by device allows an entire device's definitions and configurations to be clearly visible on a single screen.
The preprocessor does not work the same way as code works. For example, consider the following code:
int main(void)
{
int A = (B+C);
int B = (C+2);
int C = 3;
int x = A;
return x;
}
That doesn't work because B and C are used before being declared. The output from the compiler is:
cc -Wall demo.c -o demo
demo.c:3:14: error: use of undeclared identifier 'B'
int A = (B+C);
^
demo.c:3:16: error: use of undeclared identifier 'C'
int A = (B+C);
^
demo.c:4:14: error: use of undeclared identifier 'C'
int B = (C+2);
^
Now try the same thing using #defines for A, B, and C:
#define A (B+C)
#define B (C+2)
#define C 3
int main(void)
{
int x = A;
return x;
}
This time there are no warnings or errors, even though the #defines are out of order. When the preprocessor sees a #define it simply adds an entry to its dictionary. So after reading the three #defines the dictionary contains
Search Replacement
Text Text
--------------------
A (B+C)
B (C+2)
C 3
Note that the preprocessor has not evaluated the replacement text. It simply stores the text. When the preprocessor finds a search term in the code, then it uses the replacement text. So the line
int x = A;
becomes
int x = (B+C);
After performing the substitution, the preprocessor rescans the text to see if more substitutions are possible. After a second scan, we have:
int x = ((C+2)+3);
and the final result is:
int x = ((3 +2)+3);
Most compilers have an option to output the code after preprocessing is finished. With gcc or clang, use the -E option to see the preprocessor output.
OK, so now we should have enough background to actually address your question. Consider the following definitions:
#define PORTD_TRIS_MASK 0x00
#define PORTD_TRIS_MASK ( PORTD_TRIS_MASK | TC1_MISO_SHIFT )
#define PORTD_TRIS_MASK ( PORTD_TRIS_MASK | SB1_DATA_SHIFT )
We have 3 major problems here:
The substitution text is not being evaluated, so the bits are not being OR'd together.
Only one of those definitions (the last one) will be kept in the preprocessor dictionary. That's the reason for the warning. The preprocessor is telling you that it already has an entry for that search term, and it's going to discard the previous replacement text.
When PORTD_TRIS_MASK is found in the code, the preprocessor replaces it with ( PORTD_TRIS_MASK | SB1_DATA_SHIFT ). It then rescans, and finds PORTD_TRIS_MASK again. The result is infinite recursion. Fortunately, the preprocessor has protection against such things, and will stop. The compiler will generate an error later.
The solution is to create uniquely named definitions for each component:
#define TRIS_MASK_D1 TC1_MISO_SHIFT
#define TRIS_MASK_F1 TC1_DRDY_SHIFT
#define TRIS_MASK_D2 SB1_DATA_SHIFT
#define TRIS_MASK_F2 0
And then OR them all together:
#define PORTD_TRIS_MASK (TRIS_MASK_D1 | TRIS_MASK_D2 | ... | TRIS_MASK_D13)
#define PORTF_TRIS_MASK (TRIS_MASK_F1 | TRIS_MASK_F2 | ... | TRIS_MASK_F13)
Macros like PORTD_TRIS_MASK are defined by PIC based on the microcontroller used.
I would not recommend that you change or redefine these macros.
What you can do instead is to use your own macros for particular functionality. e.g.
#define TC1_MISO_SHIFT 1<<10
#define TC1_DRDY_SHIFT 1<<7
#define TC1_MISO_MASK ( PORTD_TRIS_MASK | TC1_MISO_SHIFT )
#define TCI_DRDY_MASK ( PORTF_TRIS_MASK | TC1_DRDY_SHIFT )

implicit declaration of function even though i have included the file?

my project is almost working but i get 1
Warning:
"implicit declaration of function 'init_phase_correct' [-Wimplicit-function-declaration]"
have have the function called in my main
int main(void)
{
volatile char start_flag=0;
uart0_Init ( MYUBRRF );
DDRB |=(1<<PB7);
sei(); //enable global interrupt
initAdc();
data = 'a';
ADCSRA |=(1<<ADIE);
init_phase_correct();
and init_phase_correct is included i the top in
#include "PWM.h"
that links to
/*
* IncFile1.h
*
* Created: 23-04-2015 11:30:38
* Author: Martin Egsdal
*/
#ifndef INCFILE1_H_
#define INCFILE1_H_
extern void init_fastPWM();
extern void init_phase_correct();
extern void init_ph_frPWM();
extern void init_phase_correct_alt();
#endif /* INCFILE1_H_ */
and in the C file it is:
void init_phase_correct(){
TCCR0A|=(1<<COM0A1)|(1<<WGM00); //Clear OC0A on Compare Match when up-counting. Set OC0A on Compare Match when down-counting
TCCR0B =(1<<CS01); //prescalling by 8
OCR0A =102; //40 duty cycle
TCNT0= 0;
DDRB |= (1<<DDB7);// configure OC0A pin for output
}
when i rightclick init_phase_correct() in my main i can see the 2 implentations - so why is it "Wimplicit-function-declaration"?
I see, that your header file, which contains declaration of init_phase_correct() is wrapped with include guard with some auto-generated name (INCFILE1_H_).
Also, you did not specify, whether init_phase_correct() is declared inside PWM.h or maybe another file, that is included by PWM.h.
Without more code, I cannot say for sure, but my clairvoyance skill tells me, that INCFILE1_H_ may be used as include guard in another file - either PWM.h itself or another, that is being included before file, that contains declaration of init_phase_correct().

Is there a way to get the value of __LINE__ on one line and use that value on other lines?

Essentially, I want to do this:
#include "foo.h"
#include "bar.h"
static const unsigned line_after_includes = __LINE__;
int main()
{
foo(line_after_includes);
bar(line_after_includes);
return 0;
}
Except like this:
#include "foo.h"
#include "bar.h"
#define LINE_AFTER_INCLUDES __LINE__
int main()
{
FOO(LINE_AFTER_INCLUDES);
BAR(LINE_AFTER_INCLUDES);
return 0;
}
Is it possible to make LINE_AFTER_INCLUDES expand to the value of __LINE__ on the line on which LINE_AFTER_INCLUDES was defined, so I can use it with other macros later? I would just use a variable like in the first code snippet, but I need the value as an integer literal, because I will be using it in a switch statement. The alternative is to do
#define LINE_AFTER_INCLUDES 3 // MAKE SURE THIS IS ON LINE IT'S DEFINED AS!!!
which is ugly and harder to maintain. I would settle for that, but I will be doing something a bit more complex than this example...
The best way to do this is given in #Bathsheba's answer here: https://stackoverflow.com/a/24551912/1366431
typedef char LINE_AFTER_INCLUDES[__LINE__];
You can then access the value of __LINE__ at that declaration by calling sizeof(LINE_AFTER_INCLUDES), because its value has been fixed into part of the newly-declared array type. sizeof is a C-level compile-time constant, which works for switch and related things (no division is necessary: the size of char is guaranteed to be 1, as it's the unit of measurement). The only disadvantage of this is that it's C-level rather than preprocessor-level, so it can't be used with #if or for token-pasting.
(original, which I spent ages typing:)
So the problem here is that macro definitions are lazy; i.e. that macro invocations aren't expanded until they're actually needed to be inserted into some kind of output. Because of this, __LINE__'s expansion is delayed until it's too late.
Luckily, there's a way to force eager evaluation in the preprocessor - the macro only needs to be demanded by some kind of output - not necessarily program body text. Remember that macros can also be expanded to form the arguments to preprocessor directives - and that preprocessor directives are then - having been controlled by the forced expansion - able to create further definitions. This handy observation is the basis of Boost's "evaluated slots" functionality, which uses it to provide things like eager evaluation and mutable preprocessor variable slots.
Unfortunately you can't use Boost slots with __LINE__, as it suffers from the same problem - but we can steal the idea to produce two rather inelegant solutions. They're each ugly in their own special ways.
Option 1:
Use a shell script to produce a large number (a few hundred?) of include-able files with the following naming scheme and contents:
// linedefs/_42_.h
#define LINE_AFTER_INCLUDES 42
...then use as follows:
#define GEN_LINE_INC(L) _GEN_LINE_S(_GEN_LINE_(L))
#define _GEN_LINE_(L) linedefs/_##L##_.h
#define _GEN_LINE_S(S) _GEN_LINE_S2(S)
#define _GEN_LINE_S2(S) #S
#include "foo.h"
#include "bar.h"
#include GEN_LINE_INC(__LINE__)
int main()
{
FOO(LINE_AFTER_INCLUDES);
BAR(LINE_AFTER_INCLUDES);
return 0;
}
In other words, use the #include directive to force expansion of a macro which converts __LINE__ into a filename; including that filename produces the right value for the constant. This is inelegant because it requires a load of extra files and an external tool to generate them, but it's very simple.
Option 2:
Insert a large and ugly block into your main file below the #include section:
#include "foo.h"
#include "bar.h"
// <- This line is the one we generate the number for
#define LINE_BIT_0 0
#define LINE_BIT_1 0
#define LINE_BIT_2 0
#define LINE_BIT_3 0
#define LINE_BIT_4 0
#define LINE_BIT_5 0
#if (__LINE__ - 7) & 1
# undef LINE_BIT_0
# define LINE_BIT_0 1
#endif
#if (__LINE__ - 11) >> 1 & 1
# undef LINE_BIT_1
# define LINE_BIT_1 (1 << 1)
#endif
#if (__LINE__ - 15) >> 2 & 1
# undef LINE_BIT_2
# define LINE_BIT_2 (1 << 2)
#endif
#if (__LINE__ - 19) >> 3 & 1
# undef LINE_BIT_3
# define LINE_BIT_3 (1 << 3)
#endif
#if (__LINE__ - 23) >> 4 & 1
# undef LINE_BIT_4
# define LINE_BIT_4 (1 << 4)
#endif
#if (__LINE__ - 27) >> 5 & 1
# undef LINE_BIT_5
# define LINE_BIT_5 (1 << 5)
#endif
#define LINE_AFTER_INCLUDES (LINE_BIT_0 | LINE_BIT_1 | LINE_BIT_2 | LINE_BIT_3 | LINE_BIT_4 | LINE_BIT_5)
int main() ...
This version uses the #if directive to force expansion of the __LINE__ macro and convert it into bitflags, which are then recombined at the end. This is highly inelegant because it relies on precomputing the distance between each #if and the top of the block, since __LINE__ evaluates to different values in the course of the block; and it can't be factored out and hidden in a separate file, or else __LINE__ wouldn't work. Still, it works, and it doesn't require an external tool.
(In the event you have a huge number of #include lines, extending it to more than 6 bits should be straightforward.)
On the other hand, this sounds like an X/Y problem to me. There has to be an alternative to __LINE__ that would work better for this. If you're counting the number of #included files, perhaps you could use something like a line incrementing Boost.Counter at the end of each one? That way, you also wouldn't be vulnerable to formatting changes (e.g. blank lines in the #include section).

Advanced Preprocesor Tokenization in C

I'm having problem building C macro for my PIC. It's the same for other C-based system's, so non-PIC C experts are also more than welcome.
Lets assume that I have defined my LED_1 pin :
#define LED_1 A1 //A1 as output for LED_1
So if I want to light a LED I would write:
PORTAbits.RA1 = 1;
And if I would like to do it using my LED_1 definition I have to add two more macros:
#define change_PORT_(var) PORTAbits.R##var
#define change_PORT(var) change_PORT_(var
And to use it:
change_PORT(LED_1) = 1;
And it works like a charm. But the problem is that in definitions above I have
PORT A bits.##var
So what if I want to change PORTB values? I would have to build separate macros for PORTs A and B. But it's not even close to be a robust solution.
And I came up with an idea which, I don't know why, doesnt work.
#define LED_1 A1
#define LED_2 B1
#define __A1 A //This would be defined for all PORTA's pins such as A2,A3,A4 etc
#define __B1 B
#define ___change_PORT(var,var2) PORT##var2 bits.R##var
#define __change_PORT(var,var2) ___change_PORT(var,var2)
#define _change_PORT(var) __change_PORT(var,__##var) // creating e.g. __A1
#define change_PORT(var) _change_PORT(var)
And when I try to run this:
change_PORT(LED_1);
The compiler changes __##var to ___A1 but it never changes __A1 to A so this MACRO doesn't work as it supposed to.
I spent a lot of time trying to fix it so I'd appreciate any help :)
EDIT::
I might have found a solution to my problem:
(LAT is just another register name, but it works same as PORT, so this name-change is irrelevant)
#define ___PORTchange(var,var2) PORT##var2##bits.R##var
#define __PORTchange(var,var2) ___PORTchange(var,var2)
#define CHANGE_TO_PORT_NAME(var) ___##var
#define _PORTchange(var) __PORTchange(var,CHANGE_TO_PORT_NAME(var))
#define PORTchange(var) _PORTchange(var)
but I get a compiler error:
100: PORTAbits.RA0 = 1;
^ (374) missing basic type; int assumed (warning)
^ (983) storage class redeclared
^ (984) type redeclared
^ (239) identifier "PORTAbits" redefined (from line 3900)
^ (314) ";" expected
So no it does substitute it correctly but I get a compiler warning telling me that I redefine PORTAbits which I cannot understand. I just wanted preprocessor to change PORTchange(var) to PORTxbits.Rvar where x is A or B. But instead it seems that I'm redeclaring something.
I don't get it.
If I preprocess (tried with several gcc versions and sun cc)
#define LED_1 A1
#define LED_2 B1
#define __A1 AX
#define __B1 BX
#define ___change_PORT(var,var2) PORT##var2##bits.R##var
#define __change_PORT(var,var2) ___change_PORT(var,var2)
#define _change_PORT(var) __change_PORT(var,__##var)
#define change_PORT(var) _change_PORT(var)
change_PORT(LED_1);
change_PORT(LED_2);
I get
PORTAXbits.RA1;
PORTBXbits.RB1;
which is apparently what you are wanting. A bug in your compiler?

Resources