rt-thread硬件定时驱动(裸机版)

前言

  1. 本次驱动是在stm32f407zgt6芯片上进行测试.
  2. 驱动是根据rt-thread里面的组件和硬件驱动进行改写。

驱动代码

通用宏定义(bsp.h)

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 24-8-2     shchl   first version
 */

#ifndef THREADX_F407ZGT6_BSP_H
#define THREADX_F407ZGT6_BSP_H

#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stm32f4xx_hal.h>


#include "bsp_clk.h"
#include "bsp_gpio.h"
#include "bsp_uart_fifo.h"
#include "bsp_hwtimer.h"

#if 0
#define BSP_DEF_CRITICAL_SECTION
#define BSP_ENTER_CRITICAL __set_PRIMASK(1)	/* 禁止全局中断 */
#define BSP_EXIT_CRITICAL __set_PRIMASK(0)	/* 使能全局中断 */
#else

#include "tx_api.h"

#define BSP_DEF_CRITICAL_SECTION TX_INTERRUPT_SAVE_AREA
#define BSP_ENTER_CRITICAL       TX_DISABLE    /* 禁止全局中断 */
#define BSP_EXIT_CRITICAL        TX_RESTORE    /* 使能全局中断 */
#endif
enum {
    BSP_OK = 0,
    BSP_ERROR = 1,
    BSP_BUSY = 2,
    BSP_TIMEOUT = 3,
} ;


void bsp_init(void);

void Error_Handler(void);

#endif //THREADX_F407ZGT6_BSP_H

hwtimer组件部分

头文件

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 24-8-4     shchl   first version
 */

#ifndef THREADX_F407ZGT6_HWTIMER_H
#define THREADX_F407ZGT6_HWTIMER_H
struct rt_hwtimer_device;
/* Timer Control Command */
typedef enum {
    HWTIMER_CTRL_FREQ_SET,           /* set the count frequency */
    HWTIMER_CTRL_STOP,               /* stop timer */
    HWTIMER_CTRL_INFO_GET,           /* get a timer feature information */
    HWTIMER_CTRL_MODE_SET            /* Setting the timing mode(oneshot/period) */
} rt_hwtimer_ctrl_t;

/* Timing Mode */
typedef enum {
    HWTIMER_MODE_ONESHOT = 0x01,
    HWTIMER_MODE_PERIOD
} rt_hwtimer_mode_t;

/* Time Value */
typedef struct rt_hwtimerval {
    int32_t sec;      /* second */
    int32_t usec;     /* microsecond */
} rt_hwtimerval_t;

#define HWTIMER_CNTMODE_UP      0x01 /* increment count mode */
#define HWTIMER_CNTMODE_DW      0x02 /* decreasing count mode */
/* Timer Feature Information */
struct rt_hwtimer_info {
    int32_t maxfreq;    /* the maximum count frequency timer support */
    int32_t minfreq;    /* the minimum count frequency timer support */
    uint32_t maxcnt;    /* counter maximum value */
    uint8_t cntmode;   /* count mode (inc/dec) */
};

struct rt_hwtimer_ops {
    void (*init)(struct rt_hwtimer_device *timer, uint32_t state);

    int8_t (*start)(struct rt_hwtimer_device *timer, uint32_t cnt, rt_hwtimer_mode_t mode);

    void (*stop)(struct rt_hwtimer_device *timer);

    uint32_t (*count_get)(struct rt_hwtimer_device *timer);

    int8_t (*control)(struct rt_hwtimer_device *timer, uint32_t cmd, void *args);
};

typedef struct rt_hwtimer_device {
    const struct rt_hwtimer_ops *ops;
    const struct rt_hwtimer_info *info;
    int32_t freq;                /* counting frequency set by the user */
    int32_t overflow;            /* timer overflows */
    float period_sec;
    int32_t cycles;              /* how many times will generate a timeout event after overflow */
    int32_t reload;              /* reload cycles(using in period mode) */
    rt_hwtimer_mode_t mode;         /* timing mode(oneshot/period) */

    int8_t (*rx_indicate)(struct rt_hwtimer_device *dev);
    void *user_data;
} rt_hwtimer_t;

int8_t rt_hwtimer_init(rt_hwtimer_t *timer);

int8_t rt_hwtimer_open(rt_hwtimer_t *timer);

