File port_stm32_hal.c¶
File List > port > stm32_hal > port_stm32_hal.c
Go to the documentation of this file
#if !defined(ARDUINO) && \
(defined(STM32F0xx) || defined(STM32F1xx) || defined(STM32F4xx) || defined(STM32F7xx) || \
defined(STM32L4xx) || defined(STM32G0xx) || defined(STM32H7xx) || defined(STM32C0xx) || \
defined(STM32U0xx) || defined(STM32F0) || defined(STM32F1) || defined(STM32F4) || \
defined(STM32F7) || defined(STM32L4) || defined(STM32G0) || defined(STM32H7) || \
defined(STM32C0) || defined(STM32U0))
#include "syntropic/common/syn_defs.h"
#include "syntropic/port/syn_port_gpio.h"
#include "syntropic/port/syn_port_system.h"
#include "syntropic/port/syn_port_uart.h"
/* ── STM32 HAL Headers ─────────────────────────────────────────────────── */
/* Adjust the include based on your target microcontroller family. */
#if defined(STM32F072xx) || defined(STM32F0) || defined(STM32F0xx)
#include "stm32f0xx_hal.h"
#elif defined(STM32F407xx) || defined(STM32F4) || defined(STM32F4xx)
#include "stm32f4xx_hal.h"
#elif defined(STM32F746xx) || defined(STM32F767xx) || defined(STM32F7) || defined(STM32F7xx)
#include "stm32f7xx_hal.h"
#elif defined(STM32F103xx) || defined(STM32F1) || defined(STM32F1xx)
#include "stm32f1xx_hal.h"
#elif defined(STM32L476xx) || defined(STM32L4) || defined(STM32L4xx)
#include "stm32l4xx_hal.h"
#elif defined(STM32G071xx) || defined(STM32G0) || defined(STM32G0xx)
#include "stm32g0xx_hal.h"
#elif defined(STM32H743xx) || defined(STM32H7) || defined(STM32H7xx)
#include "stm32h7xx_hal.h"
#elif defined(STM32C092xx) || defined(STM32C0) || defined(STM32C0xx)
#include "stm32c0xx_hal.h"
#elif defined(STM32U083xx) || defined(STM32U0) || defined(STM32U0xx)
#include "stm32u0xx_hal.h"
#else
/* Fallback: user can define this header or configure their include path */
#include "stm32_hal.h"
#endif
/* ── System Port ────────────────────────────────────────────────────────── */
static volatile uint32_t critical_nesting = 0;
void syn_port_enter_critical(void)
{
__disable_irq();
critical_nesting++;
}
void syn_port_exit_critical(void)
{
if (critical_nesting > 0) {
critical_nesting--;
if (critical_nesting == 0) {
__enable_irq();
}
}
}
uint32_t syn_port_get_tick_ms(void)
{
return HAL_GetTick();
}
void syn_port_delay_ms(uint32_t ms)
{
HAL_Delay(ms);
}
void syn_port_system_reset(void)
{
NVIC_SystemReset();
for (;;)
;
}
/* ── GPIO Port ──────────────────────────────────────────────────────────── */
static GPIO_TypeDef *get_gpio_port(SYN_GPIO_Pin pin)
{
uint8_t port_idx = SYN_GPIO_PIN_PORT(pin);
switch (port_idx) {
#ifdef GPIOA
case 0:
return GPIOA;
#endif
#ifdef GPIOB
case 1:
return GPIOB;
#endif
#ifdef GPIOC
case 2:
return GPIOC;
#endif
#ifdef GPIOD
case 3:
return GPIOD;
#endif
#ifdef GPIOE
case 4:
return GPIOE;
#endif
#ifdef GPIOF
case 5:
return GPIOF;
#endif
#ifdef GPIOG
case 6:
return GPIOG;
#endif
#ifdef GPIOH
case 7:
return GPIOH;
#endif
#ifdef GPIOI
case 8:
return GPIOI;
#endif
default:
return NULL;
}
}
static uint16_t get_gpio_pin_mask(SYN_GPIO_Pin pin)
{
return (uint16_t)(1U << SYN_GPIO_PIN_NUM(pin));
}
SYN_Status syn_port_gpio_init(SYN_GPIO_Pin pin, SYN_GPIO_Mode mode)
{
GPIO_TypeDef *port = get_gpio_port(pin);
if (!port)
return SYN_INVALID_PARAM;
/* Enable peripheral clock dynamically */
uint8_t port_idx = SYN_GPIO_PIN_PORT(pin);
switch (port_idx) {
#ifdef GPIOA
case 0:
__HAL_RCC_GPIOA_CLK_ENABLE();
break;
#endif
#ifdef GPIOB
case 1:
__HAL_RCC_GPIOB_CLK_ENABLE();
break;
#endif
#ifdef GPIOC
case 2:
__HAL_RCC_GPIOC_CLK_ENABLE();
break;
#endif
#ifdef GPIOD
case 3:
__HAL_RCC_GPIOD_CLK_ENABLE();
break;
#endif
#ifdef GPIOE
case 4:
__HAL_RCC_GPIOE_CLK_ENABLE();
break;
#endif
#ifdef GPIOF
case 5:
__HAL_RCC_GPIOF_CLK_ENABLE();
break;
#endif
#ifdef GPIOG
case 6:
__HAL_RCC_GPIOG_CLK_ENABLE();
break;
#endif
#ifdef GPIOH
case 7:
__HAL_RCC_GPIOH_CLK_ENABLE();
break;
#endif
#ifdef GPIOI
case 8:
__HAL_RCC_GPIOI_CLK_ENABLE();
break;
#endif
default:
return SYN_INVALID_PARAM;
}
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = get_gpio_pin_mask(pin);
switch (mode) {
case SYN_GPIO_INPUT:
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
break;
case SYN_GPIO_OUTPUT:
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
break;
case SYN_GPIO_INPUT_PULLUP:
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
break;
case SYN_GPIO_INPUT_PULLDOWN:
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
break;
case SYN_GPIO_OUTPUT_OD:
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
break;
default:
return SYN_NOT_IMPLEMENTED;
}
HAL_GPIO_Init(port, &GPIO_InitStruct);
return SYN_OK;
}
SYN_Status syn_port_gpio_deinit(SYN_GPIO_Pin pin)
{
GPIO_TypeDef *port = get_gpio_port(pin);
if (!port)
return SYN_INVALID_PARAM;
HAL_GPIO_DeInit(port, get_gpio_pin_mask(pin));
return SYN_OK;
}
SYN_Status syn_port_gpio_write(SYN_GPIO_Pin pin, SYN_GPIO_State state)
{
GPIO_TypeDef *port = get_gpio_port(pin);
if (!port)
return SYN_INVALID_PARAM;
HAL_GPIO_WritePin(port, get_gpio_pin_mask(pin),
(state == SYN_GPIO_HIGH) ? GPIO_PIN_SET : GPIO_PIN_RESET);
return SYN_OK;
}
SYN_GPIO_State syn_port_gpio_read(SYN_GPIO_Pin pin)
{
GPIO_TypeDef *port = get_gpio_port(pin);
if (!port)
return SYN_GPIO_LOW;
return (HAL_GPIO_ReadPin(port, get_gpio_pin_mask(pin)) == GPIO_PIN_SET) ? SYN_GPIO_HIGH
: SYN_GPIO_LOW;
}
SYN_Status syn_port_gpio_toggle(SYN_GPIO_Pin pin)
{
GPIO_TypeDef *port = get_gpio_port(pin);
if (!port)
return SYN_INVALID_PARAM;
HAL_GPIO_TogglePin(port, get_gpio_pin_mask(pin));
return SYN_OK;
}
/* ── UART Port ──────────────────────────────────────────────────────────── */
UART_HandleTypeDef *syn_port_uart_handles[6] = {NULL};
SYN_Status syn_port_stm32_register_uart(SYN_UARTInstance instance, void *huart)
{
if (instance >= 6) {
return SYN_INVALID_PARAM;
}
syn_port_uart_handles[instance] = (UART_HandleTypeDef *)huart;
return SYN_OK;
}
static UART_HandleTypeDef *get_uart_handle(SYN_UARTInstance instance)
{
if (instance < 6) {
return syn_port_uart_handles[instance];
}
return NULL;
}
SYN_Status syn_port_uart_init(SYN_UARTInstance instance, uint32_t baudrate)
{
(void)baudrate;
UART_HandleTypeDef *huart = get_uart_handle(instance);
if (!huart) {
return SYN_INVALID_PARAM;
}
return SYN_OK;
}
SYN_Status syn_port_uart_deinit(SYN_UARTInstance instance)
{
UART_HandleTypeDef *huart = get_uart_handle(instance);
if (!huart) {
return SYN_INVALID_PARAM;
}
HAL_StatusTypeDef status = HAL_UART_DeInit(huart);
return (status == HAL_OK) ? SYN_OK : SYN_ERROR;
}
SYN_Status syn_port_uart_transmit(SYN_UARTInstance instance, const uint8_t *data, size_t len,
uint32_t timeout_ms)
{
UART_HandleTypeDef *huart = get_uart_handle(instance);
if (!huart)
return SYN_INVALID_PARAM;
HAL_StatusTypeDef status = HAL_UART_Transmit(huart, (uint8_t *)data, (uint16_t)len,
timeout_ms == 0 ? HAL_MAX_DELAY : timeout_ms);
switch (status) {
case HAL_OK:
return SYN_OK;
case HAL_TIMEOUT:
return SYN_TIMEOUT;
case HAL_BUSY:
return SYN_BUSY;
default:
return SYN_ERROR;
}
}
SYN_Status syn_port_uart_receive(SYN_UARTInstance instance, uint8_t *data, size_t len,
size_t *received, uint32_t timeout_ms)
{
UART_HandleTypeDef *huart = get_uart_handle(instance);
if (!huart)
return SYN_INVALID_PARAM;
size_t count = 0;
uint32_t start_ms = syn_port_get_tick_ms();
uint32_t per_byte_timeout = (timeout_ms > 0) ? 1 : 1;
while (count < len) {
/* Clear any overrun error before attempting receive */
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET) {
__HAL_UART_CLEAR_OREFLAG(huart);
}
HAL_StatusTypeDef status = HAL_UART_Receive(huart, &data[count], 1, per_byte_timeout);
if (status == HAL_OK) {
count++;
} else {
/* No byte available within per_byte_timeout */
if (timeout_ms > 0 && (syn_port_get_tick_ms() - start_ms) >= timeout_ms) {
break;
}
if (count > 0) {
/* We got at least one byte; return what we have */
break;
}
break; /* No data, return immediately to let scheduler run */
}
}
if (received)
*received = count;
return (count > 0) ? SYN_OK : SYN_TIMEOUT;
}
SYN_Status syn_port_uart_transmit_byte(SYN_UARTInstance instance, uint8_t byte)
{
return syn_port_uart_transmit(instance, &byte, 1, 100);
}
SYN_Status syn_port_uart_receive_byte(SYN_UARTInstance instance, uint8_t *byte, uint32_t timeout_ms)
{
size_t rec = 0;
return syn_port_uart_receive(instance, byte, 1, &rec, timeout_ms);
}
/* ── Console serial port ────────────────────────────────────────────────── */
#include "syntropic/port/syn_port_serial.h"
#ifndef SYN_SERIAL_UART_INSTANCE
#define SYN_SERIAL_UART_INSTANCE 0
#endif
SYN_WEAK SYN_Status syn_port_serial_init(uint32_t baudrate)
{
if (baudrate == 0)
baudrate = 115200;
return syn_port_uart_init(SYN_SERIAL_UART_INSTANCE, baudrate);
}
SYN_WEAK int syn_port_serial_write(const uint8_t *data, size_t len)
{
SYN_Status s = syn_port_uart_transmit(SYN_SERIAL_UART_INSTANCE, data, len, 100);
return (s == SYN_OK) ? (int)len : -1;
}
SYN_WEAK int syn_port_serial_read(uint8_t *buf, size_t max_len)
{
size_t received = 0;
SYN_Status s = syn_port_uart_receive(SYN_SERIAL_UART_INSTANCE, buf, max_len, &received, 0);
if (s == SYN_TIMEOUT)
return (int)received;
if (s != SYN_OK)
return -1;
return (int)received;
}
#endif /* STM32 HAL */