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"
#include "syntropic/util/syn_assert.h"
/* ── Assert Handler Fallback ────────────────────────────────────────────── */
SYN_WEAK SYN_NORETURN void syn_assert_failed(const char *file, int line)
{
(void)file;
(void)line;
__disable_irq();
for (;;) {
}
}
/* ── 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();
}
uint32_t syn_port_get_tick_us(void)
{
uint32_t ms = HAL_GetTick();
uint32_t load = SysTick->LOAD;
if (load > 0) {
uint32_t val = SysTick->VAL;
uint32_t elapsed_cycles = load - val;
uint32_t cycles_per_us = SystemCoreClock / 1000000U;
if (cycles_per_us > 0) {
return (ms * 1000U) + (elapsed_cycles / cycles_per_us);
}
}
return ms * 1000U;
}
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;
}
/* ── Hardware Flash Port (STM32 HAL) ────────────────────────────────────── */
#include "syntropic/port/syn_port_flash.h"
#if defined(FLASH_TYPEERASE_SECTORS)
static uint32_t syn_stm32_addr_to_sector(uint32_t addr)
{
if (addr < 0x08004000U) return FLASH_SECTOR_0;
if (addr < 0x08008000U) return FLASH_SECTOR_1;
if (addr < 0x0800C000U) return FLASH_SECTOR_2;
if (addr < 0x08010000U) return FLASH_SECTOR_3;
if (addr < 0x08020000U) return FLASH_SECTOR_4;
if (addr < 0x08040000U) return FLASH_SECTOR_5;
if (addr < 0x08060000U) return FLASH_SECTOR_6;
if (addr < 0x08080000U) return FLASH_SECTOR_7;
if (addr < 0x080A0000U) return FLASH_SECTOR_8;
if (addr < 0x080C0000U) return FLASH_SECTOR_9;
if (addr < 0x080E0000U) return FLASH_SECTOR_10;
if (addr < 0x08100000U) return FLASH_SECTOR_11;
#if defined(FLASH_SECTOR_12)
if (addr < 0x08104000U) return FLASH_SECTOR_12;
if (addr < 0x08108000U) return FLASH_SECTOR_13;
if (addr < 0x0810C000U) return FLASH_SECTOR_14;
if (addr < 0x08110000U) return FLASH_SECTOR_15;
if (addr < 0x08120000U) return FLASH_SECTOR_16;
if (addr < 0x08140000U) return FLASH_SECTOR_17;
if (addr < 0x08160000U) return FLASH_SECTOR_18;
if (addr < 0x08180000U) return FLASH_SECTOR_19;
if (addr < 0x081A0000U) return FLASH_SECTOR_20;
if (addr < 0x081C0000U) return FLASH_SECTOR_21;
if (addr < 0x081E0000U) return FLASH_SECTOR_22;
return FLASH_SECTOR_23;
#else
return FLASH_SECTOR_11;
#endif
}
#endif
SYN_WEAK SYN_Status syn_port_flash_read(uint32_t addr, void *buf, size_t len)
{
if (buf == NULL)
return SYN_INVALID_PARAM;
memcpy(buf, (const void *)addr, len);
return SYN_OK;
}
SYN_WEAK SYN_Status syn_port_flash_erase(uint32_t addr)
{
HAL_FLASH_Unlock();
#if defined(FLASH_TYPEERASE_SECTORS)
FLASH_EraseInitTypeDef erase;
erase.TypeErase = FLASH_TYPEERASE_SECTORS;
erase.Sector = syn_stm32_addr_to_sector(addr);
erase.NbSectors = 1;
erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
uint32_t error = 0;
HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase, &error);
#elif defined(FLASH_TYPEERASE_PAGES)
FLASH_EraseInitTypeDef erase;
erase.TypeErase = FLASH_TYPEERASE_PAGES;
erase.PageAddress = addr;
erase.NbPages = 1;
uint32_t error = 0;
HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase, &error);
#else
HAL_StatusTypeDef status = HAL_ERROR;
(void)addr;
#endif
HAL_FLASH_Lock();
return (status == HAL_OK) ? SYN_OK : SYN_ERROR;
}
SYN_WEAK SYN_Status syn_port_flash_write(uint32_t addr, const void *buf, size_t len)
{
if (buf == NULL)
return SYN_INVALID_PARAM;
const uint8_t *src = (const uint8_t *)buf;
HAL_FLASH_Unlock();
HAL_StatusTypeDef status = HAL_OK;
for (size_t i = 0; i < len; i++) {
#if defined(FLASH_TYPEPROGRAM_BYTE)
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, addr + i, src[i]);
#elif defined(FLASH_TYPEPROGRAM_DOUBLEWORD)
if (i + 8 <= len && ((addr + i) % 8 == 0)) {
uint64_t val = 0;
memcpy(&val, &src[i], 8);
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr + i, val);
i += 7;
} else {
uint64_t val = 0xFFFFFFFFFFFFFFFFULL;
size_t rem = len - i;
memcpy(&val, &src[i], rem > 8 ? 8 : rem);
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr + i, val);
i += 7;
}
#else
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr + i, src[i]);
#endif
if (status != HAL_OK)
break;
}
HAL_FLASH_Lock();
return (status == HAL_OK) ? SYN_OK : SYN_ERROR;
}
SYN_WEAK uint32_t syn_port_flash_sector_size(uint32_t addr)
{
if (addr < 0x08010000U)
return 16u * 1024u;
if (addr < 0x08020000U)
return 64u * 1024u;
#if defined(FLASH_SECTOR_12)
if (addr >= 0x08100000U && addr < 0x08110000U)
return 16u * 1024u;
if (addr >= 0x08110000U && addr < 0x08120000U)
return 64u * 1024u;
#endif
return 128u * 1024u;
}
/* ── Hardware Crypto Port (STM32 CRYP) ─────────────────────────────────── */
#include "syntropic/port/syn_port_aes.h"
static void *g_hcryp = NULL;
SYN_Status syn_port_stm32_register_cryp(void *hcryp)
{
g_hcryp = hcryp;
return SYN_OK;
}
SYN_Status syn_port_aes_init(void)
{
#if defined(CRYP) || defined(AES)
return (g_hcryp != NULL) ? SYN_OK : SYN_NOT_IMPLEMENTED;
#else
return SYN_NOT_IMPLEMENTED;
#endif
}
SYN_Status syn_port_aes_encrypt_block(const uint8_t *round_keys, uint8_t nr, const uint8_t in[16],
uint8_t out[16])
{
#if defined(CRYP) || defined(AES)
if (g_hcryp == NULL || round_keys == NULL || in == NULL || out == NULL) {
return SYN_NOT_IMPLEMENTED;
}
#if defined(HAL_CRYP_MODULE_ENABLED)
CRYP_HandleTypeDef *hcryp = (CRYP_HandleTypeDef *)g_hcryp;
HAL_StatusTypeDef res = HAL_CRYP_AESECB_Encrypt(hcryp, (uint8_t *)in, 16U, out, 1000U);
return (res == HAL_OK) ? SYN_OK : SYN_ERROR;
#else
(void)nr;
return SYN_NOT_IMPLEMENTED;
#endif
#else
(void)round_keys;
(void)nr;
(void)in;
(void)out;
return SYN_NOT_IMPLEMENTED;
#endif
}
SYN_Status syn_port_aes_decrypt_block(const uint8_t *round_keys, uint8_t nr, const uint8_t in[16],
uint8_t out[16])
{
#if defined(CRYP) || defined(AES)
if (g_hcryp == NULL || round_keys == NULL || in == NULL || out == NULL) {
return SYN_NOT_IMPLEMENTED;
}
#if defined(HAL_CRYP_MODULE_ENABLED)
CRYP_HandleTypeDef *hcryp = (CRYP_HandleTypeDef *)g_hcryp;
HAL_StatusTypeDef res = HAL_CRYP_AESECB_Decrypt(hcryp, (uint8_t *)in, 16U, out, 1000U);
return (res == HAL_OK) ? SYN_OK : SYN_ERROR;
#else
(void)nr;
return SYN_NOT_IMPLEMENTED;
#endif
#else
(void)round_keys;
(void)nr;
(void)in;
(void)out;
return SYN_NOT_IMPLEMENTED;
#endif
}
SYN_Status syn_port_ghash_mult(const uint8_t x[16], const uint8_t h[16], uint8_t out[16])
{
(void)x;
(void)h;
(void)out;
return SYN_NOT_IMPLEMENTED;
}
#endif /* STM32 HAL */