int8_t rt_hwtimer_close(rt_hwtimer_t *timer);

size_t rt_hwtimer_read(rt_hwtimer_t *timer, rt_hwtimerval_t *buffer);

size_t rt_hwtimer_write(rt_hwtimer_t *timer, rt_hwtimerval_t *buffer);

int8_t rt_hwtimer_control(rt_hwtimer_t *timer, int cmd, void *args);

void rt_device_hwtimer_isr(rt_hwtimer_t *timer);
int8_t rt_device_hwtimer_init(rt_hwtimer_t *timer, const char *name, void *user_data);

rt_hwtimer_t *rt_hwtimer_get_device(const char *name);
#endif //THREADX_F407ZGT6_HWTIMER_H

源文件

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 24-8-4     shchl   first version
 */
#include "bsp.h"
#include "hwtimer.h"

static uint32_t timeout_calc(rt_hwtimer_t *timer, rt_hwtimerval_t *tv) {
    float overflow;
    float timeout;
    uint32_t counter;
    int i, index = 0;
    float tv_sec;
    float devi_min = 1;
    float devi;

/* changed to second */
    overflow = timer->info->maxcnt / (float) timer->freq;
    tv_sec = tv->sec + tv->usec / (float) 1000000;

    if (tv_sec < (1 / (float) timer->freq)) {
/* little timeout */
        i = 0;
        timeout = 1 / (float) timer->freq;
    } else {
        for (i = 1; i > 0; i++) {
            timeout = tv_sec / i;

            if (timeout <= overflow) {
                counter = (uint32_t) (timeout * timer->freq);
                devi = tv_sec - (counter / (float) timer->freq) * i;
/* Minimum calculation error */
                if (devi > devi_min) {
                    i = index;
                    timeout = tv_sec / i;
                    break;
                } else if (devi == 0) {
                    break;
                } else if (devi < devi_min) {
                    devi_min = devi;
                    index = i;
                }
            }
        }
    }

    timer->cycles = i;
    timer->reload = i;
    timer->period_sec = timeout;
    counter = (uint32_t) (timeout * timer->freq);

    return counter;
}

int8_t rt_hwtimer_init(rt_hwtimer_t *timer) {
    int8_t result = 0;
    /* try to change to 1MHz */
    if ((1000000 <= timer->info->maxfreq) && (1000000 >= timer->info->minfreq)) {
        timer->freq = 1000000;
    } else {
        timer->freq = timer->info->minfreq;
    }
    timer->mode = HWTIMER_MODE_ONESHOT;
    timer->cycles = 0;
    timer->overflow = 0;

    if (timer->ops->init) {
        timer->ops->init(timer, 1);
    } else {
        result = -1;
    }

    return result;
}

int8_t rt_hwtimer_open(rt_hwtimer_t *timer) {
    int8_t result = 0;

    if (timer->ops->control != NULL) {
        timer->ops->control(timer, HWTIMER_CTRL_FREQ_SET, &timer->freq);
    } else {
        result = -1;
    }

    return result;
}

int8_t rt_hwtimer_close(rt_hwtimer_t *timer) {
    int8_t result = 0;
    if (timer->ops->init != NULL) {
        timer->ops->init(timer, 0);
    } else {
        result = -1;
    }

    timer->rx_indicate = NULL;

    return result;
}


size_t rt_hwtimer_read(rt_hwtimer_t *timer, rt_hwtimerval_t *buffer) {
    rt_hwtimerval_t tv;
    uint32_t cnt;
    BSP_DEF_CRITICAL_SECTION;
    int32_t overflow;
    float t;

    if (timer->ops->count_get == NULL)
        return 0;

    BSP_ENTER_CRITICAL;
    cnt = timer->ops->count_get(timer);
    overflow = timer->overflow;
    BSP_EXIT_CRITICAL;

    if (timer->info->cntmode == HWTIMER_CNTMODE_DW) {
        cnt = (uint32_t) (timer->freq * timer->period_sec) - cnt;
    }
    if (timer->mode == HWTIMER_MODE_ONESHOT) {
        overflow = 0;
    }

    t = overflow * timer->period_sec + cnt / (float) timer->freq;
    tv.sec = (int32_t) t;
    tv.usec = (int32_t) ((t - tv.sec) * 1000000);
    memcpy(buffer, &tv, sizeof(tv));

    return sizeof(tv);
}

