diff --git a/README.md b/README.md new file mode 100644 index 0000000..88b54cd --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +``` +chip: stm32hal库对接接口 +os : 操作系统相关方法,上层代码依赖这一层 +hal : 硬件抽象层,依赖chip层和os层 +components: +CHIP: +``` \ No newline at end of file diff --git a/chip/basic/base.hpp b/chip/basic/base.hpp new file mode 100644 index 0000000..521e743 --- /dev/null +++ b/chip/basic/base.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "basic_h/basic.hpp" +// +#include "cppdep.hpp" +// +#include "clock.hpp" +#include "logger.hpp" +// +#include "chip_helper.hpp" +// +#include "critical_context.hpp" \ No newline at end of file diff --git a/chip/basic/basic_h/basic.hpp b/chip/basic/basic_h/basic.hpp new file mode 100644 index 0000000..b46c7d8 --- /dev/null +++ b/chip/basic/basic_h/basic.hpp @@ -0,0 +1,8 @@ +#pragma once +#include +// +#include "project_configs.h" +// +#include "marco.h" +#include "pin.hpp" +#include "stm32_header.h" diff --git a/chip/basic/basic_h/marco.h b/chip/basic/basic_h/marco.h new file mode 100644 index 0000000..d5b9d78 --- /dev/null +++ b/chip/basic/basic_h/marco.h @@ -0,0 +1,45 @@ +#pragma once +#ifndef ZARRAY_SIZE +#define ZARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif +#define ZMAX(a, b) ((a) > (b) ? (a) : (b)) +#define ZMIN(a, b) ((a) < (b) ? (a) : (b)) + +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32768) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647 - 1) +#endif +#ifndef INT64_MIN +#define INT64_MIN (-9223372036854775807LL - 1) +#endif + +#ifndef INT8_MAX +#define INT8_MAX 127 +#endif +#ifndef INT16_MAX +#define INT16_MAX 32767 +#endif +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif +#ifndef INT64_MAX +#define INT64_MAX 9223372036854775807LL +#endif + +#ifndef UINT8_MAX +#define UINT8_MAX 255 +#endif +#ifndef UINT16_MAX +#define UINT16_MAX 65535 +#endif +#ifndef UINT32_MAX +#define UINT32_MAX 0xffffffffU /* 4294967295U */ +#endif +#ifndef UINT64_MAX +#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ +#endif \ No newline at end of file diff --git a/chip/basic/basic_h/pin.hpp b/chip/basic/basic_h/pin.hpp new file mode 100644 index 0000000..15242b4 --- /dev/null +++ b/chip/basic/basic_h/pin.hpp @@ -0,0 +1,117 @@ +#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; diff --git a/chip/basic/basic_h/stm32_header.h b/chip/basic/basic_h/stm32_header.h new file mode 100644 index 0000000..63f68b2 --- /dev/null +++ b/chip/basic/basic_h/stm32_header.h @@ -0,0 +1,120 @@ +#pragma once + +#include "main.h" + +#ifdef __STM32F4xx_HAL_H +#include "stm32f4xx.h" +#endif + +#ifdef HAL_CRYP_MODULE_ENABLED +#endif +#ifdef HAL_ADC_MODULE_ENABLED +#endif +#ifdef HAL_CAN_MODULE_ENABLED +#include "can.h" +#endif +#ifdef HAL_CRC_MODULE_ENABLED +#include "crc.h" +#endif +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED +#endif +#ifdef HAL_DAC_MODULE_ENABLED +#endif +#ifdef HAL_DCMI_MODULE_ENABLED +#endif +#ifdef HAL_DMA2D_MODULE_ENABLED +#endif +#ifdef HAL_ETH_MODULE_ENABLED +#endif +#ifdef HAL_NAND_MODULE_ENABLED +#endif +#ifdef HAL_NOR_MODULE_ENABLED +#endif +#ifdef HAL_PCCARD_MODULE_ENABLED +#endif +#ifdef HAL_SRAM_MODULE_ENABLED +#endif +#ifdef HAL_SDRAM_MODULE_ENABLED +#endif +#ifdef HAL_HASH_MODULE_ENABLED +#endif +#ifdef HAL_I2C_MODULE_ENABLED +#endif +#ifdef HAL_I2S_MODULE_ENABLED +#endif +#ifdef HAL_IWDG_MODULE_ENABLED +#endif +#ifdef HAL_LTDC_MODULE_ENABLED +#endif +#ifdef HAL_RNG_MODULE_ENABLED +#endif +#ifdef HAL_RTC_MODULE_ENABLED +#endif +#ifdef HAL_SAI_MODULE_ENABLED +#endif +#ifdef HAL_SD_MODULE_ENABLED +#endif +#ifdef HAL_MMC_MODULE_ENABLED +#endif +#ifdef HAL_SPI_MODULE_ENABLED +#include "spi.h" +#endif +#ifdef HAL_TIM_MODULE_ENABLED +#include "tim.h" +#endif +#ifdef HAL_UART_MODULE_ENABLED +#include "usart.h" +#endif +#ifdef HAL_USART_MODULE_ENABLED +#include "usart.h" +#endif +#ifdef HAL_IRDA_MODULE_ENABLED +#endif +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#endif +#ifdef HAL_SMBUS_MODULE_ENABLED +#endif +#ifdef HAL_WWDG_MODULE_ENABLED +#endif +#ifdef HAL_PCD_MODULE_ENABLED +#endif +#ifdef HAL_HCD_MODULE_ENABLED +#endif +#ifdef HAL_DSI_MODULE_ENABLED +#endif +#ifdef HAL_QSPI_MODULE_ENABLED +#endif +#ifdef HAL_QSPI_MODULE_ENABLED +#endif +#ifdef HAL_CEC_MODULE_ENABLED +#endif +#ifdef HAL_FMPI2C_MODULE_ENABLED +#endif +#ifdef HAL_FMPSMBUS_MODULE_ENABLED +#endif +#ifdef HAL_SPDIFRX_MODULE_ENABLED +#endif +#ifdef HAL_DFSDM_MODULE_ENABLED +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED +#endif +#ifdef HAL_GPIO_MODULE_ENABLED +#include "gpio.h" +#endif +#ifdef HAL_EXTI_MODULE_ENABLED +#endif +#ifdef HAL_DMA_MODULE_ENABLED +#endif +#ifdef HAL_RCC_MODULE_ENABLED +#endif +#ifdef HAL_FLASH_MODULE_ENABLED +#endif +#ifdef HAL_PWR_MODULE_ENABLED +#endif +#ifdef HAL_CORTEX_MODULE_ENABLED +#endif + +extern "C" { +typedef TIM_HandleTypeDef zchip_tim_t; +typedef UART_HandleTypeDef zchip_uart_t; +} \ No newline at end of file diff --git a/chip/basic/chip_helper.cpp b/chip/basic/chip_helper.cpp new file mode 100644 index 0000000..0d1db50 --- /dev/null +++ b/chip/basic/chip_helper.cpp @@ -0,0 +1,178 @@ +#include "chip_helper.hpp" + +extern "C" { +static uint8_t g_port_exit_critical_count; + +void chip_critical_enter(void) { + if (g_port_exit_critical_count == 0) { + __disable_irq(); + } + g_port_exit_critical_count++; +} +void chip_critical_exit(void) { + g_port_exit_critical_count--; + if (g_port_exit_critical_count == 0) { + __enable_irq(); + } +} + +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; +} +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; +} + +uint32_t chip_get_timer_clock_sorce_freq(TIM_HandleTypeDef* tim) { + uint32_t timClkFreq = 0; + uint32_t pclk1Freq = HAL_RCC_GetPCLK1Freq(); + uint32_t pclk2Freq = HAL_RCC_GetPCLK2Freq(); + uint32_t sysClkFreq = HAL_RCC_GetSysClockFreq(); + + uint32_t pFLatency; + RCC_ClkInitTypeDef clkconfig; + HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); + + bool isAPB2 = false; + +#ifdef TIM1 + if (tim->Instance == TIM1) isAPB2 = true; +#endif +#ifdef TIM8 + if (tim->Instance == TIM8) isAPB2 = true; +#endif +#ifdef TIM9 + if (tim->Instance == TIM9) isAPB2 = true; +#endif +#ifdef TIM10 + if (tim->Instance == TIM10) isAPB2 = true; +#endif +#ifdef TIM11 + if (tim->Instance == TIM11) isAPB2 = true; +#endif + if (isAPB2) { + if (clkconfig.APB2CLKDivider == RCC_HCLK_DIV1) { + timClkFreq = HAL_RCC_GetPCLK2Freq(); + } else { + timClkFreq = 2 * HAL_RCC_GetPCLK2Freq(); + } + } else { + if (clkconfig.APB1CLKDivider == RCC_HCLK_DIV1) { + timClkFreq = HAL_RCC_GetPCLK1Freq(); + } else { + timClkFreq = 2 * HAL_RCC_GetPCLK1Freq(); + } + } + return timClkFreq; +} +} + +bool chip_calculate_prescaler_and_autoreload_by_expect_freq(uint32_t timerInClk, float infreqhz, uint32_t* prescaler, uint32_t* autoreload) { + /** + * @brief 计算寄存器数值 + */ + float psc_x_arr = timerInClk / infreqhz; + uint32_t psc = 0; + uint32_t arr = 65534; + for (; arr > 2; arr--) { + psc = psc_x_arr / arr; + if (psc >= 1) { + uint32_t tmparr = psc_x_arr / psc; + if (tmparr >= 65534) continue; + break; + } + } + if (psc == 0) return false; + if (arr <= 3) return false; // 定时器一周期的分辨率太小了 + arr = psc_x_arr / psc; + + int psc_x_arr_real = arr * psc; + float realfreq = timerInClk / psc_x_arr_real; + + arr = arr - 1; + psc = psc - 1; + uint16_t comparevalue = 50 / 100.0 * arr; + + *prescaler = psc; + *autoreload = arr; + return true; +} diff --git a/chip/basic/chip_helper.hpp b/chip/basic/chip_helper.hpp new file mode 100644 index 0000000..aed5e64 --- /dev/null +++ b/chip/basic/chip_helper.hpp @@ -0,0 +1,17 @@ +#pragma once +#include + +#include "basic_h/basic.hpp" +// +#include "clock.hpp" + +extern "C" { +GPIO_TypeDef* chip_get_gpio(Pin_t pin); +uint16_t chip_get_pinoff(Pin_t pin); + +void chip_critical_enter(void); +void chip_critical_exit(void); + +uint32_t chip_get_timer_clock_sorce_freq(TIM_HandleTypeDef* tim); +bool chip_calculate_prescaler_and_autoreload_by_expect_freq(uint32_t timerInClk, float infreqhz, uint32_t* prescaler, uint32_t* autoreload); +} \ No newline at end of file diff --git a/chip/basic/clock.cpp b/chip/basic/clock.cpp new file mode 100644 index 0000000..6e2ada2 --- /dev/null +++ b/chip/basic/clock.cpp @@ -0,0 +1,41 @@ +#include "clock.hpp" +extern "C" { + +static zchip_tim_t* m_usdleaytim; + +uint32_t zchip_clock_init(zchip_clock_cfg_t* cfg) { + m_usdleaytim = cfg->usdleaytim; + return 0; +} +// +uint32_t zchip_clock_get_ticket(void) { return HAL_GetTick(); } +uint32_t zchip_clock_hasspassed(uint32_t ticket) { + uint32_t nowticket = HAL_GetTick(); + if (nowticket >= ticket) { + return nowticket - ticket; + } + return UINT32_MAX - ticket + nowticket; +} + +void __zchip_clock_early_delayus(uint32_t n) { + volatile uint32_t counter = 0; + __HAL_TIM_SET_COUNTER(m_usdleaytim, 0); + HAL_TIM_Base_Start(m_usdleaytim); + while (counter < n) { + counter = __HAL_TIM_GET_COUNTER(m_usdleaytim); + } + HAL_TIM_Base_Stop(m_usdleaytim); +} +void zchip_clock_early_delayus(uint32_t n) { + uint32_t us = n % 1000; + uint32_t ms = n / 1000; + if (us > 0) { + __zchip_clock_early_delayus(us); + } + for (uint32_t i = 0; i < ms; i++) { + __zchip_clock_early_delayus(1000); + } +} + + +} \ No newline at end of file diff --git a/chip/basic/clock.hpp b/chip/basic/clock.hpp new file mode 100644 index 0000000..8816d9f --- /dev/null +++ b/chip/basic/clock.hpp @@ -0,0 +1,19 @@ +#pragma once +#include + +#include "basic_h/basic.hpp" + +extern "C" { +// 微秒延迟定时器,注意该延时定时器需要按照以下文档进行配置 +// http://192.168.1.3:3000/zwikipedia/iflytop_wikipedia/src/branch/master/doc/stm32cubemx_us_timer.md + +typedef struct { + zchip_tim_t* usdleaytim; +} zchip_clock_cfg_t; + +uint32_t zchip_clock_init(zchip_clock_cfg_t* cfg); + +uint32_t zchip_clock_get_ticket(void); +uint32_t zchip_clock_hasspassed(uint32_t ticket); +void zchip_clock_early_delayus(uint32_t us); +} diff --git a/chip/basic/cppdep.hpp b/chip/basic/cppdep.hpp new file mode 100644 index 0000000..23604ad --- /dev/null +++ b/chip/basic/cppdep.hpp @@ -0,0 +1,3 @@ +#pragma once +#include +#include diff --git a/chip/basic/critical_context.cpp b/chip/basic/critical_context.cpp new file mode 100644 index 0000000..9c6b4ac --- /dev/null +++ b/chip/basic/critical_context.cpp @@ -0,0 +1,4 @@ +#include "critical_context.hpp" +using namespace iflytop; +CriticalContext::CriticalContext() { chip_critical_enter(); } +CriticalContext::~CriticalContext() { chip_critical_exit(); } \ No newline at end of file diff --git a/chip/basic/critical_context.hpp b/chip/basic/critical_context.hpp new file mode 100644 index 0000000..70b1a72 --- /dev/null +++ b/chip/basic/critical_context.hpp @@ -0,0 +1,15 @@ +#pragma once +#include "basic_h/basic.hpp" +#include "chip_helper.hpp" + +namespace iflytop { +using namespace std; + +class CriticalContext { + public: + CriticalContext(); + ~CriticalContext(); +}; +#define ZCriticalContext CriticalContext + +} // namespace iflytop \ No newline at end of file diff --git a/chip/basic/logger.cpp b/chip/basic/logger.cpp new file mode 100644 index 0000000..139cc36 --- /dev/null +++ b/chip/basic/logger.cpp @@ -0,0 +1,32 @@ +#include "logger.hpp" + + +extern "C" { + +/********************************************************************* + * @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++; + if (m_huart != NULL) HAL_UART_Transmit(m_huart, &c, 1, 100); + } + + return size; +} + +static zchip_uart_t* m_huart; +bool g_enable_log = true; + +void zchip_loggger_init(zchip_uart_t* huart) { m_huart = huart; } +void zchip_loggger_enable(bool enable) { g_enable_log = enable; } +} diff --git a/chip/basic/logger.hpp b/chip/basic/logger.hpp new file mode 100644 index 0000000..4e39a96 --- /dev/null +++ b/chip/basic/logger.hpp @@ -0,0 +1,37 @@ +#pragma once +#include + +#include "basic_h/basic.hpp" +// +#include "clock.hpp" + +extern "C" { +extern bool g_enable_log; +#define ZLOG_RELEASE(TAG, fmt, ...) \ + if (g_enable_log) { \ + printf(TAG "" fmt "\n", ##__VA_ARGS__); \ + } +#define ZLOGI(TAG, fmt, ...) \ + if (g_enable_log) { \ + printf("%08lu INFO [%-8s] " fmt "\n", chip_get_ticket(), TAG, ##__VA_ARGS__); \ + } +#define ZLOGD(TAG, fmt, ...) \ + if (g_enable_log) { \ + printf("%08lu DEBU [%-8s] " fmt "\n", chip_get_ticket(), TAG, ##__VA_ARGS__); \ + } +#define ZLOGE(TAG, fmt, ...) \ + if (g_enable_log) { \ + printf("%08lu ERRO [%-8s] " fmt "\n", chip_get_ticket(), TAG, ##__VA_ARGS__); \ + } + +#define ZASSERT(cond) \ + if (!(cond)) { \ + while (1) { \ + printf("ASSERT: %s [%s:%d]\n", #cond, __FILE__, __LINE__); \ + zchip_clock_early_delayus(1000 * 1000); \ + } \ + } + +void zchip_loggger_init(zchip_uart_t *huart); +void zchip_loggger_enable(bool enable); +} diff --git a/chip/chip.cpp b/chip/chip.cpp new file mode 100644 index 0000000..43f1c9b --- /dev/null +++ b/chip/chip.cpp @@ -0,0 +1,16 @@ +#include "chip.hpp" + +extern "C" { +void chip_init(chip_cfg_t *cfg) { + // + zchip_clock_cfg_t zchip_clock_cfg; + zchip_clock_cfg.usdleaytim = cfg->us_dleay_tim; + zchip_clock_init(&zchip_clock_cfg); + // + zchip_loggger_init(cfg->huart); + // + iflytop::ChipTimIrqShceduler::Cfg ChipTimIrqShceduler_cfg; + ChipTimIrqShceduler_cfg.schedulertim = cfg->tim_irq_scheduler_tim; + iflytop::ChipTimIrqShceduler::instance().initialize(&ChipTimIrqShceduler_cfg); +} +} \ No newline at end of file diff --git a/chip/chip.hpp b/chip/chip.hpp new file mode 100644 index 0000000..e1e2254 --- /dev/null +++ b/chip/chip.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "chip_tim_irq_shceduler.hpp" +#include "irq_dispatcher.hpp" +#include "zcan_irq_dispatcher.hpp" +#include "zgpio.hpp" +#include "ztim.hpp" +#include "zuart.hpp" + +extern "C" { + +typedef struct { + zchip_tim_t *us_dleay_tim; + zchip_tim_t *tim_irq_scheduler_tim; + zchip_uart_t *huart; +} chip_cfg_t; + +void chip_init(chip_cfg_t *cfg); +} \ No newline at end of file diff --git a/chip/chip_tim_irq_shceduler.cpp b/chip/chip_tim_irq_shceduler.cpp new file mode 100644 index 0000000..7ac5ed0 --- /dev/null +++ b/chip/chip_tim_irq_shceduler.cpp @@ -0,0 +1,64 @@ +#include "chip_tim_irq_shceduler.hpp" + +using namespace iflytop; +using namespace std; + +ChipTimIrqShceduler::ChipTimIrqShceduler(/* args */) {} +ChipTimIrqShceduler::~ChipTimIrqShceduler() {} + +ChipTimIrqShceduler& ChipTimIrqShceduler::instance() { + static ChipTimIrqShceduler instance; + return instance; +} +void ChipTimIrqShceduler::initialize(Cfg* cfg) { + m_cfg = *cfg; + m_htim = m_cfg.schedulertim; + + simpleTimer_startByPeriod(1000); +} +void ChipTimIrqShceduler::regPeriodJob(jobcb_t jobcb, uint32_t period_ms) { + ChipTimIrqShceduler::Job* periodJob = new ChipTimIrqShceduler::Job(jobcb, period_ms); + ZASSERT(periodJob != NULL); + m_periodJobs.push_back(periodJob); +} + +/******************************************************************************* + * simpleTimer * + *******************************************************************************/ +void ChipTimIrqShceduler::simpleTimer_startByPeriod(uint32_t periodus) { simpleTimer_startByFreq(1000000.0 / periodus); } +void ChipTimIrqShceduler::simpleTimer_startByFreq(float freq) { + ZASSERT(m_htim->Init.AutoReloadPreload == TIM_AUTORELOAD_PRELOAD_ENABLE) + + uint32_t prescaler = 0; + uint32_t autoreload = 0; + + ZASSERT(chip_calculate_prescaler_and_autoreload_by_expect_freq(chip_get_timer_clock_sorce_freq(m_htim), freq, &prescaler, &autoreload)); + + __HAL_TIM_SET_AUTORELOAD(m_htim, autoreload); + __HAL_TIM_SET_PRESCALER(m_htim, prescaler); + + HAL_TIM_Base_Start_IT(m_htim); + + ZIRQDispatcher::instance().regTimIrqListener([this](zchip_tim_t* tim) { + if (tim != m_htim) return; + onTimIrq(tim); + }); +} +void ChipTimIrqShceduler::simpleTimer_stop() { HAL_TIM_Base_Stop(m_htim); } + +void ChipTimIrqShceduler::onTimIrq(zchip_tim_t* tim) { + if (tim != m_cfg.schedulertim) { + return; + } + + ticket++; + for (auto iter = m_periodJobs.begin(); iter != m_periodJobs.end(); iter++) { + auto periodJob = *iter; + periodJob->count_ms++; + if (periodJob->count_ms != periodJob->period_ms) { + continue; + } + periodJob->count_ms = 0; + periodJob->jobcb(periodJob); + } +} \ No newline at end of file diff --git a/chip/chip_tim_irq_shceduler.hpp b/chip/chip_tim_irq_shceduler.hpp new file mode 100644 index 0000000..4d1c437 --- /dev/null +++ b/chip/chip_tim_irq_shceduler.hpp @@ -0,0 +1,58 @@ + +#pragma once +#include +#include + +#include "basic/base.hpp" +#include "irq_dispatcher.hpp" + +namespace iflytop { +using namespace std; + +class ChipTimIrqShceduler { + private: + ChipTimIrqShceduler(){}; + + public: + class Cfg { + public: + zchip_tim_t* schedulertim; + }; + class Job; + typedef function jobcb_t; + + class Job { + public: + Job(jobcb_t jobcb, uint32_t period_ms) { + this->jobcb = jobcb; + this->period_ms = period_ms; + } + jobcb_t jobcb; + uint32_t period_ms = 0; + uint32_t count_ms = 0; + }; + + private: + Cfg m_cfg; + zchip_tim_t* m_htim; + list m_periodJobs; + uint64_t ticket; + + volatile bool m_timer_start; + + public: + static ChipTimIrqShceduler& instance(); + + void initialize(Cfg* cfg); + void regPeriodJob(jobcb_t job, uint32_t period_ms); + ~ChipTimIrqShceduler(); + + private: + void onTimIrq(zchip_tim_t* tim); + + void simpleTimer_startByPeriod(uint32_t periodus); + void simpleTimer_startByFreq(float freq); + void simpleTimer_stop(); +}; + +} // namespace iflytop \ No newline at end of file diff --git a/chip/irq_dispatcher.cpp b/chip/irq_dispatcher.cpp new file mode 100644 index 0000000..caec7ac --- /dev/null +++ b/chip/irq_dispatcher.cpp @@ -0,0 +1,18 @@ +#include "irq_dispatcher.hpp" + +using namespace iflytop; +using namespace std; + +extern "C" { +void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) { ZIRQDispatcher::instance()._callOnTimIrq(htim); } +} + +ZIRQDispatcher &ZIRQDispatcher::instance() {} + +void ZIRQDispatcher::regTimIrqListener(ontimirq_t listener) { m_ontimirqs.push_back(listener); } + +void ZIRQDispatcher::_callOnTimIrq(zchip_tim_t *tim) { + for (auto &listener : m_ontimirqs) { + listener(tim); + } +} \ No newline at end of file diff --git a/chip/irq_dispatcher.hpp b/chip/irq_dispatcher.hpp new file mode 100644 index 0000000..66dc700 --- /dev/null +++ b/chip/irq_dispatcher.hpp @@ -0,0 +1,24 @@ +#pragma once +#include +#include + +#include "basic/base.hpp" + +namespace iflytop { +using namespace std; +class ZIRQDispatcher { + public: + typedef function ontimirq_t; + + list m_ontimirqs; + + public: + static ZIRQDispatcher &instance(); + + void regTimIrqListener(ontimirq_t listener); + + public: + void _callOnTimIrq(zchip_tim_t *tim); +}; + +} // namespace iflytop \ No newline at end of file diff --git a/chip/zcan_irq_dispatcher.cpp b/chip/zcan_irq_dispatcher.cpp new file mode 100644 index 0000000..4010e55 --- /dev/null +++ b/chip/zcan_irq_dispatcher.cpp @@ -0,0 +1,91 @@ +#include "zcan_irq_dispatcher.hpp" +#ifdef HAL_CAN_MODULE_ENABLED + +extern "C" { + +void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_TxMailbox0Complete(hcan); + } +} +void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_TxMailbox1Complete(hcan); + } +} +void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_TxMailbox2Complete(hcan); + } +} +void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_TxMailbox0Abort(hcan); + } +} +void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_TxMailbox1Abort(hcan); + } +} +void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_TxMailbox2Abort(hcan); + } +} +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_RxFifo0MsgPending(hcan); + } +} +void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_RxFifo0Full(hcan); + } +} +void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_RxFifo1MsgPending(hcan); + } +} +void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_RxFifo1Full(hcan); + } +} +void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_Sleep(hcan); + } +} +void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_WakeUpFromRxMsg(hcan); + } +} +void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) { + for (int i = 0; i < iflytop::ZCanIRQDispatcher::instance().m_listenerNum; i++) { + iflytop::ZCanIRQDispatcher::instance().m_listener[i]->STM32_HAL_onCAN_Error(hcan); + } +} +} + +using namespace iflytop; +void ZCanIRQDispatcher::regListener(ZCanIRQListener *listener) { + if (listener == NULL) return; + for (int i = 0; i < STM32_HAL_LISTENER_NUM; i++) { + if (m_listener[i] == NULL) { + m_listener[i] = listener; + m_listenerNum++; + return; + } + } + ZASSERT(0); +} + +ZCanIRQDispatcher &ZCanIRQDispatcher::instance() { + static ZCanIRQDispatcher instance; + return instance; +} + +#endif diff --git a/chip/zcan_irq_dispatcher.hpp b/chip/zcan_irq_dispatcher.hpp new file mode 100644 index 0000000..a5cb06d --- /dev/null +++ b/chip/zcan_irq_dispatcher.hpp @@ -0,0 +1,41 @@ +#pragma once +#include + +#include "basic/base.hpp" + +#define STM32_HAL_LISTENER_NUM 3 +namespace iflytop { +class ZCanIRQListener { + public: + /******************************************************************************* + * 涓柇绠$悊 * + *******************************************************************************/ +#ifdef HAL_CAN_MODULE_ENABLED + virtual void STM32_HAL_onCAN_TxMailbox0Complete(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_TxMailbox1Complete(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_TxMailbox2Complete(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_TxMailbox0Abort(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_TxMailbox1Abort(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_TxMailbox2Abort(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_RxFifo0MsgPending(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_RxFifo0Full(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_RxFifo1MsgPending(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_RxFifo1Full(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_Sleep(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_WakeUpFromRxMsg(CAN_HandleTypeDef *can){}; + virtual void STM32_HAL_onCAN_Error(CAN_HandleTypeDef *can){}; +#endif +}; + +class ZCanIRQDispatcher { + ZCanIRQDispatcher(){}; + + public: + ZCanIRQListener *m_listener[STM32_HAL_LISTENER_NUM]; + int m_listenerNum; + void regListener(ZCanIRQListener *listener); + + static ZCanIRQDispatcher &instance(); +}; + +} // namespace iflytop \ No newline at end of file diff --git a/chip/zgpio.cpp b/chip/zgpio.cpp new file mode 100644 index 0000000..90480a6 --- /dev/null +++ b/chip/zgpio.cpp @@ -0,0 +1,348 @@ + +#include "zgpio.hpp" +#define TAG "GPIO" +namespace iflytop { +/******************************************************************************* + * LISTENER * + *******************************************************************************/ + +static ZGPIO *s_irqGPIO[20]; +int s_irqGPIO_num = 0; + +extern "C" { +/** + * @brief This function handles EXTI line3 interrupt. + */ +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); +} +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { + for (int i = 0; i < s_irqGPIO_num; i++) { + s_irqGPIO[i]->tryTriggerIRQ(GPIO_Pin); + } +} +} + +void ZGPIO::regListener(onirq_t listener) { m_onirq = listener; } + +/******************************************************************************* + * GPIOIMPL * + *******************************************************************************/ + +/******************************************************************************* + * BASE_FUNC * + *******************************************************************************/ +bool ZGPIO::enableClock() { +#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; +} + + + + +void regIRQGPIO(ZGPIO *gpio) { + for (int i = 0; i < s_irqGPIO_num; i++) { + if (s_irqGPIO[i] == gpio) { + return; + } + } + + ZASSERT((s_irqGPIO_num + 1) < (int)ZARRAY_SIZE(s_irqGPIO)); + s_irqGPIO[s_irqGPIO_num] = gpio; + s_irqGPIO_num++; +} + +bool ZGPIO::isMirror() { return m_mirror; } +void ZGPIO::initAsInput(Pin_t pin, GPIOMode_t mode, GPIOIrqType_t irqtype, bool mirror) { + m_mirror = mirror; + m_mode = mode; + m_irqtype = irqtype; + m_gpiotype = kType_Input; + + m_gpio = chip_get_gpio(pin); + m_pinoff = chip_get_pinoff(pin); + + enableClock(); + GPIO_InitTypeDef m_GPIO_InitStruct = {0}; + if (m_irqtype == kIRQ_noIrq) { + m_GPIO_InitStruct.Pin = m_pinoff; + m_GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + m_GPIO_InitStruct.Pull = 0; + m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + } else if (m_irqtype == kIRQ_risingIrq) { + m_GPIO_InitStruct.Pin = m_pinoff; + m_GPIO_InitStruct.Mode = m_mirror ? GPIO_MODE_IT_FALLING : GPIO_MODE_IT_RISING; + m_GPIO_InitStruct.Pull = 0; + m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + } else if (m_irqtype == kIRQ_fallingIrq) { + m_GPIO_InitStruct.Pin = m_pinoff; + m_GPIO_InitStruct.Mode = !m_mirror ? GPIO_MODE_IT_FALLING : GPIO_MODE_IT_RISING; + m_GPIO_InitStruct.Pull = 0; + m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + } else if (m_irqtype == kIRQ_risingAndFallingIrq) { + m_GPIO_InitStruct.Pin = m_pinoff; + m_GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; + m_GPIO_InitStruct.Pull = 0; + m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + } + + HAL_GPIO_Init(m_gpio, &m_GPIO_InitStruct); + if (m_irqtype != kIRQ_noIrq) { + regIRQGPIO(this); + lastLevel = getState(); + HAL_NVIC_SetPriority(getEXTIIRQn(), 0, 0); + HAL_NVIC_EnableIRQ(getEXTIIRQn()); + } + return; +} +void ZGPIO::initAsOutput(Pin_t pin, GPIOMode_t mode, bool mirror, bool initLevel) { + m_mirror = mirror; + m_mode = mode; + m_irqtype = kIRQ_noIrq; + m_gpiotype = kType_Output; + + m_gpio = chip_get_gpio(pin); + m_pinoff = chip_get_pinoff(pin); + + enableClock(); + + GPIO_InitTypeDef m_GPIO_InitStruct = {0}; + initLevel = m_mirror ? !initLevel : initLevel; + GPIO_PinState pinState = initLevel ? GPIO_PIN_SET : GPIO_PIN_RESET; + + HAL_GPIO_WritePin(m_gpio, m_pinoff, pinState); + if (m_mode == kMode_nopull) { + m_GPIO_InitStruct.Pin = m_pinoff; + m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + m_GPIO_InitStruct.Pull = GPIO_NOPULL; + m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + } else if (m_mode == kMode_pullup) { + m_GPIO_InitStruct.Pin = m_pinoff; + m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + m_GPIO_InitStruct.Pull = GPIO_PULLUP; + m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + } else if (m_mode == kMode_pulldown) { + m_GPIO_InitStruct.Pin = m_pinoff; + m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + m_GPIO_InitStruct.Pull = GPIO_PULLDOWN; + m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + } else if (m_mode == kMode_od) { + m_GPIO_InitStruct.Pin = m_pinoff; + m_GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; + m_GPIO_InitStruct.Pull = 0; + m_GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + } + HAL_GPIO_Init(m_gpio, &m_GPIO_InitStruct); + return; +} +bool ZGPIO::isItRisingEXITGPIO() { return m_irqtype == kIRQ_risingIrq; } +bool ZGPIO::isItFallingEXITGPIO() { return m_irqtype == kIRQ_fallingIrq; } +bool ZGPIO::isItRisingAndItFallingEXITGPIO() { return m_irqtype == kIRQ_risingAndFallingIrq; } + +/******************************************************************************* + * EXT FUNC * + *******************************************************************************/ + +/** + * @brief 鍒ゆ柇褰撳墠鏄惁鏄繖涓紩鑴氫骇鐢熺殑涓柇 + * + * @param checkloop + * @param GPIO_Pin + * @return true + * @return false + * + * 鐢变簬STM32鐨凣PIO涓柇绾挎槸鍏辩敤鐨勶紝鎵浠ラ渶瑕佹牴鎹瓽PIO鐨勫嵆鏃剁姸鎬佸垽鏂槸鍚︽槸杩欎釜寮曡剼浜х敓鐨勪腑鏂? + * + * 鍒ゆ柇閫昏緫鏄?: + * 鍏堝垽鏂墍鏈変腑鏂ā寮忔槸 GPIO_MODE_IT_RISING 鍜? GPIO_MODE_IT_FALLING 鐨勫紩鑴氾紝閲囨牱褰撳墠鐢靛钩鍒ゆ柇鏄惁鏄繖涓紩鑴氫骇鐢熺殑涓柇 + * 鍐嶅垽鏂腑鏂ā寮忔槸 GPIO_MODE_IT_RISING_FALLING 鐨勫紩鑴氾紝鐩存帴杩斿洖true + */ +bool ZGPIO::tryTriggerIRQ(uint16_t GPIO_Pin) { + bool ret = false; + bool nostate = false; + if (GPIO_Pin != m_pinoff) return false; + if (!(isItRisingEXITGPIO() || isItFallingEXITGPIO() || isItRisingAndItFallingEXITGPIO())) { + return false; + } + + nostate = getState(); + + if (isItRisingEXITGPIO()) { + if (nostate) { + ret = true; + if (m_onirq) { + m_onirq(this, kRisingIrqEvent); + } + } + } else if (isItFallingEXITGPIO()) { + if (!nostate) { + ret = true; + if (m_onirq) { + m_onirq(this, kFallingIrqEvent); + } + } + } else { + if (lastLevel != nostate) { + ret = true; + if (m_onirq) { + if (lastLevel) + m_onirq(this, kRisingIrqEvent); + else + m_onirq(this, kFallingIrqEvent); + } + } + } + + lastLevel = nostate; + return ret; +} + +void ZGPIO::toggleState() { HAL_GPIO_TogglePin(m_gpio, m_pinoff); } +uint32_t ZGPIO::getStateUint32() { + if (getState()) + return 1; + else + return 0; +} + +bool ZGPIO::getState() { + bool ret = false; + if (HAL_GPIO_ReadPin(m_gpio, m_pinoff) == GPIO_PIN_SET) { + ret = true; + } else { + ret = false; + } + if (m_mirror) ret = !ret; + return ret; +} +bool ZGPIO::setState(bool state) { + if (m_mirror) state = !state; + if (state) { + HAL_GPIO_WritePin(m_gpio, m_pinoff, GPIO_PIN_SET); + } else { + HAL_GPIO_WritePin(m_gpio, m_pinoff, GPIO_PIN_RESET); + } + return true; +} +IRQn_Type ZGPIO::getEXTIIRQn() { + 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: + ZASSERT(0); + } + return EXTI0_IRQn; +} +/** + * @brief 鍒濆鍖朑PIO涓轰腑鏂ā寮? + * + * @param pull GPIO_NOPULL, GPIO_PULLUP, GPIO_PULLDOWN + * @param mode GPIO_MODE_IT_RISING, GPIO_MODE_IT_FALLING, GPIO_MODE_IT_RISING_FALLING + * @return true + * @return false + */ + +} // namespace iflytop diff --git a/chip/zgpio.hpp b/chip/zgpio.hpp new file mode 100644 index 0000000..866ceba --- /dev/null +++ b/chip/zgpio.hpp @@ -0,0 +1,74 @@ + +#pragma once +#include + +#include "basic/base.hpp" + +namespace iflytop { +using namespace std; + +#define STM32_GPIO_LISTENER_NUM 10 +class ZGPIO { + public: + typedef enum { + kRisingIrqEvent, + kFallingIrqEvent, + } IrqTypeEvent_t; + + typedef enum { + kMode_nopull, // + kMode_pullup, // + kMode_pulldown, // + kMode_od, // + } GPIOMode_t; + + typedef enum { kType_AIN, kType_Input, kType_Output } GPIOType_t; + + typedef enum { + kIRQ_noIrq, + kIRQ_risingIrq, + kIRQ_fallingIrq, + kIRQ_risingAndFallingIrq, + } GPIOIrqType_t; + + typedef function onirq_t; + + private: + GPIO_TypeDef *m_gpio; + uint16_t m_pinoff; + GPIOType_t m_gpiotype; + GPIOMode_t m_mode; + GPIOIrqType_t m_irqtype; + bool m_mirror; + bool lastLevel; + + onirq_t m_onirq; + + public: + ZGPIO(){}; + + void initAsInput(Pin_t pin, GPIOMode_t mode, GPIOIrqType_t irqtype, bool mirror); + void initAsOutput(Pin_t pin, GPIOMode_t mode, bool mirror, bool initLevel); + + void regListener(onirq_t listener); + + bool isMirror(); + bool isItRisingEXITGPIO(); + bool isItFallingEXITGPIO(); + bool isItRisingAndItFallingEXITGPIO(); + + bool getState(); + uint32_t getStateUint32(); + bool setState(bool state); + void toggleState(); + + IRQn_Type getEXTIIRQn(); + GPIO_TypeDef *getPort() { return m_gpio; } + uint16_t getPin() { return m_pinoff; } + + bool tryTriggerIRQ(uint16_t GPIO_Pin); + + private: + bool enableClock(); +}; +} // namespace iflytop \ No newline at end of file diff --git a/chip/ztim.cpp b/chip/ztim.cpp new file mode 100644 index 0000000..95d6d37 --- /dev/null +++ b/chip/ztim.cpp @@ -0,0 +1,48 @@ +#include "ztim.hpp" + +#include "irq_dispatcher.hpp" +using namespace iflytop; + +void ZTIM::initialize(zchip_tim_t *htim, mode_t mode) { + m_htim = htim; + m_mode = mode; +} +ZTIM::mode_t ZTIM::getMode() { return m_mode; } + +/****************************************************** + * kTimMode_timer * + ******************************************************/ + +/** + * @brief startTimer + * + * @param periodus 定时器周期 + * @param onirq 回调函数,如果为null,则使用上次注册的回调函数 + */ + +void ZTIM::simpleTimer_startByPeriod(uint32_t periodus) { simpleTimer_startByFreq(1000000.0 / periodus); } +void ZTIM::simpleTimer_startByFreq(float freq) { + ZASSERT(m_htim->Init.AutoReloadPreload == TIM_AUTORELOAD_PRELOAD_ENABLE) + m_timer_start = true; + + uint32_t prescaler = 0; + uint32_t autoreload = 0; + + uint32_t timClkFreq = chip_get_timer_clock_sorce_freq(m_htim); + + ZASSERT(chip_calculate_prescaler_and_autoreload_by_expect_freq(timClkFreq, freq, &prescaler, &autoreload)); + + __HAL_TIM_SET_AUTORELOAD(m_htim, autoreload); + __HAL_TIM_SET_PRESCALER(m_htim, prescaler); + + HAL_TIM_Base_Start_IT(m_htim); + + ZIRQDispatcher::instance().regTimIrqListener([this](zchip_tim_t *tim) { + if (tim != m_htim) return; + if (m_timer_start && m_simpleTimer_cb) m_simpleTimer_cb(); + }); +} +void ZTIM::simpleTimer_stop() { + m_timer_start = false; + HAL_TIM_Base_Stop(m_htim); +} diff --git a/chip/ztim.hpp b/chip/ztim.hpp new file mode 100644 index 0000000..f96cf90 --- /dev/null +++ b/chip/ztim.hpp @@ -0,0 +1,62 @@ + +#pragma once +#include + +#include "basic/base.hpp" + +#ifdef HAL_TIM_MODULE_ENABLED + +namespace iflytop { +using namespace iflytop; +class ZTIM { + public: + typedef enum { + ktm_null, + ktm_timer, + ktm_pwm, + } mode_t; + + typedef function ontimirq_t; + + private: + zchip_tim_t *m_htim; + mode_t m_mode; + + volatile bool m_timer_start; + + ontimirq_t m_simpleTimer_cb; + + public: + ZTIM() {} + + void initialize(zchip_tim_t *htim, mode_t mode); + mode_t getMode(); + + /****************************************************** + * kTimMode_timer * + ******************************************************/ + + /** + * @brief startTimer + * + * @param periodus 定时器周期 + * @param onirq 回调函数,如果为null,则使用上次注册的回调函数 + */ + + void simpleTimer_regCb(ontimirq_t cb) { m_simpleTimer_cb = cb; } + void simpleTimer_startByPeriod(uint32_t periodus); + void simpleTimer_startByFreq(float freq); + void simpleTimer_stop(); + + /******************************************************************************* + * PWM_MODE * + *******************************************************************************/ + void setPWMFreq(float freq); + void startPWM(uint32_t Channel, float duty); + void stopPWM(uint32_t Channel); + +}; + +} // namespace iflytop + +#endif \ No newline at end of file diff --git a/chip/zuart.cpp b/chip/zuart.cpp new file mode 100644 index 0000000..5ef4c6c --- /dev/null +++ b/chip/zuart.cpp @@ -0,0 +1,220 @@ +#include "zuart.hpp" + +#include +#include + +using namespace iflytop; + +static ZUART *s_uart_table[10]; +static int s_numUart; + +static void prv_reg_uart(ZUART *uart) { + if (s_numUart < 10) { + s_uart_table[s_numUart++] = uart; + } +} + +ZUART *prv_find_uart(UART_HandleTypeDef *huart) { + for (int i = 0; i < s_numUart; i++) { + if (s_uart_table[i]->getHuart() == huart) { + return s_uart_table[i]; + } + } + return NULL; +} + +extern "C" { +void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { + ZUART *stm32uart = prv_find_uart(huart); + if (stm32uart != NULL) stm32uart->HAL_UART_TxCpltCallback(); +} +void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) { + ZUART *stm32uart = prv_find_uart(huart); + if (stm32uart != NULL) stm32uart->HAL_UART_TxHalfCpltCallback(); +} +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { + ZUART *stm32uart = prv_find_uart(huart); + if (stm32uart != NULL) stm32uart->HAL_UART_RxCpltCallback(); +} +void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) { + ZUART *stm32uart = prv_find_uart(huart); + if (stm32uart != NULL) stm32uart->HAL_UART_RxHalfCpltCallback(); +} +void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { + ZUART *stm32uart = prv_find_uart(huart); + if (stm32uart != NULL) stm32uart->HAL_UART_ErrorCallback(); +} +void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart) { + ZUART *stm32uart = prv_find_uart(huart); + if (stm32uart != NULL) stm32uart->HAL_UART_AbortCpltCallback(); +} +void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart) { + ZUART *stm32uart = prv_find_uart(huart); + if (stm32uart != NULL) stm32uart->HAL_UART_AbortTransmitCpltCallback(); +} +void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart) { + ZUART *stm32uart = prv_find_uart(huart); + if (stm32uart != NULL) stm32uart->HAL_UART_AbortReceiveCpltCallback(); +} +} + +IRQn_Type ZUART::getUartIRQType() { +#ifdef USART1 + if (m_huart->Instance == USART1) { + return USART1_IRQn; + } +#endif +#ifdef USART2 + if (m_huart->Instance == USART2) { + return USART2_IRQn; + } +#endif +#ifdef USART3 + if (m_huart->Instance == USART3) { + return USART3_IRQn; + } +#endif +#ifdef UART4 + if (m_huart->Instance == UART4) { + return UART4_IRQn; + } +#endif +#ifdef UART5 + if (m_huart->Instance == UART5) { + return UART5_IRQn; + } +#endif +#ifdef USART6 + if (m_huart->Instance == USART6) { + return USART6_IRQn; + } +#endif + ZASSERT(false); + return USART1_IRQn; +} + +void ZUART::initialize(cfg_t *cfg, callback_t cb) { + m_name = cfg->name; + m_huart = cfg->huart; + m_cb = cb; + m_rxovertime_ms = cfg->rxovertime_ms; + + m_rxBuffer = (uint8_t *)malloc(cfg->rxbuffersize); + memset(m_rxBuffer, 0, cfg->rxbuffersize); + ZASSERT(m_rxBuffer != NULL); + m_rxBufferLen = cfg->rxbuffersize; + + m_isRxing = false; + m_dataIsReady = false; + m_rxBufferPos = 0; + m_lastRxTime = 0; + onebyte = 0; + + ChipTimIrqShceduler::instance().regPeriodJob([this](ChipTimIrqShceduler::Job *job) { periodicJob(); }, 1); + prv_reg_uart(this); +} +void ZUART::initialize(cfg_t *cfg) { initialize(cfg, NULL); } + +bool ZUART::tx(uint8_t *data, size_t len) { + HAL_UART_Transmit(m_huart, data, len, 0xffff); + return true; +} +bool ZUART::tx(const char *data) { + HAL_UART_Transmit(m_huart, (uint8_t *)data, strlen(data), 0xffff); + return true; +} + +bool ZUART::startRxIt() { + ZASSERT(m_rxBuffer != NULL); + ZASSERT(NVIC_GetEnableIRQ(getUartIRQType()) != 0); + + if (m_isRxing) return true; + m_isRxing = true; + + HAL_UART_Receive_IT(m_huart, &onebyte, 1); + + return true; +} + +bool ZUART::dataIsReady() { + // CriticalContext criticalContext; + if (m_dataIsReady) { + return true; + } + if (!m_dataIsReady && m_rxBufferPos != 0) { + if (zchip_clock_hasspassed(m_lastRxTime) > (uint32_t)m_rxovertime_ms) { + m_dataIsReady = true; + return true; + } + } + return false; +} +void ZUART::clearRxData() { + // ZCriticalContext criticalContext; + m_dataIsReady = false; + memset(m_rxBuffer, 0, m_rxBufferLen); + m_rxBufferPos = 0; +} +void ZUART::periodicJob() { + if (dataIsReady()) { + if (m_cb) { + m_cb(m_rxBuffer, m_rxBufferPos); + } + clearRxData(); + } +} + +void ZUART::forceCchedule() { periodicJob(); } + +/******************************************************************************* + * 涓柇 * + *******************************************************************************/ +void ZUART::HAL_UART_TxCpltCallback() {} +void ZUART::HAL_UART_TxHalfCpltCallback() {} +void ZUART::HAL_UART_RxCpltCallback() { + if (m_dataIsReady) { + HAL_UART_Receive_IT(m_huart, &onebyte, 1); + return; + } + + m_rxBuffer[m_rxBufferPos] = onebyte; + m_rxBufferPos++; + m_lastRxTime = zchip_clock_get_ticket(); + + if (m_rxBufferPos >= m_rxBufferLen) { + m_dataIsReady = true; + } + HAL_UART_Receive_IT(m_huart, &onebyte, 1); +} + +void ZUART::HAL_UART_RxHalfCpltCallback() {} +void ZUART::HAL_UART_ErrorCallback() { + HAL_UART_AbortReceive_IT(m_huart); + HAL_UART_Receive_IT(m_huart, &onebyte, 1); +} +void ZUART::HAL_UART_AbortCpltCallback() {} +void ZUART::HAL_UART_AbortTransmitCpltCallback() {} +void ZUART::HAL_UART_AbortReceiveCpltCallback() {} + +namespace iflytop { +#if 0 +#ifdef USART1 +ZUART STM32_UART1("uart1", USART1); +#endif +#ifdef USART2 +ZUART STM32_UART2("uart2", USART2); +#endif +#ifdef USART3 +ZUART STM32_UART3("uart3", USART3); +#endif +#ifdef UART4 +ZUART STM32_UART4("uart4", UART4); +#endif +#ifdef UART5 +ZUART STM32_UART5("uart5", UART5); +#endif +#ifdef USART6 +ZUART STM32_UART6("uart6", USART6); +#endif +#endif +} // namespace iflytop diff --git a/chip/zuart.hpp b/chip/zuart.hpp new file mode 100644 index 0000000..e7a0125 --- /dev/null +++ b/chip/zuart.hpp @@ -0,0 +1,69 @@ +#pragma once +#include + +#include "basic/base.hpp" +#include "chip_tim_irq_shceduler.hpp" +namespace iflytop { +using namespace std; +class ZUART { + public: + typedef struct { + const char *name; + UART_HandleTypeDef *huart; + int32_t rxbuffersize = 128; + int32_t rxovertime_ms = 3; + } cfg_t; + typedef function callback_t; + + private: + const char *m_name; + UART_HandleTypeDef *m_huart; + + uint8_t *m_rxBuffer; + volatile int32_t m_rxBufferPos; + int32_t m_rxBufferLen; + + volatile uint32_t m_lastRxTime; + + int32_t m_rxovertime_ms = 3; + + uint8_t onebyte; + + bool m_isRxing = false; + volatile bool m_dataIsReady = false; + + callback_t m_cb; + + public: + ZUART() {} + void initialize(cfg_t *cfg, callback_t cb); + void initialize(cfg_t *cfg); + + void setrxcb(callback_t cb) { m_cb = cb; } + + bool tx(const char *data); + bool tx(uint8_t *data, size_t len); + bool startRxIt(); + + void clearRxData(); + void forceCchedule(); + + public: + void HAL_UART_TxCpltCallback(); + void HAL_UART_TxHalfCpltCallback(); + void HAL_UART_RxCpltCallback(); + void HAL_UART_RxHalfCpltCallback(); + void HAL_UART_ErrorCallback(); + void HAL_UART_AbortCpltCallback(); + void HAL_UART_AbortTransmitCpltCallback(); + void HAL_UART_AbortReceiveCpltCallback(); + + UART_HandleTypeDef *getHuart() { return m_huart; } + + private: + IRQn_Type getUartIRQType(); + bool dataIsReady(); + void periodicJob(); +}; + +} // namespace iflytop \ No newline at end of file diff --git a/os/README.md b/os/README.md new file mode 100644 index 0000000..4735978 --- /dev/null +++ b/os/README.md @@ -0,0 +1,13 @@ +``` +DEP: + + dealy +------------------------------------------------------------------------ + logger +------------------------------------------------------------------------ + mutex +------------------------------------------------------------------------ + os +------------------------------------------------------------------------ + +``` \ No newline at end of file diff --git a/os/delay.cpp b/os/delay.cpp new file mode 100644 index 0000000..98905fd --- /dev/null +++ b/os/delay.cpp @@ -0,0 +1,19 @@ +#include "delay.hpp" + +#ifdef IFLYTOP_ENABLE_OS +#include "cmsis_os.h" +#endif + +extern "C" { +void zos_early_delayus(int var_nus) { zchip_clock_early_delayus(var_nus); } +void zos_early_delay(int ms) { + for (int i = 0; i < ms; i++) { + zos_early_delayus(1000); + } +} +#ifdef IFLYTOP_ENABLE_OS +void zos_delay(int ms) { osDelay(ms); } +#else +void zos_delay(int ms) { z_early_delay(ms); } +#endif +} diff --git a/os/delay.hpp b/os/delay.hpp new file mode 100644 index 0000000..84c0ba8 --- /dev/null +++ b/os/delay.hpp @@ -0,0 +1,7 @@ +#pragma once +#include "osbasic_h.hpp" +extern "C" { +void zos_early_delay(int ms); +void zos_early_delayus(int us); +void zos_delay(int ms); +} diff --git a/os/mutex.cpp b/os/mutex.cpp new file mode 100644 index 0000000..0a418bd --- /dev/null +++ b/os/mutex.cpp @@ -0,0 +1,53 @@ +#include "mutex.hpp" +#define TAG "zmutex" + +using namespace iflytop; + +/******************************************************************************* + * zmutex * + *******************************************************************************/ +zmutex::zmutex() {} +zmutex::~zmutex() { +#ifdef IFLYTOP_ENABLE_OS + vSemaphoreDelete(recursiveMutex); +#endif +} + +void zmutex::init() { +#ifdef IFLYTOP_ENABLE_OS + recursiveMutex = xSemaphoreCreateRecursiveMutex(); +#endif +} + +bool zmutex::isInit() { +#ifdef IFLYTOP_ENABLE_OS + return recursiveMutex != NULL; +#else + return true; +#endif +} + +void zmutex::lock() { +#ifdef IFLYTOP_ENABLE_OS + ZASSERT(recursiveMutex != NULL); + xSemaphoreTakeRecursive(recursiveMutex, portMAX_DELAY); +#else + chip_critical_enter(); +#endif +} +void zmutex::unlock() { +#ifdef IFLYTOP_ENABLE_OS + xSemaphoreGiveRecursive(recursiveMutex); +#else + chip_critical_exit(); +#endif +} + +/******************************************************************************* + * zlock_guard * + *******************************************************************************/ +zlock_guard::zlock_guard(zmutex* mutex) { + m_mutex = mutex; + m_mutex->lock(); +} +zlock_guard::~zlock_guard() { m_mutex->unlock(); } diff --git a/os/mutex.hpp b/os/mutex.hpp new file mode 100644 index 0000000..962403c --- /dev/null +++ b/os/mutex.hpp @@ -0,0 +1,36 @@ +#pragma once +#include "osbasic_h.hpp" +namespace iflytop { +using namespace std; + +class zmutex { + public: +#ifdef IFLYTOP_ENABLE_OS + SemaphoreHandle_t recursiveMutex; +#endif + + public: + zmutex(); + ~zmutex(); + + void init(); + bool isInit(); + + void lock(); + void unlock(); +}; + +class zlock_guard { + zmutex* m_mutex; + zlock_guard(zmutex* mutex); + ~zlock_guard(); +}; + +class CriticalContext { + public: + CriticalContext(); + ~CriticalContext(); +}; +#define ZCriticalContext CriticalContext + +} // namespace iflytop \ No newline at end of file diff --git a/os/osbasic_h.hpp b/os/osbasic_h.hpp new file mode 100644 index 0000000..5df3a0c --- /dev/null +++ b/os/osbasic_h.hpp @@ -0,0 +1,6 @@ +#pragma once +#include "../chip/chip.hpp" +// +#ifdef IFLYTOP_ENABLE_OS +#include "cmsis_os.h" +#endif \ No newline at end of file diff --git a/os/ticket.cpp b/os/ticket.cpp new file mode 100644 index 0000000..fd5831c --- /dev/null +++ b/os/ticket.cpp @@ -0,0 +1,11 @@ +#include "ticket.hpp" + +extern "C" { +uint32_t zos_get_tick(void) { +#ifdef IFLYTOP_ENABLE_OS + return osKernelSysTick(); +#else + return HAL_GetTick(); +#endif +} +} \ No newline at end of file diff --git a/os/ticket.hpp b/os/ticket.hpp new file mode 100644 index 0000000..a0392c2 --- /dev/null +++ b/os/ticket.hpp @@ -0,0 +1,7 @@ +#pragma once +#include "osbasic_h.hpp" + +extern "C" { +uint32_t zos_get_tick(void); +uint32_t zos_haspassedms(uint32_t ticket); +} \ No newline at end of file diff --git a/os/zos.cpp b/os/zos.cpp new file mode 100644 index 0000000..d31d084 --- /dev/null +++ b/os/zos.cpp @@ -0,0 +1,4 @@ +#include "zos.hpp" +extern "C" { +void zos_init(zos_cfg_t* cfg) {} +} \ No newline at end of file diff --git a/os/zos.hpp b/os/zos.hpp new file mode 100644 index 0000000..31e47c6 --- /dev/null +++ b/os/zos.hpp @@ -0,0 +1,19 @@ +#pragma once +// +#include "osbasic_h.hpp" +// +#include "oscppdep.hpp" +// +#include "delay.hpp" +// +#include "mutex.hpp" +// +#include "ticket.hpp" + +extern "C" { +typedef struct { + uint32_t __reserved0; +} zos_cfg_t; + +void zos_init(zos_cfg_t* cfg); +} \ No newline at end of file