I hope I’m putting this in the right place, please feel free to move it elsewhere if i’m mistaken.
Hello! First post in the forum.
I’m having problems with splitting my code in multiple files, all while following the standard C/C++ folder structure.
The error:
Processing bluepill_f103c8 (platform: ststm32; board: bluepill_f103c8; framework: libopencm3)
-----------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/ststm32/bluepill_f103c8.html
PLATFORM: ST STM32 (11.0.0) > BluePill F103C8
HARDWARE: STM32F103C8T6 72MHz, 20KB RAM, 64KB Flash
DEBUG: Current (stlink) External (blackmagic, cmsis-dap, jlink, stlink)
PACKAGES:
- framework-libopencm3 1.10000.200730 (1.0.0)
- toolchain-gccarmnoneeabi 1.70201.0 (7.2.1)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 0 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
Linking .pio/build/bluepill_f103c8/firmware.elf
.pio/build/bluepill_f103c8/src/main.o: In function `main':
main.c:(.text.startup.main+0x2): undefined reference to `clock_setup'
main.c:(.text.startup.main+0x6): undefined reference to `usart_setup'
main.c:(.text.startup.main+0xa): undefined reference to `i2c_setup'
main.c:(.text.startup.main+0xe): undefined reference to `gpio_setup'
collect2: error: ld returned 1 exit status
*** [.pio/build/bluepill_f103c8/firmware.elf] Error 1
============================== [FAILED] Took 0.84 seconds ==============================
The terminal process "pio 'run'" terminated with exit code: 1.
Project structure(standard libopencm3):
Here the files:
- main.c
#include <string.h>
#include "init.h"
void usart_send_str(uint32_t usart, char *str);
void usart_send_str(uint32_t usart, char *str) {
while(*str) {
usart_send_blocking(usart, *str);
str++;
}
}
int main(void) {
clock_setup();
usart_setup();
i2c_setup();
gpio_setup();
usart_send_str(USART1, "Program started!\r\n");
while(1) {
__asm__("nop");
}
return 0;
}
void usart1_isr(void) {
static uint8_t data = 'A';
/* Check if we were called because of RXNE. */
if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
((USART_SR(USART1) & USART_SR_RXNE) != 0)) {
/* Indicate that we got data. */
gpio_toggle(GPIOC, GPIO13);
/* Retrieve the data from the peripheral. */
data = usart_recv(USART1);
/* Enable transmit interrupt so it sends back the data. */
USART_CR1(USART1) |= USART_CR1_TXEIE;
}
/* Check if we were called because of TXE. */
if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) &&
((USART_SR(USART1) & USART_SR_TXE) != 0)) {
/* Indicate that we are sending out data. */
gpio_toggle(GPIOC, GPIO13);
/* Put data into the transmit register. */
usart_send(USART1, data);
/* Disable the TXE interrupt as we don't need it anymore. */
USART_CR1(USART1) &= ~USART_CR1_TXEIE;
}
}
- init.c
#include "init.h"
static void clock_setup(void) {
rcc_clock_setup_in_hse_8mhz_out_72mhz();
rcc_periph_clock_enable(RCC_GPIOA);
rcc_periph_clock_enable(RCC_GPIOC);
rcc_periph_clock_enable(RCC_GPIOB);
rcc_periph_clock_enable(RCC_USART1);
rcc_periph_clock_enable(RCC_I2C1);
}
static void usart_setup(void) {
nvic_enable_irq(NVIC_USART1_IRQ);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX);
usart_set_baudrate(USART1, 115200);
usart_set_databits(USART1, 8);
usart_set_stopbits(USART1, USART_STOPBITS_1);
usart_set_mode(USART1, USART_MODE_TX_RX);
usart_set_parity(USART1, USART_PARITY_NONE);
usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
usart_enable_rx_interrupt(USART1);
usart_enable(USART1);
}
static void i2c_setup(void) {
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO_I2C1_SCL | GPIO_I2C1_SDA);
i2c_peripheral_disable(I2C1);
i2c_set_clock_frequency(I2C1, I2C_CR2_FREQ_36MHZ);
i2c_set_fast_mode(I2C1);
i2c_set_ccr(I2C1, 0x1e);
i2c_set_trise(I2C1, 0x0b);
i2c_set_own_7bit_slave_address(I2C1, 0x32);
i2c_peripheral_enable(I2C1);
}
static void gpio_setup(void) {
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
}
- init.h
#ifndef INIT_H
#define INIT_H
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/i2c.h>
#include <libopencm3/cm3/nvic.h>
static void clock_setup(void);
static void usart_setup(void);
static void i2c_setup(void);
static void gpio_setup(void);
#endif
It appears to be a linker problem, although I’m unsure what I’m doing wrong, since the header files are in the include
folder and the source files are in src
.