size_t rt_hwtimer_write(rt_hwtimer_t *timer, rt_hwtimerval_t *buffer) {
    BSP_DEF_CRITICAL_SECTION;
    uint32_t t;
    rt_hwtimer_mode_t opm = HWTIMER_MODE_PERIOD;

    if ((timer->ops->start == NULL) || (timer->ops->stop == NULL))
        return 0;

    timer->ops->stop(timer);

    BSP_ENTER_CRITICAL;
    timer->overflow = 0;
    BSP_EXIT_CRITICAL;


    t = timeout_calc(timer,  buffer);
    if ((timer->cycles <= 1) && (timer->mode == HWTIMER_MODE_ONESHOT)) {
        opm = HWTIMER_MODE_ONESHOT;
    }

    if (timer->ops->start(timer, t, opm) != 0) return 0;

    return sizeof(rt_hwtimerval_t);
}

int8_t rt_hwtimer_control(rt_hwtimer_t *timer, int cmd, void *args) {
    BSP_DEF_CRITICAL_SECTION
    int8_t result = 0;

    switch (cmd) {
        case HWTIMER_CTRL_STOP: {
            if (timer->ops->stop != NULL) {
                timer->ops->stop(timer);
            } else {
                result = -1;
            }
        }
            break;
        case HWTIMER_CTRL_FREQ_SET: {
            int32_t *f;

            if (args == NULL) {
                result = -2;
                break;
            }

            f = (int32_t *) args;
            if ((*f > timer->info->maxfreq) || (*f < timer->info->minfreq)) {
//                bsp_d_log("frequency setting out of range! It will maintain at %d Hz", timer->freq);
                result = -3;
                break;
            }

            if (timer->ops->control != NULL) {
                result = timer->ops->control(timer, cmd, args);
                if (result == 0) {
                    BSP_ENTER_CRITICAL;
                    timer->freq = *f;
                    BSP_EXIT_CRITICAL;
                }
            } else {
                result = -1;
            }
        }
            break;
        case HWTIMER_CTRL_INFO_GET: {
            if (args == NULL) {
                result = -2;
                break;
            }

            *((struct rt_hwtimer_info *) args) = *timer->info;
        }
            break;
        case HWTIMER_CTRL_MODE_SET: {
            rt_hwtimer_mode_t *m;

            if (args == NULL) {
                result = -2;
                break;
            }

            m = (rt_hwtimer_mode_t *) args;

            if ((*m != HWTIMER_MODE_ONESHOT) && (*m != HWTIMER_MODE_PERIOD)) {
                result = -2;
                break;
            }
            BSP_ENTER_CRITICAL
            timer->mode = *m;
            BSP_EXIT_CRITICAL
        }
            break;
        default: {
            result = -3;
        }
            break;
    }

    return result;
}

void rt_device_hwtimer_isr(rt_hwtimer_t *timer) {
    BSP_DEF_CRITICAL_SECTION;

    assert_param(timer != RT_NULL);

    BSP_ENTER_CRITICAL;

    timer->overflow++;

    if (timer->cycles != 0) {
        timer->cycles--;
    }

    if (timer->cycles == 0) {
        timer->cycles = timer->reload;

        BSP_ENTER_CRITICAL;

        if (timer->mode == HWTIMER_MODE_ONESHOT) {
            if (timer->ops->stop != NULL) {
                timer->ops->stop(timer);
            }
        }

        if (timer->rx_indicate != NULL) {
            timer->rx_indicate(timer);
        }
    } else {
        BSP_EXIT_CRITICAL;
    }
}

int8_t rt_device_hwtimer_init(rt_hwtimer_t *timer, const char *name, void *user_data) {

    timer->user_data = user_data;

    return 0;
}

bsp_hwtimer驱动部分

头文件

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 24-8-4     shchl   first version
 */

#ifndef THREADX_F407ZGT6_BSP_HWTIMER_H
#define THREADX_F407ZGT6_BSP_HWTIMER_H
#include "hwtimer/hwtimer.h"
#define TIM_DEV_INFO_CONFIG                     \
    {                                           \
        .maxfreq = 1000000,                     \
        .minfreq = 3000,                        \
        .maxcnt  = 0xFFFF,                      \
        .cntmode = HWTIMER_CNTMODE_UP,          \
    }

