From 7f4f50f9b7cec0419455946ed7b69d5f3ba67182 Mon Sep 17 00:00:00 2001 From: Ajit Ananthadevan Date: Mon, 25 Aug 2025 00:54:33 +1000 Subject: [PATCH] impl printf --- myapps/printf-test/Makefile | 161 ++++++++++++++++++++++++++++++ myapps/printf-test/hal.mk | 13 +++ myapps/printf-test/src/main.c | 65 ++++++++++++ vendor/my_printf/inc/my_printf.h | 25 +++++ vendor/my_printf/my_printf.c | 165 +++++++++++++++++++++++++++++++ 5 files changed, 429 insertions(+) create mode 100644 myapps/printf-test/Makefile create mode 100644 myapps/printf-test/hal.mk create mode 100644 myapps/printf-test/src/main.c create mode 100644 vendor/my_printf/inc/my_printf.h create mode 100644 vendor/my_printf/my_printf.c diff --git a/myapps/printf-test/Makefile b/myapps/printf-test/Makefile new file mode 100644 index 0000000..53a4d84 --- /dev/null +++ b/myapps/printf-test/Makefile @@ -0,0 +1,161 @@ +###################################### +# target +###################################### +TARGET = stm32g0_blinky +PART = STM32G030xx +PYOCD_TARGET = stm32g030f6px + + +###################################### +# building variables +###################################### +# debug build? +DEBUG = 1 +# optimization for size +OPT = -Os + + +####################################### +# paths +####################################### +# Build path +BUILD_DIR = build +VND_DIR = ../../vendor + +###################################### +# source +###################################### +# C sources +include hal.mk +C_SOURCES += \ +$(VND_DIR)/STM32CubeG0/Drivers/CMSIS/Device/ST/STM32G0xx/Source/Templates/system_stm32g0xx.c \ +src/main.c + +C_SOURCES += \ +$(VND_DIR)/STM32CubeG0/Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_usart.c \ +$(VND_DIR)/my_printf/my_printf.c + +C_INCLUDES += -I$(VND_DIR)/my_printf/inc + + +# ASM sources +ASM_SOURCES = \ +$(VND_DIR)/STM32CubeG0/Drivers/CMSIS/Device/ST/STM32G0xx/Source/Templates/gcc/startup_stm32g030xx.s + +####################################### +# binaries +####################################### +PREFIX = arm-none-eabi- + +CC = $(PREFIX)gcc +CP = $(PREFIX)objcopy +#SZ = $(PREFIX)size + +BIN = $(CP) -O binary -S + +####################################### +# CFLAGS +####################################### + +ifeq ($(DEBUG), 1) +DEBUG_FLAGS = -gdwarf-3 +endif + +# cpu +CPU = \ + -mcpu=cortex-m0plus + +DEFINES = -D$(PART) + +# fpu +FPU = + +# float-abi +FLOAT-ABI = + +# mcu +MCU = $(CPU) $(FPU) $(FLOAT-ABI) + +# C includes +C_INCLUDES += \ + -Isrc/inc \ + -I$(VND_DIR)/STM32CubeG0/Drivers/CMSIS/Core/Include \ + -I$(VND_DIR)/STM32CubeG0/Drivers/CMSIS/Device/ST/STM32G0xx/Include + +# compile gcc flags +ADDN_CFLAGS = \ + -Wall \ + -fdata-sections \ + -ffunction-sections + +CFLAGS = $(MCU) $(ADDN_CFLAGS) $(C_INCLUDES) $(DEBUG_FLAGS) $(OPT) $(DEFINES) + + +# Generate dependency information +#CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" + + +ASFLAGS = $(MCU) $(DEBUG_FLAGS) $(OPT) -Wa,--warn + +####################################### +# LDFLAGS +####################################### +# link script +LDSCRIPT = $(VND_DIR)/Ld/STM32G030F6MX_RTOS_FLASH.ld + +LIBDIR = +LDFLAGS = \ + $(MCU) \ + -T $(LDSCRIPT) \ + --specs=nano.specs \ + -specs=nosys.specs -lc -lm \ + -Wl,-Map=$(BUILD_DIR)/$(TARGET).map \ + -Wl,--gc-sections \ + -Wl,--print-memory-usage \ + -Wl,--no-warn-rwx-segments + +# default action: build all +all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).bin + + +####################################### +# build the application +####################################### +# list of objects +OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) +vpath %.c $(sort $(dir $(C_SOURCES))) + +# list of ASM program objects +OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o))) +vpath %.s $(sort $(dir $(ASM_SOURCES))) + +$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) + $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ + +$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR) + $(CC) -c $(ASFLAGS) $< -o $@ + +#$(LUAOBJECTS) $(OBJECTS) +$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile + $(CC) $(OBJECTS) $(LDFLAGS) -o $@ + +$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR) + $(BIN) $< $@ + +$(BUILD_DIR): + mkdir $@ + +####################################### +# Program +####################################### + +flash: $(BUILD_DIR)/$(TARGET).bin + pyocd load --target $(PYOCD_TARGET) $(BUILD_DIR)/$(TARGET).bin + +####################################### +# clean up +####################################### +clean: + -rm -fR $(BUILD_DIR) + +# *** EOF *** diff --git a/myapps/printf-test/hal.mk b/myapps/printf-test/hal.mk new file mode 100644 index 0000000..1e754e6 --- /dev/null +++ b/myapps/printf-test/hal.mk @@ -0,0 +1,13 @@ +C_INCLUDES += \ + -I$(VND_DIR)/STM32CubeG0/Drivers/STM32G0xx_HAL_Driver/Inc + +# "stm32g0xx_ll_bus.h" "stm32g0xx_ll_system.h" "stm32g0xx_ll_cortex.h" : missing +C_SOURCES += \ + $(VND_DIR)/STM32CubeG0/Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_rcc.c \ + $(VND_DIR)/STM32CubeG0/Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_crs.c \ + $(VND_DIR)/STM32CubeG0/Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_exti.c \ + $(VND_DIR)/STM32CubeG0/Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_utils.c \ + $(VND_DIR)/STM32CubeG0/Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_pwr.c \ + $(VND_DIR)/STM32CubeG0/Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_dma.c \ + $(VND_DIR)/STM32CubeG0/Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_gpio.c + diff --git a/myapps/printf-test/src/main.c b/myapps/printf-test/src/main.c new file mode 100644 index 0000000..4e1d624 --- /dev/null +++ b/myapps/printf-test/src/main.c @@ -0,0 +1,65 @@ + + +#define LED_Pin LL_GPIO_PIN_4 +#define LED_GPIO_Port GPIOA + +#include "stm32g0xx_ll_rcc.h" +#include "stm32g0xx_ll_bus.h" +#include "stm32g0xx_ll_crs.h" +#include "stm32g0xx_ll_system.h" +#include "stm32g0xx_ll_exti.h" +#include "stm32g0xx_ll_cortex.h" +#include "stm32g0xx_ll_utils.h" +#include "stm32g0xx_ll_pwr.h" +#include "stm32g0xx_ll_dma.h" +#include "my_printf.h" + +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); + while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2); + + /* HSI configuration and activation */ + LL_RCC_HSI_Enable(); + while(LL_RCC_HSI_IsReady() != 1); + + /* Main PLL configuration and activation */ + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_1, 8, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_Enable(); + LL_RCC_PLL_EnableDomain_SYS(); + while(LL_RCC_PLL_IsReady() != 1); + + /* Set AHB prescaler*/ + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + + /* Sysclk activation on the main PLL */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL); + + /* Set APB1 prescaler*/ + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_Init1msTick(64000000); + /* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function) */ + LL_SetSystemCoreClock(64000000); +} + + +int main(void) +{ + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG); + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); + /** Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral */ + //LL_SYSCFG_DisableDBATT(LL_SYSCFG_UCPD1_STROBE | LL_SYSCFG_UCPD2_STROBE); + + SystemClock_Config(); + my_printf_config(115200); + + + while(1) + { + printf("Hello World\r\n"); + LL_mDelay(250); + } +} + diff --git a/vendor/my_printf/inc/my_printf.h b/vendor/my_printf/inc/my_printf.h new file mode 100644 index 0000000..c4119ea --- /dev/null +++ b/vendor/my_printf/inc/my_printf.h @@ -0,0 +1,25 @@ +#ifndef MY_PRINTF_H +#define MY_PRINTF_H + +#include +#include "stm32g0xx_ll_rcc.h" +#include "stm32g0xx_ll_bus.h" +#include "stm32g0xx_ll_crs.h" +#include "stm32g0xx_ll_system.h" +#include "stm32g0xx_ll_exti.h" +#include "stm32g0xx_ll_cortex.h" +#include "stm32g0xx_ll_utils.h" +#include "stm32g0xx_ll_pwr.h" +#include "stm32g0xx_ll_dma.h" +#include "stm32g0xx_ll_gpio.h" +#include "stm32g0xx_ll_usart.h" + + + +void my_printf_config(uint32_t baudRate); + +void my_uart_txchar(char ch); +void my_uart_txstring(char *str); + + +#endif /* MY_PRINTF_H */ diff --git a/vendor/my_printf/my_printf.c b/vendor/my_printf/my_printf.c new file mode 100644 index 0000000..2021ba5 --- /dev/null +++ b/vendor/my_printf/my_printf.c @@ -0,0 +1,165 @@ +#include +#include +#include +#include "my_printf.h" + + +void my_uart_txchar(char ch) +{ + LL_USART_TransmitData8(USART2, ch); + while (!LL_USART_IsActiveFlag_TC(USART2)); + LL_USART_ClearFlag_TC(USART2); +} + +void my_uart_txstring(char *str) +{ + while (*str) my_uart_txchar(*str++); +} + + +void my_printf_config(uint32_t baudRate) +{ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2); + + /* USART Init */ + LL_USART_SetBaudRate(USART2, SystemCoreClock, LL_USART_PRESCALER_DIV1, LL_USART_OVERSAMPLING_16, baudRate); + LL_USART_SetDataWidth(USART2, LL_USART_DATAWIDTH_8B); + LL_USART_SetStopBitsLength(USART2, LL_USART_STOPBITS_1); + LL_USART_SetParity(USART2, LL_USART_PARITY_NONE); + LL_USART_SetHWFlowCtrl(USART2, LL_USART_HWCONTROL_NONE); + LL_USART_SetTransferDirection(USART2, LL_USART_DIRECTION_TX_RX); + LL_USART_Enable(USART2); + LL_USART_ClearFlag_TC(USART2); + + /**USART GPIO Configuration + PA2 ------> USART2_TX + PA3 ------> USART2_RX + */ + LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); + + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_2, LL_GPIO_MODE_ALTERNATE); + LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_2, LL_GPIO_SPEED_FREQ_VERY_HIGH); + LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_2, LL_GPIO_PULL_UP); + LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_2, LL_GPIO_AF_1); + + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_3, LL_GPIO_MODE_ALTERNATE); + LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_3, LL_GPIO_SPEED_FREQ_VERY_HIGH); + LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_3, LL_GPIO_PULL_UP); + LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_3, LL_GPIO_AF_1); + +#if defined (__GNUC__) && !defined (__clang__) + // To avoid io buffer + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stdin, NULL, _IONBF, 0); +#endif +} + +#if defined (__GNUC__) && !defined (__clang__) + #define GETCHAR_PROTOTYPE __attribute__((weak)) int __io_getchar (void) + #define PUTCHAR_PROTOTYPE __attribute__((weak)) int __io_putchar(int ch) +#else + #define GETCHAR_PROTOTYPE int fgetc(FILE * f) + #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) +#endif + +/** + * @brief retargets the c library printf function to the usart. + * @param none + * @retval none + */ +PUTCHAR_PROTOTYPE +{ + /* Send a byte to USART */ + LL_USART_TransmitData8(USART2, ch); + while (!LL_USART_IsActiveFlag_TC(USART2)); + LL_USART_ClearFlag_TC(USART2); + + return (ch); +} + +GETCHAR_PROTOTYPE +{ + int ch; + while (!LL_USART_IsActiveFlag_RXNE(USART2)); + ch = LL_USART_ReceiveData8(USART2); + return (ch); +} + +#if defined (__GNUC__) && !defined (__clang__) +__attribute__((weak)) int _write(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + __io_putchar(*ptr++); + } + return len; +} +#endif + +__attribute__((weak)) int _read(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + *ptr++ = __io_getchar(); + } + return len; +} + +__attribute__((weak)) int _isatty(int fd) +{ + if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) + return 1; + + errno = EBADF; + return 0; +} + +__attribute__((weak)) int _close(int fd) +{ + if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) + return 0; + + errno = EBADF; + return -1; +} + +__attribute__((weak)) int _lseek(int fd, int ptr, int dir) +{ + (void)fd; + (void)ptr; + (void)dir; + + errno = EBADF; + return -1; +} + +__attribute__((weak)) int _fstat(int fd, struct stat *st) +{ + if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) + { + st->st_mode = S_IFCHR; + return 0; + } + + errno = EBADF; + return 0; +} + +__attribute__((weak)) int _getpid(void) +{ + errno = ENOSYS; + return -1; +} + +__attribute__((weak)) int _kill(pid_t pid, int sig) +{ + (void)pid; + (void)sig; + errno = ENOSYS; + return -1; +} +