Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
I have an 8-bit microcontroller with 100 pins. Each pin belongs to a port with a unique address and each pin has a number from 0 to 7. I want to create a scheme where in the code each pin is a stru...
#5: Post edited
Extern keyword in C and proper way to use extern variables in embedded systems
I have an 8-bit microcontroller with 100 pins. Each pin belongs to a port with a unique address and each pin has a number from 0 to 7. I want to create a scheme where in the code each pin is a struct that carries the pin's port address and number with it. I have defined a `pin_t` struct in `gpio.h`.
```
/*gpio.h */
typedef enum {INPUT = 0, INPUT_PULLUP = 1, OUTPUT = 2} gpio_mode_t;
typedef enum {LOW = 0, HIGH = 1} gpio_value_t;
typedef struct
{
volatile uint8_t *const port_addr; //const pointer that points to volatile register
const uint8_t pin_number;
} pin_t;
void pin_mode(const pin_t* pin, gpio_mode_t mode);
void digital_write(const pin_t* pin, gpio_value_t value);
```
Then, I have `pins.c` in which all the pin definitions are made. The port address and pin number should not be changed anywhere else in the program.
```
/* pins.c */
#include "gpio.h"
pin_t D1 = {.port_addr = &PORTG, .pin_number = 5};
pin_t D2 = {.port_addr = &PORTE, .pin_number = 0};
/* more definitions below ...*/
```
Then I have `pins.h` that declares each pin `extern`.
```
/*pins.h */
extern pin_t D1;
extern pin_t D2;
/* more below ...*/
```
Such that I in `main.c` can do things like this
```
/* main.c */
#include "pins.h"
int main(void)
{
pin_mode(&D1, OUTPUT);
for(;;) {}
}
```
**Question 1**: As far as I understand it, declaring variables as `extern` in `pins.h` makes them visible to source files that include `pins.h`, and I need not define them again. But to be honest, I'm not sure why I need `extern` in the first place. I get a compiler error if I remove it, saying there are multiple definitions of the pins in `main.o`. And with the same logic, shouldn't the function prototypes in `gpio.h` also be `extern` for my source files to see them?
**Question 2**: Is this the appropriate way to share variables across multiple files for an embedded system?
#4: Post edited
- I have an 8-bit microcontroller with 100 pins. Each pin belongs to a port with a unique address and each pin has a number from 0 to 7. I want to create a scheme where in the code each pin is a struct that carries the pin's port address and number with it. I have defined a `pin_t` struct in `gpio.h`.
- ```
- /*gpio.h */
- typedef enum {INPUT = 0, INPUT_PULLUP = 1, OUTPUT = 2} gpio_mode_t;
- typedef enum {LOW = 0, HIGH = 1} gpio_value_t;
- typedef struct
- {
- volatile uint8_t *const port_addr; //const pointer that points to volatile register
- const uint8_t pin_number;
- } pin_t;
- void pin_mode(const pin_t* pin, gpio_mode_t mode);
- void digital_write(const pin_t* pin, gpio_value_t value);
- ```
- Then, I have `pins.c` in which all the pin definitions are made. The port address and pin number should not be changed anywhere else in the program.
- ```
- /* pins.c */
- #include "gpio.h"
- pin_t D1 = {.port_addr = &PORTG, .pin_number = 5};
- pin_t D2 = {.port_addr = &PORTE, .pin_number = 0};
- /* more definitions below ...*/
- ```
- Then I have `pins.h` that declares each pin `extern`.
- ```
- /*pins.h */
- extern pin_t D1;
- extern pin_t D2;
- /* more below ...*/
- ```
- Such that I in `main.c` can do things like this
- ```
- /* main.c */
- #include "pins.h"
- int main(void)
- {
pin_mode(D1, OUTPUT);- for(;;) {}
- }
- ```
- **Question 1**: As far as I understand it, declaring variables as `extern` in `pins.h` makes them visible to source files that include `pins.h`, and I need not define them again. But to be honest, I'm not sure why I need `extern` in the first place. I get a compiler error if I remove it, saying there are multiple definitions of the pins in `main.o`. And with the same logic, shouldn't the function prototypes in `gpio.h` also be `extern` for my source files to see them?
- **Question 2**: Is this the appropriate way to share variables across multiple files for an embedded system?
- I have an 8-bit microcontroller with 100 pins. Each pin belongs to a port with a unique address and each pin has a number from 0 to 7. I want to create a scheme where in the code each pin is a struct that carries the pin's port address and number with it. I have defined a `pin_t` struct in `gpio.h`.
- ```
- /*gpio.h */
- typedef enum {INPUT = 0, INPUT_PULLUP = 1, OUTPUT = 2} gpio_mode_t;
- typedef enum {LOW = 0, HIGH = 1} gpio_value_t;
- typedef struct
- {
- volatile uint8_t *const port_addr; //const pointer that points to volatile register
- const uint8_t pin_number;
- } pin_t;
- void pin_mode(const pin_t* pin, gpio_mode_t mode);
- void digital_write(const pin_t* pin, gpio_value_t value);
- ```
- Then, I have `pins.c` in which all the pin definitions are made. The port address and pin number should not be changed anywhere else in the program.
- ```
- /* pins.c */
- #include "gpio.h"
- pin_t D1 = {.port_addr = &PORTG, .pin_number = 5};
- pin_t D2 = {.port_addr = &PORTE, .pin_number = 0};
- /* more definitions below ...*/
- ```
- Then I have `pins.h` that declares each pin `extern`.
- ```
- /*pins.h */
- extern pin_t D1;
- extern pin_t D2;
- /* more below ...*/
- ```
- Such that I in `main.c` can do things like this
- ```
- /* main.c */
- #include "pins.h"
- int main(void)
- {
- pin_mode(&D1, OUTPUT);
- for(;;) {}
- }
- ```
- **Question 1**: As far as I understand it, declaring variables as `extern` in `pins.h` makes them visible to source files that include `pins.h`, and I need not define them again. But to be honest, I'm not sure why I need `extern` in the first place. I get a compiler error if I remove it, saying there are multiple definitions of the pins in `main.o`. And with the same logic, shouldn't the function prototypes in `gpio.h` also be `extern` for my source files to see them?
- **Question 2**: Is this the appropriate way to share variables across multiple files for an embedded system?
#3: Post edited
- I have an 8-bit microcontroller with 100 pins. Each pin belongs to a port with a unique address and each pin has a number from 0 to 7. I want to create a scheme where in the code each pin is a struct that carries the pin's port address and number with it. I have defined a `pin_t` struct in `gpio.h`.
- ```
- /*gpio.h */
- typedef enum {INPUT = 0, INPUT_PULLUP = 1, OUTPUT = 2} gpio_mode_t;
- typedef enum {LOW = 0, HIGH = 1} gpio_value_t;
- typedef struct
- {
- volatile uint8_t *const port_addr; //const pointer that points to volatile register
- const uint8_t pin_number;
- } pin_t;
- void pin_mode(const pin_t* pin, gpio_mode_t mode);
- void digital_write(const pin_t* pin, gpio_value_t value);
- ```
- Then, I have `pins.c` in which all the pin definitions are made. The port address and pin number should not be changed anywhere else in the program.
- ```
- /* pins.c */
- #include "gpio.h"
- pin_t D1 = {.port_addr = &PORTG, .pin_number = 5};
- pin_t D2 = {.port_addr = &PORTE, .pin_number = 0};
- /* more definitions below ...*/
- ```
- Then I have `pins.h` that declares each pin `extern`.
- ```
- /*pins.h */
- extern pin_t D1;
- extern pin_t D2;
- /* more below ...*/
- ```
- Such that I in `main.c` can do things like this
- ```
- /* main.c */
- #include "pins.h"
- int main(void)
- {
- pin_mode(D1, OUTPUT);
- for(;;) {}
- }
- ```
**Question 1**: As far as I understand it, declaring variables as `extern` in `pins.h` makes them visible to source files that include `pins.h`, and I need not define them again. But to be honest, I'm not sure why I need `extern` in the first place. I get a compiler error if I remove it, saying there are multiple definitions. And with the same logic, shouldn't the function prototypes in `gpio.h` also be `extern` for my source files to see them?- **Question 2**: Is this the appropriate way to share variables across multiple files for an embedded system?
- I have an 8-bit microcontroller with 100 pins. Each pin belongs to a port with a unique address and each pin has a number from 0 to 7. I want to create a scheme where in the code each pin is a struct that carries the pin's port address and number with it. I have defined a `pin_t` struct in `gpio.h`.
- ```
- /*gpio.h */
- typedef enum {INPUT = 0, INPUT_PULLUP = 1, OUTPUT = 2} gpio_mode_t;
- typedef enum {LOW = 0, HIGH = 1} gpio_value_t;
- typedef struct
- {
- volatile uint8_t *const port_addr; //const pointer that points to volatile register
- const uint8_t pin_number;
- } pin_t;
- void pin_mode(const pin_t* pin, gpio_mode_t mode);
- void digital_write(const pin_t* pin, gpio_value_t value);
- ```
- Then, I have `pins.c` in which all the pin definitions are made. The port address and pin number should not be changed anywhere else in the program.
- ```
- /* pins.c */
- #include "gpio.h"
- pin_t D1 = {.port_addr = &PORTG, .pin_number = 5};
- pin_t D2 = {.port_addr = &PORTE, .pin_number = 0};
- /* more definitions below ...*/
- ```
- Then I have `pins.h` that declares each pin `extern`.
- ```
- /*pins.h */
- extern pin_t D1;
- extern pin_t D2;
- /* more below ...*/
- ```
- Such that I in `main.c` can do things like this
- ```
- /* main.c */
- #include "pins.h"
- int main(void)
- {
- pin_mode(D1, OUTPUT);
- for(;;) {}
- }
- ```
- **Question 1**: As far as I understand it, declaring variables as `extern` in `pins.h` makes them visible to source files that include `pins.h`, and I need not define them again. But to be honest, I'm not sure why I need `extern` in the first place. I get a compiler error if I remove it, saying there are multiple definitions of the pins in `main.o`. And with the same logic, shouldn't the function prototypes in `gpio.h` also be `extern` for my source files to see them?
- **Question 2**: Is this the appropriate way to share variables across multiple files for an embedded system?
#2: Post edited
I have an 8-bit microcontroller with 100 pins. Each pin belongs to a port with a unique address and each pin has a number from 0 to 7. I want to create a scheme where in the code each pin is a struct that carries the pin's port address and number. I have defined a `pin_t` struct in `gpio.h`.- ```
- /*gpio.h */
- typedef enum {INPUT = 0, INPUT_PULLUP = 1, OUTPUT = 2} gpio_mode_t;
- typedef enum {LOW = 0, HIGH = 1} gpio_value_t;
- typedef struct
- {
- volatile uint8_t *const port_addr; //const pointer that points to volatile register
- const uint8_t pin_number;
- } pin_t;
- void pin_mode(const pin_t* pin, gpio_mode_t mode);
- void digital_write(const pin_t* pin, gpio_value_t value);
- ```
- Then, I have `pins.c` in which all the pin definitions are made. The port address and pin number should not be changed anywhere else in the program.
- ```
- /* pins.c */
- #include "gpio.h"
- pin_t D1 = {.port_addr = &PORTG, .pin_number = 5};
- pin_t D2 = {.port_addr = &PORTE, .pin_number = 0};
- /* more definitions below ...*/
- ```
- Then I have `pins.h` that declares each pin `extern`.
- ```
- /*pins.h */
- extern pin_t D1;
- extern pin_t D2;
- /* more below ...*/
- ```
- Such that I in `main.c` can do things like this
- ```
- /* main.c */
- #include "pins.h"
- int main(void)
- {
- pin_mode(D1, OUTPUT);
- for(;;) {}
- }
- ```
- **Question 1**: As far as I understand it, declaring variables as `extern` in `pins.h` makes them visible to source files that include `pins.h`, and I need not define them again. But to be honest, I'm not sure why I need `extern` in the first place. I get a compiler error if I remove it, saying there are multiple definitions. And with the same logic, shouldn't the function prototypes in `gpio.h` also be `extern` for my source files to see them?
- **Question 2**: Is this the appropriate way to share variables across multiple files for an embedded system?
- I have an 8-bit microcontroller with 100 pins. Each pin belongs to a port with a unique address and each pin has a number from 0 to 7. I want to create a scheme where in the code each pin is a struct that carries the pin's port address and number with it. I have defined a `pin_t` struct in `gpio.h`.
- ```
- /*gpio.h */
- typedef enum {INPUT = 0, INPUT_PULLUP = 1, OUTPUT = 2} gpio_mode_t;
- typedef enum {LOW = 0, HIGH = 1} gpio_value_t;
- typedef struct
- {
- volatile uint8_t *const port_addr; //const pointer that points to volatile register
- const uint8_t pin_number;
- } pin_t;
- void pin_mode(const pin_t* pin, gpio_mode_t mode);
- void digital_write(const pin_t* pin, gpio_value_t value);
- ```
- Then, I have `pins.c` in which all the pin definitions are made. The port address and pin number should not be changed anywhere else in the program.
- ```
- /* pins.c */
- #include "gpio.h"
- pin_t D1 = {.port_addr = &PORTG, .pin_number = 5};
- pin_t D2 = {.port_addr = &PORTE, .pin_number = 0};
- /* more definitions below ...*/
- ```
- Then I have `pins.h` that declares each pin `extern`.
- ```
- /*pins.h */
- extern pin_t D1;
- extern pin_t D2;
- /* more below ...*/
- ```
- Such that I in `main.c` can do things like this
- ```
- /* main.c */
- #include "pins.h"
- int main(void)
- {
- pin_mode(D1, OUTPUT);
- for(;;) {}
- }
- ```
- **Question 1**: As far as I understand it, declaring variables as `extern` in `pins.h` makes them visible to source files that include `pins.h`, and I need not define them again. But to be honest, I'm not sure why I need `extern` in the first place. I get a compiler error if I remove it, saying there are multiple definitions. And with the same logic, shouldn't the function prototypes in `gpio.h` also be `extern` for my source files to see them?
- **Question 2**: Is this the appropriate way to share variables across multiple files for an embedded system?
#1: Initial revision
Extern keyword in C and proper way to use extern variables in embedded systems
I have an 8-bit microcontroller with 100 pins. Each pin belongs to a port with a unique address and each pin has a number from 0 to 7. I want to create a scheme where in the code each pin is a struct that carries the pin's port address and number. I have defined a `pin_t` struct in `gpio.h`.
```
/*gpio.h */
typedef enum {INPUT = 0, INPUT_PULLUP = 1, OUTPUT = 2} gpio_mode_t;
typedef enum {LOW = 0, HIGH = 1} gpio_value_t;
typedef struct
{
volatile uint8_t *const port_addr; //const pointer that points to volatile register
const uint8_t pin_number;
} pin_t;
void pin_mode(const pin_t* pin, gpio_mode_t mode);
void digital_write(const pin_t* pin, gpio_value_t value);
```
Then, I have `pins.c` in which all the pin definitions are made. The port address and pin number should not be changed anywhere else in the program.
```
/* pins.c */
#include "gpio.h"
pin_t D1 = {.port_addr = &PORTG, .pin_number = 5};
pin_t D2 = {.port_addr = &PORTE, .pin_number = 0};
/* more definitions below ...*/
```
Then I have `pins.h` that declares each pin `extern`.
```
/*pins.h */
extern pin_t D1;
extern pin_t D2;
/* more below ...*/
```
Such that I in `main.c` can do things like this
```
/* main.c */
#include "pins.h"
int main(void)
{
pin_mode(D1, OUTPUT);
for(;;) {}
}
```
**Question 1**: As far as I understand it, declaring variables as `extern` in `pins.h` makes them visible to source files that include `pins.h`, and I need not define them again. But to be honest, I'm not sure why I need `extern` in the first place. I get a compiler error if I remove it, saying there are multiple definitions. And with the same logic, shouldn't the function prototypes in `gpio.h` also be `extern` for my source files to see them?
**Question 2**: Is this the appropriate way to share variables across multiple files for an embedded system?