#define TIM13_CONFIG                                        \
    {                                                       \
       .tim_handle.Instance     = TIM13,                    \
       .tim_irqn                = TIM8_UP_TIM13_IRQn,       \
       .name                    = "timer13",                \
    }


#define BSP_USING_TIM13

int bsp_hwtimer_init(void);
#endif //THREADX_F407ZGT6_BSP_HWTIMER_H

源文件

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-12-10     zylx         first version
 * 2020-06-16     thread-liu   Porting for stm32mp1
 * 2020-08-25     linyongkang  Fix the timer clock frequency doubling problem
 * 2020-10-14     Dozingfiretruck   Porting for stm32wbxx
 */

#include "bsp.h"
#include "bsp_hwtimer.h"


enum {
#ifdef BSP_USING_TIM1
    TIM1_INDEX,
#endif
#ifdef BSP_USING_TIM2
    TIM2_INDEX,
#endif
#ifdef BSP_USING_TIM3
    TIM3_INDEX,
#endif
#ifdef BSP_USING_TIM4
    TIM4_INDEX,
#endif
#ifdef BSP_USING_TIM5
    TIM5_INDEX,
#endif
#ifdef BSP_USING_TIM6
    TIM6_INDEX,
#endif
#ifdef BSP_USING_TIM7
    TIM7_INDEX,
#endif
#ifdef BSP_USING_TIM8
    TIM8_INDEX,
#endif
#ifdef BSP_USING_TIM9
    TIM9_INDEX,
#endif
#ifdef BSP_USING_TIM10
    TIM10_INDEX,
#endif
#ifdef BSP_USING_TIM11
    TIM11_INDEX,
#endif
#ifdef BSP_USING_TIM12
    TIM12_INDEX,
#endif
#ifdef BSP_USING_TIM13
    TIM13_INDEX,
#endif
#ifdef BSP_USING_TIM14
    TIM14_INDEX,
#endif
};

struct stm32_hwtimer {
    rt_hwtimer_t time_device;
    TIM_HandleTypeDef tim_handle;
    IRQn_Type tim_irqn;
    char *name;
};

static struct stm32_hwtimer stm32_hwtimer_obj[] =
        {
#ifdef BSP_USING_TIM1
                TIM1_CONFIG,
#endif

#ifdef BSP_USING_TIM2
                TIM2_CONFIG,
#endif

#ifdef BSP_USING_TIM3
                TIM3_CONFIG,
#endif

#ifdef BSP_USING_TIM4
                TIM4_CONFIG,
#endif

#ifdef BSP_USING_TIM5
                TIM5_CONFIG,
#endif

#ifdef BSP_USING_TIM6
                TIM6_CONFIG,
#endif

#ifdef BSP_USING_TIM7
                TIM7_CONFIG,
#endif

#ifdef BSP_USING_TIM8
                TIM8_CONFIG,
#endif

#ifdef BSP_USING_TIM9
                TIM9_CONFIG,
#endif

#ifdef BSP_USING_TIM10
                TIM10_CONFIG,
#endif

#ifdef BSP_USING_TIM11
                TIM11_CONFIG,
#endif

#ifdef BSP_USING_TIM12
                TIM12_CONFIG,
#endif

#ifdef BSP_USING_TIM13
                TIM13_CONFIG,
#endif

#ifdef BSP_USING_TIM14
                TIM14_CONFIG,
#endif

#ifdef BSP_USING_TIM15
                TIM15_CONFIG,
#endif

#ifdef BSP_USING_TIM16
                TIM16_CONFIG,
#endif

#ifdef BSP_USING_TIM17
                TIM17_CONFIG,
#endif
        };

/* APBx timer clocks frequency doubler state related to APB1CLKDivider value */
static void pclkx_doubler_get(uint32_t *pclk1_doubler, uint32_t *pclk2_doubler) {
    uint32_t flatency = 0;
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    assert_param(pclk1_doubler != ULL);
    assert_param(pclk1_doubler != NULL);

    HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, (uint32_t *) &flatency);

    *pclk1_doubler = 1;
    *pclk2_doubler = 1;

#if defined(SOC_SERIES_STM32MP1)
    if (RCC_ClkInitStruct.APB1_Div != RCC_APB1_DIV1)
    {
        *pclk1_doubler = 2;
    }
    if (RCC_ClkInitStruct.APB2_Div != RCC_APB2_DIV1)
    {
       *pclk2_doubler = 2;
    }
