0

I am programming a simple gpio program for a PIC24FJ1024GB610 microcontroller in C using MPLABX. I have created two methods that work similarly to Arduino pin direction and digital write methods. I have 2 .c files and 3 .h files:

  • main.c
  • gpio.c
  • main.h
  • gpio.h
  • board.h

When I build the code, I get an error stating that I have multiple definitions of an array called `_TRIS_REG'. This array is declared at the bottom of gpio.h. The error goes away when I move all the code from gpio.c into main.c and the code works perfectly. After I move the code back to gpio.c, I get the error again.

main.c

#include "main.h"

int main(int argc, char** argv) {
    
    pinDirection(LED3, OUTPUT);
    pinDirection(LED5, OUTPUT);
    
    digitalWrite(LED3, HIGH);
    digitalWrite(LED5, HIGH);
    
    while(1){
        
    }    
    return (0);
}

gpio.c

#include "gpio.h"

void pinDirection(uint16_t pin, bool direction){
    
    uint16_t port_index = pin / 16;
    uint16_t port_bit = pin % 16;
    uint16_t bit_mask = (1 << port_bit);
    
    if (direction){
        *TRIS_REG[port_index] |= bit_mask;
    } else {
        *TRIS_REG[port_index] &= ~(bit_mask);
    }
}

void digitalWrite(uint16_t pin, bool state){
    
    uint16_t port_index = pin / 16;
    uint16_t port_bit = pin % 16;
    uint16_t bit_mask = (1 << port_bit);
    
    if (state){
        *LAT_REG[port_index] |= bit_mask;
    } else {
        *LAT_REG[port_index] &= ~(bit_mask);
    }
}

main.h

#ifndef MAIN_H
#define MAIN_H

#include <xc.h>
#include <stdbool.h>
#include "board.h"
#include "gpio.h"

#endif

gpio.h

#ifndef GPIO_H
#define GPIO_H

#include <p24FJ1024GB610.h>
#include <xc.h>
#include <stdbool.h>

#define INPUT   true
#define OUTPUT  false

#define HIGH    true
#define LOW     false

/************
* Pin Index *
************/

/* PORT A */
#define PIN_PA00    0
#define PIN_PA01    1
#define PIN_PA02    2
#define PIN_PA03    3
#define PIN_PA04    4
#define PIN_PA05    5
#define PIN_PA06    6
#define PIN_PA07    7
#define PIN_PA08    8
#define PIN_PA09    9
#define PIN_PA10    10
#define PIN_PA11    11
#define PIN_PA12    12
#define PIN_PA13    13
#define PIN_PA14    14
#define PIN_PA15    15

/* PORT B */
#define PIN_PB00    16
#define PIN_PB01    17
#define PIN_PB02    18
#define PIN_PB03    19
#define PIN_PB04    20
#define PIN_PB05    21
#define PIN_PB06    22
#define PIN_PB07    23
#define PIN_PB08    24
#define PIN_PB09    25
#define PIN_PB10    26
#define PIN_PB11    27
#define PIN_PB12    28
#define PIN_PB13    29
#define PIN_PB14    30
#define PIN_PB15    31

/* PORT C */
#define PIN_PC00    32
#define PIN_PC01    33
#define PIN_PC02    34
#define PIN_PC03    35
#define PIN_PC04    36
#define PIN_PC05    37
#define PIN_PC06    38
#define PIN_PC07    39
#define PIN_PC08    40
#define PIN_PC09    41
#define PIN_PC10    42
#define PIN_PC11    43
#define PIN_PC12    44
#define PIN_PC13    45
#define PIN_PC14    46
#define PIN_PC15    47

/* PORT D */
#define PIN_PD00    48
#define PIN_PD01    49
#define PIN_PD02    50
#define PIN_PD03    51
#define PIN_PD04    52
#define PIN_PD05    53
#define PIN_PD06    54
#define PIN_PD07    55
#define PIN_PD08    56
#define PIN_PD09    57
#define PIN_PD10    58
#define PIN_PD11    59
#define PIN_PD12    60
#define PIN_PD13    61
#define PIN_PD14    62
#define PIN_PD15    63

/* PORT E */
#define PIN_PE00    64
#define PIN_PE01    65
#define PIN_PE02    66
#define PIN_PE03    67
#define PIN_PE04    68
#define PIN_PE05    69
#define PIN_PE06    70
#define PIN_PE07    71
#define PIN_PE08    72
#define PIN_PE09    73
#define PIN_PE10    74
#define PIN_PE11    75
#define PIN_PE12    76
#define PIN_PE13    77
#define PIN_PE14    78
#define PIN_PE15    79

/* PORT F */
#define PIN_PF00    80
#define PIN_PF01    81
#define PIN_PF02    82
#define PIN_PF03    83
#define PIN_PF04    84
#define PIN_PF05    85
#define PIN_PF06    86
#define PIN_PF07    87
#define PIN_PF08    88
#define PIN_PF09    89
#define PIN_PF10    90
#define PIN_PF11    91
#define PIN_PF12    92
#define PIN_PF13    93
#define PIN_PF14    94
#define PIN_PF15    95

/* PORT G */
#define PIN_PG00    96
#define PIN_PG01    97
#define PIN_PG02    98
#define PIN_PG03    99
#define PIN_PG04    100
#define PIN_PG05    101
#define PIN_PG06    102
#define PIN_PG07    103
#define PIN_PG08    104
#define PIN_PG09    105
#define PIN_PG10    106
#define PIN_PG11    107
#define PIN_PG12    108
#define PIN_PG13    109
#define PIN_PG14    110
#define PIN_PG15    111

volatile uint16_t *TRIS_REG[] = {
    (volatile uint16_t*)&TRISA,
    (volatile uint16_t*)&TRISB,
    (volatile uint16_t*)&TRISC,
    (volatile uint16_t*)&TRISD,
    (volatile uint16_t*)&TRISE,
    (volatile uint16_t*)&TRISF,
    (volatile uint16_t*)&TRISG
};

volatile uint16_t *PORT_REG[] = {
    (volatile uint16_t*)&PORTA,
    (volatile uint16_t*)&PORTB,
    (volatile uint16_t*)&PORTC,
    (volatile uint16_t*)&PORTD,
    (volatile uint16_t*)&PORTE,
    (volatile uint16_t*)&PORTF,
    (volatile uint16_t*)&PORTG
};

volatile uint16_t *LAT_REG[] = {
    (volatile uint16_t*)&LATA,
    (volatile uint16_t*)&LATB,
    (volatile uint16_t*)&LATC,
    (volatile uint16_t*)&LATD,
    (volatile uint16_t*)&LATE,
    (volatile uint16_t*)&LATF,
    (volatile uint16_t*)&LATG
};

void pinDirection(uint16_t pin, bool direction);
void digitalWrite(uint16_t pin, bool state);

#endif

board.h

#ifndef BOARD_H
#define BOARD_H

/*********************
* Device Pin Mapping *
*        for         *
*   Explorer 16/32   *
*   Development Kit  *
*********************/

/* LEDs */
#define LED3    PIN_PA00
#define LED4    PIN_PA01
#define LED5    PIN_PA02
#define LED6    PIN_PA03
#define LED7    PIN_PA04
#define LED8    PIN_PA05
#define LED9    PIN_PA06
#define LED10   PIN_PA07

#endif

ERROR

make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory 'C:/Users/bri_g/MPLABXProjects/GPIO_Test2.X'
make  -f nbproject/Makefile-default.mk dist/default/production/GPIO_Test2.X.production.hex
make[2]: Entering directory 'C:/Users/bri_g/MPLABXProjects/GPIO_Test2.X'
"C:\Program Files\Microchip\xc16\v1.61\bin\xc16-gcc.exe"   main.c  -o build/default/production/main.o  -c -mcpu=24FJ1024GB610  -MP -MMD -MF "build/default/production/main.o.d"      -mno-eds-warn  -g -omf=elf -DXPRJ_default=default  -legacy-libc    -O0 -msmart-io=1 -Wall -msfr-warn=off    -mdfp="C:/Program Files/Microchip/MPLABX/v5.45/packs/Microchip/PIC24F-GA-GB_DFP/1.4.141/xc16"
"C:\Program Files\Microchip\xc16\v1.61\bin\xc16-gcc.exe"   -o dist/default/production/GPIO_Test2.X.production.elf  build/default/production/main.o build/default/production/gpio.o      -mcpu=24FJ1024GB610        -omf=elf -DXPRJ_default=default  -legacy-libc    -Wl,--local-stack,,--defsym=__MPLAB_BUILD=1,,--script=p24FJ1024GB610.gld,--stack=16,--check-sections,--data-init,--pack-data,--handles,--isr,--no-gc-sections,--fill-upper=0,--stackguard=16,--no-force-link,--smart-io,-Map="dist/default/production/GPIO_Test2.X.production.map",--report-mem,--memorysummary,dist/default/production/memoryfile.xml  -mdfp="C:/Program Files/Microchip/MPLABX/v5.45/packs/Microchip/PIC24F-GA-GB_DFP/1.4.141/xc16" 
nbproject/Makefile-default.mk:146: recipe for target 'dist/default/production/GPIO_Test2.X.production.hex' failed
make[2]: Leaving directory 'C:/Users/bri_g/MPLABXProjects/GPIO_Test2.X'
nbproject/Makefile-default.mk:91: recipe for target '.build-conf' failed
make[1]: Leaving directory 'C:/Users/bri_g/MPLABXProjects/GPIO_Test2.X'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed
build/default/production/gpio.o(.data+0x0): In function `pinDirection':
C:\Users\bri_g\MPLABXProjects\GPIO_Test2.X/gpio.c:3: multiple definition of `_TRIS_REG'
build/default/production/main.o(.data+0x0):C:\Users\bri_g\MPLABXProjects\GPIO_Test2.X/main.c:10: first defined here
build/default/production/gpio.o(.data+0xe): In function `pinDirection':
C:\Users\bri_g\MPLABXProjects\GPIO_Test2.X/gpio.c:6: multiple definition of `_PORT_REG'
build/default/production/main.o(.data+0xe):C:\Users\bri_g\MPLABXProjects\GPIO_Test2.X/main.c:13: first defined here
build/default/production/gpio.o(.data+0x1c): In function `pinDirection':
C:\Users\bri_g\MPLABXProjects\GPIO_Test2.X/gpio.c:9: multiple definition of `_LAT_REG'
build/default/production/main.o(.data+0x1c):C:\Users\bri_g\MPLABXProjects\GPIO_Test2.X/main.c:16: first defined here
c:\program files\microchip\xc16\v1.61\bin\bin\..\bin/elf-ld.exe: Link terminated due to previous error(s).

Info: Loading file: C:/Program Files/Microchip/MPLABX/v5.45/packs/Microchip/PIC24F-GA-GB_DFP/1.4.141/xc16/bin/../support/PIC24F/gld\\p24FJ1024GB610.gld
make[2]: *** [dist/default/production/GPIO_Test2.X.production.hex] Error 255
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2

BUILD FAILED (exit value 2, total time: 760ms)

I'm sorry that there aren't any comments in the code, I just started writing it and couldn't figure this out. Any help would be greatly appreciated.

  • 2
    `This array is declared at the bottom of gpio.h` No, it is *defined*, not just *declared*. Because of that, each `.c` file that includes the header will end up with the same array defined in it, which causes the multiple definitions error. The solution is to *declare* the array in the header, then *define* it in just one of the `.c` files. See [Multiple definition of … linker error](https://stackoverflow.com/questions/17764661/multiple-definition-of-linker-error). – dxiv Jan 08 '21 at 21:38
  • 1
    `volatile uint16_t *LAT_REG[]` - these are not static. You defined `LAT_REG` in `gpio.h`, so it is going to be defined in each file that `#include`s `gpio.h`. Either move the definition into `C` file and add `extern` declaration into `gpio.h` _or_ add `static`. – KamilCuk Jan 08 '21 at 22:25

0 Answers0