commit 0bae19852f16f3039a7863c76ad0854bd81da56a Author: zhaohe Date: Wed Jan 3 22:12:13 2024 +0800 init diff --git a/README.md b/README.md new file mode 100644 index 0000000..d5a256b --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +``` +1. 微秒定时器 OK +3. 日志接口 OK +5. GPIO初始化中断处理 OK +7. SPI读写 +8. 线程 +9. 按键检测 +``` \ No newline at end of file diff --git a/iflytop_xsync.h b/iflytop_xsync.h new file mode 100644 index 0000000..5f1f83e --- /dev/null +++ b/iflytop_xsync.h @@ -0,0 +1,15 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xs_basic.h" +#include "xs_delay.h" +#include "xs_flash.h" +#include "xs_gpio.h" +#include "xs_log.h" +#include "xs_id.h" +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/pin.c b/pin.c new file mode 100644 index 0000000..34984c6 --- /dev/null +++ b/pin.c @@ -0,0 +1,234 @@ +#include "pin.h" +const char* pinname(Pin_t pin) { + switch (pin) { + case PinNull: + return "PinNull"; + case PA0: + return "PA0"; + case PA1: + return "PA1"; + case PA2: + return "PA2"; + case PA3: + return "PA3"; + case PA4: + return "PA4"; + case PA5: + return "PA5"; + case PA6: + return "PA6"; + case PA7: + return "PA7"; + case PA8: + return "PA8"; + case PA9: + return "PA9"; + case PA10: + return "PA10"; + case PA11: + return "PA11"; + case PA12: + return "PA12"; + case PA13: + return "PA13"; + case PA14: + return "PA14"; + case PA15: + return "PA15"; + case PB0: + return "PB0"; + case PB1: + return "PB1"; + case PB2: + return "PB2"; + case PB3: + return "PB3"; + case PB4: + return "PB4"; + case PB5: + return "PB5"; + case PB6: + return "PB6"; + case PB7: + return "PB7"; + case PB8: + return "PB8"; + case PB9: + return "PB9"; + case PB10: + return "PB10"; + case PB11: + return "PB11"; + case PB12: + return "PB12"; + case PB13: + return "PB13"; + case PB14: + return "PB14"; + case PB15: + return "PB15"; + case PC0: + return "PC0"; + case PC1: + return "PC1"; + case PC2: + return "PC2"; + case PC3: + return "PC3"; + case PC4: + return "PC4"; + case PC5: + return "PC5"; + case PC6: + return "PC6"; + case PC7: + return "PC7"; + case PC8: + return "PC8"; + case PC9: + return "PC9"; + case PC10: + return "PC10"; + case PC11: + return "PC11"; + case PC12: + return "PC12"; + case PC13: + return "PC13"; + case PC14: + return "PC14"; + case PC15: + return "PC15"; + case PD0: + return "PD0"; + case PD1: + return "PD1"; + case PD2: + return "PD2"; + case PD3: + return "PD3"; + case PD4: + return "PD4"; + case PD5: + return "PD5"; + case PD6: + return "PD6"; + case PD7: + return "PD7"; + case PD8: + return "PD8"; + case PD9: + return "PD9"; + case PD10: + return "PD10"; + case PD11: + return "PD11"; + case PD12: + return "PD12"; + case PD13: + return "PD13"; + case PD14: + return "PD14"; + case PD15: + return "PD15"; + case PE0: + return "PE0"; + case PE1: + return "PE1"; + case PE2: + return "PE2"; + case PE3: + return "PE3"; + case PE4: + return "PE4"; + case PE5: + return "PE5"; + case PE6: + return "PE6"; + case PE7: + return "PE7"; + case PE8: + return "PE8"; + case PE9: + return "PE9"; + case PE10: + return "PE10"; + case PE11: + return "PE11"; + case PE12: + return "PE12"; + case PE13: + return "PE13"; + case PE14: + return "PE14"; + case PE15: + return "PE15"; + case PF0: + return "PF0"; + case PF1: + return "PF1"; + case PF2: + return "PF2"; + case PF3: + return "PF3"; + case PF4: + return "PF4"; + case PF5: + return "PF5"; + case PF6: + return "PF6"; + case PF7: + return "PF7"; + case PF8: + return "PF8"; + case PF9: + return "PF9"; + case PF10: + return "PF10"; + case PF11: + return "PF11"; + case PF12: + return "PF12"; + case PF13: + return "PF13"; + case PF14: + return "PF14"; + case PF15: + return "PF15"; + case PG0: + return "PG0"; + case PG1: + return "PG1"; + case PG2: + return "PG2"; + case PG3: + return "PG3"; + case PG4: + return "PG4"; + case PG5: + return "PG5"; + case PG6: + return "PG6"; + case PG7: + return "PG7"; + case PG8: + return "PG8"; + case PG9: + return "PG9"; + case PG10: + return "PG10"; + case PG11: + return "PG11"; + case PG12: + return "PG12"; + case PG13: + return "PG13"; + case PG14: + return "PG14"; + case PG15: + return "PG15"; + default: + break; + } + return "UNKNOWN_PIN"; +}; diff --git a/pin.h b/pin.h new file mode 100644 index 0000000..1b44440 --- /dev/null +++ b/pin.h @@ -0,0 +1,119 @@ +#pragma once + +typedef enum { + PinNull = 0, + PA0 = 0x10, + PA1, + PA2, + PA3, + PA4, + PA5, + PA6, + PA7, + PA8, + PA9, + PA10, + PA11, + PA12, + PA13, + PA14, + PA15, + PB0 = 0x20, + PB1, + PB2, + PB3, + PB4, + PB5, + PB6, + PB7, + PB8, + PB9, + PB10, + PB11, + PB12, + PB13, + PB14, + PB15, + PC0 = 0x30, + PC1, + PC2, + PC3, + PC4, + PC5, + PC6, + PC7, + PC8, + PC9, + PC10, + PC11, + PC12, + PC13, + PC14, + PC15, + PD0 = 0x40, + PD1, + PD2, + PD3, + PD4, + PD5, + PD6, + PD7, + PD8, + PD9, + PD10, + PD11, + PD12, + PD13, + PD14, + PD15, + PE0 = 0x50, + PE1, + PE2, + PE3, + PE4, + PE5, + PE6, + PE7, + PE8, + PE9, + PE10, + PE11, + PE12, + PE13, + PE14, + PE15, + PF0 = 0x60, + PF1, + PF2, + PF3, + PF4, + PF5, + PF6, + PF7, + PF8, + PF9, + PF10, + PF11, + PF12, + PF13, + PF14, + PF15, + PG0 = 0x70, + PG1, + PG2, + PG3, + PG4, + PG5, + PG6, + PG7, + PG8, + PG9, + PG10, + PG11, + PG12, + PG13, + PG14, + PG15, +} Pin_t; + +const char* pinname(Pin_t pin); \ No newline at end of file diff --git a/xs_basic.c b/xs_basic.c new file mode 100644 index 0000000..e69de29 diff --git a/xs_basic.h b/xs_basic.h new file mode 100644 index 0000000..184b2e4 --- /dev/null +++ b/xs_basic.h @@ -0,0 +1,9 @@ +#pragma once +#include "main.h" +// +#include "project_configs.h" +// +#include "cmsis_os.h" +// +#include +#include diff --git a/xs_delay.c b/xs_delay.c new file mode 100644 index 0000000..d5f6b0b --- /dev/null +++ b/xs_delay.c @@ -0,0 +1,60 @@ +#include "xs_delay.h" + +#include "xs_basic.h" + +extern TIM_HandleTypeDef PC_SYS_DELAY_US_TIMER; + +static HAL_StatusTypeDef _HAL_TIM_Base_Start(TIM_HandleTypeDef* htim) __attribute__((optimize("O2"))); +static HAL_StatusTypeDef _HAL_TIM_Base_Stop(TIM_HandleTypeDef* htim) __attribute__((optimize("O2"))); +static HAL_StatusTypeDef _HAL_TIM_Base_Start(TIM_HandleTypeDef* htim) { + uint32_t tmpsmcr; + /* Check the TIM state */ + if (htim->State != HAL_TIM_STATE_READY) { + return HAL_ERROR; + } + htim->State = HAL_TIM_STATE_BUSY; + if (IS_TIM_SLAVE_INSTANCE(htim->Instance)) { + tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS; + if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr)) { + __HAL_TIM_ENABLE(htim); + } + } else { + __HAL_TIM_ENABLE(htim); + } + return HAL_OK; +} +static HAL_StatusTypeDef _HAL_TIM_Base_Stop(TIM_HandleTypeDef* htim) { + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + /* Set the TIM state */ + htim->State = HAL_TIM_STATE_READY; + /* Return function status */ + return HAL_OK; +} + +void xs_delay_us(int var_nus) { + volatile uint32_t counter = 0; + __HAL_TIM_SET_COUNTER(&PC_SYS_DELAY_US_TIMER, 0); + _HAL_TIM_Base_Start(&PC_SYS_DELAY_US_TIMER); + while (counter < var_nus) { + counter = __HAL_TIM_GET_COUNTER(&PC_SYS_DELAY_US_TIMER); + } + _HAL_TIM_Base_Stop(&PC_SYS_DELAY_US_TIMER); +} +void xs_delay_ms(int ms) { + for (int i = 0; i < ms; i++) { + xs_delay_us(1000); + } +} +void xs_os_delay_ms(int ms) { osDelay(ms); } + +uint32_t xs_get_ticket(void) { return HAL_GetTick(); } + +uint32_t xs_has_passedms(uint32_t ticket) { + uint32_t now = HAL_GetTick(); + if (now >= ticket) { + return now - ticket; + } else { + return 0xFFFFFFFF - ticket + now; + } +} diff --git a/xs_delay.h b/xs_delay.h new file mode 100644 index 0000000..3b5d2f1 --- /dev/null +++ b/xs_delay.h @@ -0,0 +1,7 @@ +#pragma once +#include +void xs_delay_us(int us); +void xs_delay_ms(int ms); +void xs_os_delay_ms(int ms); +uint32_t xs_get_ticket(void); +uint32_t xs_has_passedms(uint32_t ticket); diff --git a/xs_flash.c b/xs_flash.c new file mode 100644 index 0000000..aa94e51 --- /dev/null +++ b/xs_flash.c @@ -0,0 +1,110 @@ +#include "xs_flash.h" + +#include +#include +#include + +#include "xs_log.h" + +static uint32_t* _rawstartadd; +static uint32_t* _defaultdata; +static uint32_t _rawsize; +static bool _is_first_run = false; + +static bool _xs_check_raw_data() { + uint32_t checksum = 0; + ZLOGI("flash", "_rawstartadd[0] = %x", _rawstartadd[0]); + if (_rawstartadd[0] != FLASH_MASK_VAL) { + return false; + } + for (uint32_t i = 0; i < _rawsize - 1; i++) { + checksum += _rawstartadd[i]; + } + if (checksum != _rawstartadd[_rawsize - 1]) { + return false; + } + return true; +} + +static HAL_StatusTypeDef _flash_erase(void) { + HAL_StatusTypeDef status; + uint32_t sector_error_point; + FLASH_EraseInitTypeDef flash_erase_structer = { + // + .TypeErase = FLASH_TYPEERASE_SECTORS, // + .Sector = FLASH_EARSE_SECTOR, // + .NbSectors = 1, // + .VoltageRange = FLASH_VOLTAGE_RANGE_3 // + }; + + HAL_FLASH_Unlock(); // 解锁 + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); // 清除一些错误标志 + status = HAL_FLASHEx_Erase(&flash_erase_structer, §or_error_point); + if (status != HAL_OK) { + ZLOGE("flash", "erase error"); + } + HAL_FLASH_Lock(); // 上锁 + return status; +} +/******************************************************************************* + * EXTERN * + *******************************************************************************/ + +void xs_flash_init(uint32_t* rawstartadd, uint32_t rawsize) { + _rawstartadd = rawstartadd; + _defaultdata = NULL; + _rawsize = rawsize; + + // 读取flash数据 + memcpy(_rawstartadd, (uint32_t*)(FLASH_START_ADD), _rawsize * 4); + +#if 0 + // 校验数据 + if (_xs_check_raw_data()) { + return; + } + _is_first_run = true; + xs_flash_factory_reset(); +#endif +} + +bool xs_flash_check(void) { return _xs_check_raw_data(); } + +bool xs_flash_set_default_data(uint32_t* defaultdata) { + _defaultdata = defaultdata; + return true; +} + +bool xs_flash_is_first_run(void) { return _is_first_run; } + +uint32_t xs_compute_checksum(uint32_t* data, uint32_t size) { + uint32_t checksum = 0; + for (uint32_t i = 0; i < size; i++) { + checksum += data[i]; + } + return checksum; +} +bool xs_flash_factory_reset(void) { + memcpy(_rawstartadd, _defaultdata, _rawsize * 4); + xs_flash_flush(); + return true; +} + +bool xs_flash_flush(void) { +#if PC_NVS_ENABLE + _rawstartadd[0] = FLASH_MASK_VAL; + _rawstartadd[_rawsize - 1] = xs_compute_checksum(_rawstartadd, _rawsize - 1); + + _flash_erase(); + HAL_FLASH_Unlock(); // 解锁 + HAL_StatusTypeDef status; + for (uint32_t i = 0; i < _rawsize; i++) { + status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_START_ADD + i * 4, _rawstartadd[i]); + if (status != HAL_OK) { + ZLOGE("flash", "write error"); + } + } + HAL_FLASH_Lock(); // 上锁 +#endif + return true; +} diff --git a/xs_flash.h b/xs_flash.h new file mode 100644 index 0000000..44efdd3 --- /dev/null +++ b/xs_flash.h @@ -0,0 +1,68 @@ +#pragma once +#include + +#include "main.h" + +/** + * @brief + * STM32F407VETx 512k + * + * index startAdd size + * 0 0x08000000 16k + * 1 0x08004000 16k + * 2 0x08008000 16k + * 3 0x0800C000 16k + * 4 0x08010000 64k + * 5 0x08020000 128k + * 6 0x08040000 128k + * 7 0x08060000 128k + * + * + * @WARNING: + * 1. 我们使用第7个扇区,即0x08060000~0x0807FFFF + * 2. 程序最大不能超过75% + * 3. rawstartadd第一位必须是0xABCD,最后一位是校验和 + */ + +#define FLASH_MASK_VAL 0xABCD +#define FLASH_START_ADD 0x08060000 // +#define FLASH_EARSE_SECTOR FLASH_SECTOR_7 + +/** + * @brief 初始化flash + * + * @param rawstartadd flash内存映射的地址 + * @param defaultdata 默认数据 + * @param rawsize flash内存映射的地址大小 + */ +void xs_flash_init(uint32_t* rawstartadd, uint32_t rawsize); +/** + * @brief 判断是否是第一次初始化flash + * + * @return true + * @return false + */ +bool xs_flash_is_first_run(void); +/** + * @brief 刷新内存输出到flash中 + * + * @return true + * @return false + */ +bool xs_flash_flush(void); +/** + * @brief 恢复出厂设置 + * + * @return true + * @return false + */ +bool xs_flash_factory_reset(void); +/** + * @brief + * + * @param defaultdata + * @return true + * @return false + */ +bool xs_flash_set_default_data(uint32_t* defaultdata); +bool xs_flash_check(void); diff --git a/xs_gpio.c b/xs_gpio.c new file mode 100644 index 0000000..4909c79 --- /dev/null +++ b/xs_gpio.c @@ -0,0 +1,327 @@ +#include "xs_gpio.h" + +static bool gpio_enable_clock(GPIO_TypeDef *m_gpio) { +#ifdef GPIOA + if (m_gpio == GPIOA) { + __HAL_RCC_GPIOA_CLK_ENABLE(); + return true; + } +#endif +#ifdef GPIOB + if (m_gpio == GPIOB) { + __HAL_RCC_GPIOB_CLK_ENABLE(); + return true; + } +#endif +#ifdef GPIOC + if (m_gpio == GPIOC) { + __HAL_RCC_GPIOC_CLK_ENABLE(); + return true; + } +#endif +#ifdef GPIOD + if (m_gpio == GPIOD) { + __HAL_RCC_GPIOD_CLK_ENABLE(); + return true; + } +#endif +#ifdef GPIOE + if (m_gpio == GPIOE) { + __HAL_RCC_GPIOE_CLK_ENABLE(); + return true; + } +#endif +#ifdef GPIOF + if (m_gpio == GPIOF) { + __HAL_RCC_GPIOF_CLK_ENABLE(); + return true; + } +#endif +#ifdef GPIOG + if (m_gpio == GPIOG) { + __HAL_RCC_GPIOG_CLK_ENABLE(); + return true; + } +#endif +#ifdef GPIOH + if (m_gpio == GPIOH) { + __HAL_RCC_GPIOH_CLK_ENABLE(); + return true; + } +#endif +#ifdef GPIOI + if (m_gpio == GPIOI) { + __HAL_RCC_GPIOI_CLK_ENABLE(); + return true; + } +#endif +#ifdef GPIOJ + if (m_gpio == GPIOJ) { + __HAL_RCC_GPIOJ_CLK_ENABLE(); + return true; + } +#endif +#ifdef GPIOK + if (m_gpio == GPIOK) { + __HAL_RCC_GPIOK_CLK_ENABLE(); + return true; + } +#endif + return false; +} + +static GPIO_TypeDef *_chip_get_gpio(Pin_t pin) { + int port = pin >> 4; + + switch (port) { + case 1: +#ifdef GPIOA + return GPIOA; +#endif + break; + case 2: +#ifdef GPIOB + return GPIOB; +#endif + break; + case 3: +#ifdef GPIOC + return GPIOC; +#endif + break; + case 4: +#ifdef GPIOD + return GPIOD; +#endif + break; + + case 5: +#ifdef GPIOE + return GPIOE; +#endif + break; + case 6: +#ifdef GPIOF + return GPIOF; +#endif + break; + case 7: +#ifdef GPIOG + return GPIOG; +#endif + break; + default: + break; + } + return NULL; +} +static uint16_t _chip_get_pinoff(Pin_t pin) { + uint16_t pinoff = pin & 0x0F; + switch (pinoff) { + case 0: + return GPIO_PIN_0; + case 1: + return GPIO_PIN_1; + case 2: + return GPIO_PIN_2; + case 3: + return GPIO_PIN_3; + case 4: + return GPIO_PIN_4; + case 5: + return GPIO_PIN_5; + case 6: + return GPIO_PIN_6; + case 7: + return GPIO_PIN_7; + case 8: + return GPIO_PIN_8; + case 9: + return GPIO_PIN_9; + case 10: + return GPIO_PIN_10; + case 11: + return GPIO_PIN_11; + case 12: + return GPIO_PIN_12; + case 13: + return GPIO_PIN_13; + case 14: + return GPIO_PIN_14; + case 15: + return GPIO_PIN_15; + default: + break; + }; + return 0; +} + +IRQn_Type getEXTIIRQn(int32_t m_pinoff) { + switch (m_pinoff) { + case GPIO_PIN_0: + return EXTI0_IRQn; + case GPIO_PIN_1: + return EXTI1_IRQn; + case GPIO_PIN_2: + return EXTI2_IRQn; + case GPIO_PIN_3: + return EXTI3_IRQn; + case GPIO_PIN_4: + return EXTI4_IRQn; + case GPIO_PIN_5: + case GPIO_PIN_6: + case GPIO_PIN_7: + case GPIO_PIN_8: + case GPIO_PIN_9: + return EXTI9_5_IRQn; + case GPIO_PIN_10: + case GPIO_PIN_11: + case GPIO_PIN_12: + case GPIO_PIN_13: + case GPIO_PIN_14: + case GPIO_PIN_15: + return EXTI15_10_IRQn; + default: + XS_ASSERT(0); + } + return EXTI0_IRQn; +} + +void xs_gpio_init_as_input(xs_gpio_t *gpio, Pin_t pin, xs_gpio_mode_t mode, xs_gpio_irq_t irqtype, bool mirror) { + if (pin == PinNull) return; + + gpio->mirror = mirror; + gpio->mode = mode; + gpio->irqtype = irqtype; + gpio->gpiotype = kxs_gpio_input; + + gpio->pin = pin; + gpio->gpio = _chip_get_gpio(pin); + gpio->pinoff = _chip_get_pinoff(pin); + + // kxs_gpio_nopull, // + // kxs_gpio_pullup, // + // kxs_gpio_pulldown, // + // kxs_gpio_od, + + uint32_t pulluptype = 0; + if (mode == kxs_gpio_nopull) { + pulluptype = GPIO_NOPULL; + } else if (mode == kxs_gpio_pullup) { + pulluptype = GPIO_PULLUP; + } else if (mode == kxs_gpio_pulldown) { + pulluptype = GPIO_PULLDOWN; + } + + gpio_enable_clock(gpio->gpio); + // kxs_gpio_no_irq, + // kxs_gpio_rising_irq, + // kxs_gpio_falling_irq, + // kxs_gpio_rising_and_falling_irq, + + GPIO_InitTypeDef init_type_def = {0}; + if (gpio->irqtype == kxs_gpio_no_irq) { + init_type_def.Pin = gpio->pinoff; + init_type_def.Mode = GPIO_MODE_INPUT; + init_type_def.Pull = pulluptype; + init_type_def.Speed = GPIO_SPEED_FREQ_LOW; + } else if (gpio->irqtype == kxs_gpio_rising_irq) { + init_type_def.Pin = gpio->pinoff; + init_type_def.Mode = gpio->mirror ? GPIO_MODE_IT_FALLING : GPIO_MODE_IT_RISING; + init_type_def.Pull = pulluptype; + init_type_def.Speed = GPIO_SPEED_FREQ_LOW; + } else if (gpio->irqtype == kxs_gpio_falling_irq) { + init_type_def.Pin = gpio->pinoff; + init_type_def.Mode = !gpio->mirror ? GPIO_MODE_IT_FALLING : GPIO_MODE_IT_RISING; + init_type_def.Pull = pulluptype; + init_type_def.Speed = GPIO_SPEED_FREQ_LOW; + } else if (gpio->irqtype == kxs_gpio_rising_and_falling_irq) { + init_type_def.Pin = gpio->pinoff; + init_type_def.Mode = GPIO_MODE_IT_RISING_FALLING; + init_type_def.Pull = pulluptype; + init_type_def.Speed = GPIO_SPEED_FREQ_LOW; + } + + HAL_GPIO_Init(gpio->gpio, &init_type_def); + if (gpio->irqtype != kxs_gpio_no_irq) { + HAL_NVIC_SetPriority(getEXTIIRQn(gpio->pinoff), PC_IRQ_PREEMPTPRIORITY_DEFAULT, 0); + HAL_NVIC_EnableIRQ(getEXTIIRQn(gpio->pinoff)); + } + + gpio->inited = true; + return; +} +void xs_gpio_init_as_output(xs_gpio_t *gpio, Pin_t pin, xs_gpio_mode_t mode, bool mirror, bool initLevel) { + if (pin == PinNull) return; + + gpio->mirror = mirror; + gpio->mode = mode; + gpio->irqtype = kxs_gpio_no_irq; + gpio->gpiotype = kxs_gpio_output; + gpio->pin = pin; + gpio->gpio = _chip_get_gpio(pin); + gpio->pinoff = _chip_get_pinoff(pin); + + gpio_enable_clock(gpio->gpio); + + GPIO_InitTypeDef init_type_def = {0}; + initLevel = gpio->mirror ? !initLevel : initLevel; + GPIO_PinState pinState = initLevel ? GPIO_PIN_SET : GPIO_PIN_RESET; + + HAL_GPIO_WritePin(gpio->gpio, gpio->pinoff, pinState); + + if (gpio->mode == kxs_gpio_nopull) { + init_type_def.Pin = gpio->pinoff; + init_type_def.Mode = GPIO_MODE_OUTPUT_PP; + init_type_def.Pull = GPIO_NOPULL; + init_type_def.Speed = GPIO_SPEED_FREQ_LOW; + } else if (gpio->mode == kxs_gpio_pullup) { + init_type_def.Pin = gpio->pinoff; + init_type_def.Mode = GPIO_MODE_OUTPUT_PP; + init_type_def.Pull = GPIO_PULLUP; + init_type_def.Speed = GPIO_SPEED_FREQ_LOW; + } else if (gpio->mode == kxs_gpio_pulldown) { + init_type_def.Pin = gpio->pinoff; + init_type_def.Mode = GPIO_MODE_OUTPUT_PP; + init_type_def.Pull = GPIO_PULLDOWN; + init_type_def.Speed = GPIO_SPEED_FREQ_LOW; + } else if (gpio->mode == kxs_gpio_od) { + init_type_def.Pin = gpio->pinoff; + init_type_def.Mode = GPIO_MODE_OUTPUT_OD; + init_type_def.Pull = 0; + init_type_def.Speed = GPIO_SPEED_FREQ_LOW; + } + HAL_GPIO_Init(gpio->gpio, &init_type_def); + gpio->inited = true; + return; +} +bool xs_gpio_read(xs_gpio_t *gpio) { + GPIO_PinState pinState = HAL_GPIO_ReadPin(gpio->gpio, gpio->pinoff); + return !gpio->mirror ? pinState == GPIO_PIN_SET : pinState != GPIO_PIN_SET; +} +void xs_gpio_write(xs_gpio_t *gpio, bool level) { + level = gpio->mirror ? !level : level; + GPIO_PinState pinState = level ? GPIO_PIN_SET : GPIO_PIN_RESET; + HAL_GPIO_WritePin(gpio->gpio, gpio->pinoff, pinState); +} + +void EXTI0_IRQHandler() { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); } +void EXTI1_IRQHandler() { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); } +void EXTI2_IRQHandler() { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); } +void EXTI3_IRQHandler() { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3); } +void EXTI4_IRQHandler() { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); } +void EXTI9_5_IRQHandler(void) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9); +} +void EXTI15_10_IRQHandler(void) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14); + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15); +} \ No newline at end of file diff --git a/xs_gpio.h b/xs_gpio.h new file mode 100644 index 0000000..1838062 --- /dev/null +++ b/xs_gpio.h @@ -0,0 +1,36 @@ +#pragma once +#include "pin.h" +#include "xs_basic.h" +#include "xs_log.h" + +typedef enum { + kxs_gpio_nopull, // + kxs_gpio_pullup, // + kxs_gpio_pulldown, // + kxs_gpio_od, // +} xs_gpio_mode_t; + +typedef enum { kxs_gpio_ain, kxs_gpio_input, kxs_gpio_output } xs_gpio_type_t; + +typedef enum { + kxs_gpio_no_irq, + kxs_gpio_rising_irq, + kxs_gpio_falling_irq, + kxs_gpio_rising_and_falling_irq, +} xs_gpio_irq_t; + +typedef struct { + Pin_t pin; + GPIO_TypeDef *gpio; + uint16_t pinoff; + xs_gpio_mode_t mode; + xs_gpio_type_t gpiotype; + xs_gpio_irq_t irqtype; + bool mirror; + bool inited; +} xs_gpio_t; + +void xs_gpio_init_as_input(xs_gpio_t *gpio, Pin_t pin, xs_gpio_mode_t mode, xs_gpio_irq_t irqtype, bool mirror); +void xs_gpio_init_as_output(xs_gpio_t *gpio, Pin_t pin, xs_gpio_mode_t mode, bool mirror, bool initLevel); +bool xs_gpio_read(xs_gpio_t *gpio); +void xs_gpio_write(xs_gpio_t *gpio, bool level); \ No newline at end of file diff --git a/xs_id.c b/xs_id.c new file mode 100644 index 0000000..cf60f72 --- /dev/null +++ b/xs_id.c @@ -0,0 +1,31 @@ +#include "xs_id.h" + +#include "main.h" +#include "rng.h" + +extern RNG_HandleTypeDef hrng; + +void xs_id_generate_random_mac(mac_t* id) { + id->mac[0] = 0x00; // 00 80 E1 是STM32的MAC地址前三位 + id->mac[1] = 0x80; + id->mac[2] = 0xE1; + + uint32_t random0 = 0; + uint32_t random1 = 0; + uint32_t random2 = 0; + HAL_RNG_GenerateRandomNumber(&hrng, &random0); + HAL_RNG_GenerateRandomNumber(&hrng, &random1); + HAL_RNG_GenerateRandomNumber(&hrng, &random2); + + id->mac[3] = random0 % 256; + id->mac[4] = random1 % 256; + id->mac[5] = random2 % 256; +} +void xs_id_get_cpu_id(cpu_id_t* id) { + // UID_BASE + uint8_t* uid_base = (uint8_t*)UID_BASE; + for (int32_t i = 0; i < 12; i++) { + id->id[i] = uid_base[i]; + } + return; +} \ No newline at end of file diff --git a/xs_id.h b/xs_id.h new file mode 100644 index 0000000..5d413e2 --- /dev/null +++ b/xs_id.h @@ -0,0 +1,12 @@ +#pragma once +#include +typedef struct { + uint8_t mac[6]; +} mac_t; + +typedef struct { + uint8_t id[12]; // 96bit +} cpu_id_t; + +void xs_id_generate_random_mac(mac_t* id); +void xs_id_get_cpu_id(cpu_id_t* id); diff --git a/xs_log.c b/xs_log.c new file mode 100644 index 0000000..b79c8fd --- /dev/null +++ b/xs_log.c @@ -0,0 +1,39 @@ +#include "xs_log.h" + +#include +#include +#include +#include +#include +bool g_xs_enable_log = true; +extern UART_HandleTypeDef PC_DEBUG_UART; +/********************************************************************* + * @fn _write + * + * @brief Support Printf Function + * + * @param *buf - UART send Data. + * size - Data length + * + * @return size: Data length + */ +__attribute__((used)) int _write(int fd, char* buf, int size) { + int i; + + for (i = 0; i < size; i++) { + uint8_t c = *buf++; + HAL_UART_Transmit(&PC_DEBUG_UART, &c, 1, 100); + } + + return size; +} + +void xs_log_enable(bool enable) { g_xs_enable_log = enable; } +void xs_log(const char* fmt, ...) { + if (g_xs_enable_log) { + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + } +} diff --git a/xs_log.h b/xs_log.h new file mode 100644 index 0000000..911d9f0 --- /dev/null +++ b/xs_log.h @@ -0,0 +1,43 @@ +#pragma once +#include "xs_basic.h" +#include "xs_delay.h" + +extern bool g_xs_enable_log; +#define XS_LOG_RELEASE(TAG, fmt, ...) \ + if (g_xs_enable_log) { \ + xs_log(TAG "" fmt "\n", ##__VA_ARGS__); \ + } +#define XS_LOGI(TAG, fmt, ...) \ + if (g_xs_enable_log) { \ + xs_log("%08lu INFO [%-8s] " fmt "\n", xs_get_ticket(), TAG, ##__VA_ARGS__); \ + } +#define XS_LOGD(TAG, fmt, ...) \ + if (g_xs_enable_log) { \ + xs_log("%08lu DEBU [%-8s] " fmt "\n", xs_get_ticket(), TAG, ##__VA_ARGS__); \ + } +#define XS_LOGE(TAG, fmt, ...) \ + if (g_xs_enable_log) { \ + xs_log("%08lu ERRO [%-8s] " fmt "\n", xs_get_ticket(), TAG, ##__VA_ARGS__); \ + } + +#define XS_LOGW(TAG, fmt, ...) \ + if (g_xs_enable_log) { \ + xs_log("%08lu WARN [%-8s] " fmt "\n", xs_get_ticket(), TAG, ##__VA_ARGS__); \ + } + +#define XS_ASSERT(cond) \ + if (!(cond)) { \ + while (1) { \ + xs_log("ASSERT: %s [%s:%d]\n", #cond, __FILE__, __LINE__); \ + xs_delay_ms(1000); \ + } \ + } + +#define ZLOGI(TAG, fmt, ...) XS_LOGI(TAG, fmt, ##__VA_ARGS__) +#define ZLOGD(TAG, fmt, ...) XS_LOGD(TAG, fmt, ##__VA_ARGS__) +#define ZLOGE(TAG, fmt, ...) XS_LOGE(TAG, fmt, ##__VA_ARGS__) +#define ZLOGW(TAG, fmt, ...) XS_LOGW(TAG, fmt, ##__VA_ARGS__) +#define ZASSERT(cond) XS_ASSERT(cond) + +void xs_log(const char* fmt, ...); +void xs_log_enable(bool enable); \ No newline at end of file diff --git a/xs_udp.c b/xs_udp.c new file mode 100644 index 0000000..651efcd --- /dev/null +++ b/xs_udp.c @@ -0,0 +1,103 @@ +#include "xs_udp.h" + +#include "xs_log.h" +#define TAG "xs_udp" + +#define UDP_DEFAULT_SEND_PORT 5000 + +#define SOCKET_DO(function) \ + do { \ + int ret = function; \ + if (ret) { \ + ZLOGE(TAG, "do %s fail", #function); \ + return false; \ + } \ + } while (0) + +static void udp_server_receive_thread(void const *argument) { // + udp_t *udp_handler = (udp_t *)argument; + ZLOGI(TAG, "udp server receive thread start: %s", udp_handler->name); + while (true) { + struct sockaddr_in sock; + socklen_t sock_len = sizeof(sock); + int recv_datalen = recvfrom(udp_handler->sock_fd, (char *)udp_handler->rxbuf, udp_handler->rxbuf_len, 0, (struct sockaddr *)&sock, &sock_len); + if (recv_datalen > 0) { + if (udp_handler->on_packet) udp_handler->on_packet(udp_handler, &sock, (uint8_t *)udp_handler->rxbuf, recv_datalen); + } + } +} + +bool xs_udp_init(udp_t *udp_handler, const char *name, uint16_t port, udp_on_packet_t on_packet, int32_t rxbuf_size, void *data) { + memset(udp_handler, 0, sizeof(udp_t)); + udp_handler->server.sin_family = AF_INET; + udp_handler->server.sin_addr.s_addr = inet_addr("0.0.0.0"); + udp_handler->server.sin_port = htons(port); + udp_handler->on_packet = on_packet; + udp_handler->data = data; + udp_handler->name = name; + if (rxbuf_size == 0) { + udp_handler->rxbuf_len = 1024; + } else { + udp_handler->rxbuf_len = rxbuf_size; + } + udp_handler->rxbuf = (char *)malloc(udp_handler->rxbuf_len); + ZASSERT(udp_handler->rxbuf != NULL); + + // 创建客户端用于通信的Socket + udp_handler->sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (udp_handler->sock_fd < 0) { + ZLOGE(TAG, "create socket fail"); + return false; + } + // 设置超时 + struct timeval tv = {0, 1000}; + SOCKET_DO(lwip_setsockopt(udp_handler->sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv))); + // 绑定 + SOCKET_DO(bind(udp_handler->sock_fd, (struct sockaddr *)&udp_handler->server, sizeof(udp_handler->server))); + + if (on_packet) { + // 创建接收线程 + osThreadDef(udp_server_rx_thread, udp_server_receive_thread, osPriorityBelowNormal, 0, 512); + udp_handler->rx_thread = osThreadCreate(osThread(udp_server_rx_thread), udp_handler); + ZASSERT(udp_handler->rx_thread != NULL); + } + return true; +} + +int xs_udp_send_message(udp_t *udp_handler, const char *ip, int port, const char *data, int len) { // + struct sockaddr_in sockaddr; + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr.s_addr = inet_addr(ip); + sockaddr.sin_port = htons(port); + return sendto(udp_handler->sock_fd, data, len, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); +} +int xs_udp_send_message2(udp_t *udp_handler, struct sockaddr_in *add, const char *data, int len) { // + return sendto(udp_handler->sock_fd, data, len, 0, (struct sockaddr *)add, sizeof(struct sockaddr_in)); +} + +bool xs_udp_broadcast_init(udp_broadcast_handler_t *udp_handler, uint16_t localport) { + memset(udp_handler, 0, sizeof(udp_broadcast_handler_t)); + udp_handler->server.sin_family = AF_INET; + udp_handler->server.sin_addr.s_addr = inet_addr("0.0.0.0"); + udp_handler->server.sin_port = htons(localport); + + // 创建客户端用于通信的Socket + udp_handler->sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (udp_handler->sock_fd < 0) { + ZLOGE(TAG, "create socket fail"); + return false; + } + // 设置超时 + struct timeval tv = {0, 1000}; + SOCKET_DO(lwip_setsockopt(udp_handler->sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv))); + // 绑定 + SOCKET_DO(bind(udp_handler->sock_fd, (struct sockaddr *)&udp_handler->server, sizeof(udp_handler->server))); + return true; +} +bool xs_udp_broadcast(udp_broadcast_handler_t *handler, uint32_t remoteport, uint8_t *data, size_t datalen) { + struct sockaddr_in sockaddr; + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); + sockaddr.sin_port = htons(remoteport); + return sendto(handler->sock_fd, data, datalen, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); +} diff --git a/xs_udp.h b/xs_udp.h new file mode 100644 index 0000000..f4351d0 --- /dev/null +++ b/xs_udp.h @@ -0,0 +1,40 @@ +#pragma once +#ifdef __cplusplus +extern "C" { +#endif +#include +#include + +#include "lwip/api.h" +#include "lwip/opt.h" +#include "lwip/sys.h" +#include "project_configs.h" + +typedef struct udp_s udp_t; +typedef void (*udp_on_packet_t)(udp_t *udp_handler, struct sockaddr_in *client, uint8_t *data, uint16_t len); +struct udp_s { + struct sockaddr_in server; + int sock_fd; + osThreadId rx_thread; + char *rxbuf; + int rxbuf_len; + udp_on_packet_t on_packet; + void *data; + const char *name; +}; + +typedef struct { + struct sockaddr_in server; + int sock_fd; +} udp_broadcast_handler_t; + +bool xs_udp_init(udp_t *udp_handler, const char *name, uint16_t port, udp_on_packet_t on_packet, int32_t rxbuf_size, void *data); +int xs_udp_send_message(udp_t *udp_handler, const char *remoteip, int remoteport, const char *data, int len); +int xs_udp_send_message2(udp_t *udp_handler, struct sockaddr_in *add, const char *data, int len); + +bool xs_udp_broadcast_init(udp_broadcast_handler_t *handler, uint16_t localport); +bool xs_udp_broadcast(udp_broadcast_handler_t *handler, uint32_t remoteport, uint8_t *data, size_t datalen); + +#ifdef __cplusplus +} +#endif