#else
    if (RCC_ClkInitStruct.APB1CLKDivider != RCC_HCLK_DIV1) {
        *pclk1_doubler = 2;
    }
#if !defined(SOC_SERIES_STM32F0) && !defined(SOC_SERIES_STM32G0)
    if (RCC_ClkInitStruct.APB2CLKDivider != RCC_HCLK_DIV1) {
        *pclk2_doubler = 2;
    }
#endif
#endif
}

static void timer_init(struct rt_hwtimer_device *timer, uint32_t state) {
    uint32_t prescaler_value = 0;
    uint32_t pclk1_doubler, pclk2_doubler;
    TIM_HandleTypeDef *tim = NULL;
    struct stm32_hwtimer *tim_device = NULL;

    assert_param(timer != NULL);
    if (state) {
        tim = (TIM_HandleTypeDef *) timer->user_data;
        tim_device = (struct stm32_hwtimer *) timer;

        pclkx_doubler_get((uint32_t *) &pclk1_doubler, (uint32_t *) &pclk2_doubler);

        /* time init */

        if (tim->Instance == TIM9 || tim->Instance == TIM10 || tim->Instance == TIM11) {

            prescaler_value = (uint32_t) (HAL_RCC_GetPCLK2Freq() * pclk2_doubler / 10000) - 1;

        } else {
            prescaler_value = (uint32_t) (HAL_RCC_GetPCLK1Freq() * pclk1_doubler / 10000) - 1;
        }
        tim->Init.Period = 10000 - 1;
        tim->Init.Prescaler = prescaler_value;
        tim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
        if (timer->info->cntmode == HWTIMER_CNTMODE_UP) {
            tim->Init.CounterMode = TIM_COUNTERMODE_UP;
        } else {
            tim->Init.CounterMode = TIM_COUNTERMODE_DOWN;
        }
        tim->Init.RepetitionCounter = 0;

        if (HAL_TIM_Base_Init(tim) != HAL_OK) {
            printf("%s init failed", tim_device->name);
            return;
        } else {
            /* set the TIMx priority */
            HAL_NVIC_SetPriority(tim_device->tim_irqn, 3, 0);

            /* enable the TIMx global Interrupt */
            HAL_NVIC_EnableIRQ(tim_device->tim_irqn);

            /* clear update flag */
            __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE);
            /* enable update request source */
            __HAL_TIM_URS_ENABLE(tim);

            printf("%s init success", tim_device->name);
        }
    }
}

static int8_t timer_start(rt_hwtimer_t *timer, uint32_t t, rt_hwtimer_mode_t opmode) {
    int8_t result = 0;
    TIM_HandleTypeDef *tim = NULL;

    assert_param(timer != NULL);

    tim = (TIM_HandleTypeDef *) timer->user_data;

    /* set tim cnt */
    __HAL_TIM_SET_COUNTER(tim, 0);
    /* set tim arr */
    __HAL_TIM_SET_AUTORELOAD(tim, t - 1);

    if (opmode == HWTIMER_MODE_ONESHOT) {
        /* set timer to single mode */
        tim->Instance->CR1 |= TIM_OPMODE_SINGLE;
    } else {
        tim->Instance->CR1 &= (~TIM_OPMODE_SINGLE);
    }

    /* start timer */
    if (HAL_TIM_Base_Start_IT(tim) != HAL_OK) {
        printf("TIM start failed");
        result = -1;
    }

    return result;
}

static void timer_stop(rt_hwtimer_t *timer) {
    TIM_HandleTypeDef *tim = NULL;

    assert_param(timer != NULL);

    tim = (TIM_HandleTypeDef *) timer->user_data;

    /* stop timer */
    HAL_TIM_Base_Stop_IT(tim);

    /* set tim cnt */
    __HAL_TIM_SET_COUNTER(tim, 0);
}

static int8_t timer_ctrl(rt_hwtimer_t *timer, uint32_t cmd, void *arg) {
    TIM_HandleTypeDef *tim = NULL;
    int8_t result = 0;
    uint32_t pclk1_doubler, pclk2_doubler;

    assert_param(timer != NULL);
    assert_param(arg != NULL);

    tim = (TIM_HandleTypeDef *) timer->user_data;

    switch (cmd) {
        case HWTIMER_CTRL_FREQ_SET: {
            uint32_t freq;
            uint16_t val;

            /* set timer frequence */
            freq = *((uint32_t *) arg);

            pclkx_doubler_get((uint32_t *) &pclk1_doubler, (uint32_t *) &pclk2_doubler);

            if (tim->Instance == TIM9 || tim->Instance == TIM10 || tim->Instance == TIM11) {

                val = HAL_RCC_GetPCLK2Freq() * pclk2_doubler / freq;

            } else {
                val = HAL_RCC_GetPCLK1Freq() * pclk1_doubler / freq;
            }
            __HAL_TIM_SET_PRESCALER(tim, val - 1);

            /* Update frequency value */
            tim->Instance->EGR |= TIM_EVENTSOURCE_UPDATE;
        }
            break;
        default: {
            result = -1;
        }
            break;
    }

    return result;
}

static uint32_t timer_counter_get(rt_hwtimer_t *timer) {
    TIM_HandleTypeDef *tim = NULL;

    assert_param(timer != NULL);

    tim = (TIM_HandleTypeDef *) timer->user_data;

    return tim->Instance->CNT;
}

static const struct rt_hwtimer_info _info = TIM_DEV_INFO_CONFIG;

static const struct rt_hwtimer_ops _ops =
        {
                .init = timer_init,
                .start = timer_start,
                .stop = timer_stop,
                .count_get = timer_counter_get,
                .control = timer_ctrl,
        };

#ifdef BSP_USING_TIM2
void TIM2_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();
    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM2_INDEX].tim_handle);
    /* leave interrupt */
    rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_TIM3
void TIM3_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();
    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM3_INDEX].tim_handle);
    /* leave interrupt */
    rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_TIM4
void TIM4_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();
    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM4_INDEX].tim_handle);
    /* leave interrupt */
    rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_TIM5
void TIM5_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();
    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM5_INDEX].tim_handle);
    /* leave interrupt */
    rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_TIM11
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();
    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM11_INDEX].tim_handle);
    /* leave interrupt */
    rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_TIM13
void TIM8_UP_TIM13_IRQHandler(void)
{
    /* enter interrupt */
    BSP_DEF_CRITICAL_SECTION;
    BSP_ENTER_CRITICAL;
    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM13_INDEX].tim_handle);
    /* leave interrupt */
    BSP_EXIT_CRITICAL;
}
#endif
#ifdef BSP_USING_TIM14

void TIM8_TRG_COM_TIM14_IRQHandler(void) {
/* enter interrupt */
    BSP_DEF_CRITICAL_SECTION;
    BSP_ENTER_CRITICAL;

    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM14_INDEX].tim_handle);

/* leave interrupt */
    BSP_EXIT_CRITICAL;
}

#endif
#ifdef BSP_USING_TIM15
void TIM1_BRK_TIM15_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();
    HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM15_INDEX].tim_handle);
    /* leave interrupt */
    rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_TIM16
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32WB)
void TIM1_UP_TIM16_IRQHandler(void)
#elif defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32MP1)
void TIM16_IRQHandler(void)
#endif
{
/* enter interrupt */
rt_interrupt_enter();
HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM16_INDEX].tim_handle);
/* leave interrupt */
rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_TIM17
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32WB)
void TIM1_TRG_COM_TIM17_IRQHandler(void)
#elif defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32MP1)
void TIM17_IRQHandler(void)
#endif
{
/* enter interrupt */
rt_interrupt_enter();
HAL_TIM_IRQHandler(&stm32_hwtimer_obj[TIM17_INDEX].tim_handle);
/* leave interrupt */
rt_interrupt_leave();
}
#endif

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
#ifdef BSP_USING_TIM2
    if (htim->Instance == TIM2)
    {
        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM2_INDEX].time_device);
    }
#endif
#ifdef BSP_USING_TIM3
    if (htim->Instance == TIM3)
    {
        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM3_INDEX].time_device);
    }
#endif
#ifdef BSP_USING_TIM4
    if (htim->Instance == TIM4)
    {
        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM4_INDEX].time_device);
    }
#endif
#ifdef BSP_USING_TIM5
    if (htim->Instance == TIM5)
    {
        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM5_INDEX].time_device);
    }
#endif
#ifdef BSP_USING_TIM11
    if (htim->Instance == TIM11)
    {
        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM11_INDEX].time_device);
    }
#endif
#ifdef BSP_USING_TIM13
    if (htim->Instance == TIM13)
    {
        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM13_INDEX].time_device);
    }
#endif
#ifdef BSP_USING_TIM14
    if (htim->Instance == TIM14) {
        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM14_INDEX].time_device);
    }
#endif
#ifdef BSP_USING_TIM15
    if (htim->Instance == TIM15)
    {
        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM15_INDEX].time_device);
    }
#endif
#ifdef BSP_USING_TIM16
    if (htim->Instance == TIM16)
    {
        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM16_INDEX].time_device);
    }
#endif
#ifdef BSP_USING_TIM17
    if (htim->Instance == TIM17)
    {
        rt_device_hwtimer_isr(&stm32_hwtimer_obj[TIM17_INDEX].time_device);
    }
#endif
}

int bsp_hwtimer_init(void) {
    int i = 0;
    int result = 0;

    for (i = 0; i < sizeof(stm32_hwtimer_obj) / sizeof(stm32_hwtimer_obj[0]); i++) {
        stm32_hwtimer_obj[i].time_device.info = &_info;
        stm32_hwtimer_obj[i].time_device.ops = &_ops;
        if (rt_device_hwtimer_init(&stm32_hwtimer_obj[i].time_device, stm32_hwtimer_obj[i].name,
                                   &stm32_hwtimer_obj[i].tim_handle) == 0) {
            printf("%s register success", stm32_hwtimer_obj[i].name);
        } else {
            printf("%s register failed", stm32_hwtimer_obj[i].name);
            result = -1;
        }
    }

    return result;
}

rt_hwtimer_t *rt_hwtimer_get_device(const char *name) {
    int i = 0;
    for (i = 0; i < sizeof(stm32_hwtimer_obj) / sizeof(stm32_hwtimer_obj[0]); i++) {

        if (strncmp(stm32_hwtimer_obj[i].name, name, strlen(name)) == 0) {
            return &stm32_hwtimer_obj[i].time_device;
        }


    }


    return NULL;
}

测试代码

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 24-8-4     shchl   first version
 */
#include "bsp.h"
#include "bsp_hwtimer.h"

#define HWTIMER_DEV_NAME   "timer13"     /* 定时器名称 */
rt_hwtimer_t *hw_dev = NULL;   /* 定时器设备句柄 */
/* 定时器超时回调函数 */
static int8_t timeout_cb(struct rt_hwtimer_device *dev) {
    printf("set timeout value failed\n");
    return 0;
}

int hwtimer_sample() {
    int8_t ret = 0;
    rt_hwtimerval_t timeout_s;      /* 定时器超时值 */

    rt_hwtimer_mode_t mode;         /* 定时器模式 */
     uint32_t freq = 10000;               /* 计数频率 */

    /* 查找定时器设备 */
    hw_dev = rt_hwtimer_get_device(HWTIMER_DEV_NAME);
    if (hw_dev == NULL) {
        printf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME);
        return -1;
    }

    /* 以读写方式打开设备 */
    rt_hwtimer_init(hw_dev);
    ret = rt_hwtimer_open(hw_dev);

    if (ret != 0) {
        printf("open %s device failed!\n", HWTIMER_DEV_NAME);
        return ret;
    }

    /* 设置超时回调函数 */
    hw_dev->rx_indicate = timeout_cb;

    /* 设置计数频率(若未设置该项,默认为1Mhz 或 支持的最小计数频率) */
    rt_hwtimer_control(hw_dev, HWTIMER_CTRL_FREQ_SET, &freq);
    /* 设置模式为周期性定时器(若未设置,默认是HWTIMER_MODE_ONESHOT)*/
    mode = HWTIMER_MODE_PERIOD;
    ret = rt_hwtimer_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
    if (ret != 0) {
        printf("set mode failed! ret is :%d\n", ret);
        return ret;
    }

    /* 设置定时器超时值为5s并启动定时器 */
    timeout_s.sec = 5;      /* 秒 */
    timeout_s.usec = 0;     /* 微秒 */
    if (rt_hwtimer_write(hw_dev,  &timeout_s) != sizeof(timeout_s)) {
        printf("set timeout value failed\n");
        return -1;
    }

    /* 延时3500ms */
    HAL_Delay(3500);



    return ret;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

詩不诉卿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值