2025-10-10 16:07:00 +08:00

219 lines
7.2 KiB
C

/**
* @file iot_timer.c
* @brief Beken Corp implementation of Common I/O timer API.
*
* @copyright Copyright (c) 2022 Beken Corp Inc.
*
*/
/* FreeRTOS kernel layer */
#include "FreeRTOS.h"
#include "semphr.h"
/* timer driver layer */
#include "driver/hal/hal_timer_types.h"
#include "timer_hal.h"
#include "driver/timer.h"
#include "driver/timer_types.h"
/* timer iot layer */
#include "iot_timer.h"
#define IOT_TIMER_TAG "iot_timer"
/* attention (copied from timer_driver.c, be careful to check and sync)
* 1. timer2 has been used for time cali
* 2. timer3 has been used for clock, but bk7271 use timer1
* 3. bk7271 has used timer0(10ms)
*/
#define USED_TIMER_ID TIMER_ID0
static void timer_callback(timer_id_t id);
typedef enum{
IOT_TIMER_OPENED = 0, /*!< timer opened flag */
IOT_TIMER_CLOSED, /*!< timer closed flag */
} timer_status_t;
typedef enum{
IOT_COUNTER_STARTED = 0, /*!< timer counter started flag */
IOT_COUNTER_STOPED, /*!< timer counter stoped flag */
} counter_status_t;
typedef struct IotTimerDescriptor
{
timer_id_t timer_id; /*!< timer id */
uint64_t timeout_us; /*!< timeout setting */
uint32_t last_count; /*!< care about last count */
timer_status_t timer_status; /*!< timer status */
counter_status_t counter_status; /*!< counter status */
timer_isr_t timer_isr; /*!< timer interrupt service routine */
IotTimerCallback_t xTimerCallback; /*!< user defined callback function */
void *pvUserContext; /*!< user defined parameters */
} IotTimerDescriptor_t;
static IotTimerDescriptor_t xDefaultTimerDesc =
{
.timer_id = USED_TIMER_ID,
.timeout_us = 0,
.last_count = 0,
.timer_status = IOT_TIMER_CLOSED,
.counter_status = IOT_COUNTER_STOPED,
.timer_isr = NULL,
.xTimerCallback = NULL,
.pvUserContext = NULL,
};
IotTimerHandle_t iot_timer_open(int32_t lTimerInstance)
{
if(USED_TIMER_ID != lTimerInstance){
BK_LOGE(IOT_TIMER_TAG, "Invalid instance of timer %s\n", __func__);
return NULL;
}
IotTimerHandle_t TimerDesc = &xDefaultTimerDesc;
TimerDesc->timer_status = IOT_TIMER_OPENED;
return TimerDesc;
}
int32_t iot_timer_close( IotTimerHandle_t const pxTimerHandle )
{
if(NULL == pxTimerHandle){
BK_LOGE(IOT_TIMER_TAG, "Invalid handler %s\n", __func__);
return IOT_TIMER_INVALID_VALUE;
}
if(IOT_TIMER_CLOSED == pxTimerHandle->timer_status){
BK_LOGE(IOT_TIMER_TAG, "Timer handler is not open %s\n", __func__);
return IOT_TIMER_INVALID_VALUE;
}
if(BK_OK != bk_timer_stop(pxTimerHandle->timer_id))
{
BK_LOGE(IOT_TIMER_TAG, "Timer stop failed %s\n", __func__);
return IOT_TIMER_SET_FAILED;
}
/* Reset the timer handler to default */
pxTimerHandle->timer_status = IOT_TIMER_CLOSED;
pxTimerHandle->xTimerCallback = NULL;
pxTimerHandle->counter_status = IOT_COUNTER_STOPED;
pxTimerHandle->pvUserContext = NULL;
pxTimerHandle->timer_isr = NULL;
pxTimerHandle->timeout_us = 0;
pxTimerHandle->last_count = 0;
return IOT_TIMER_SUCCESS;
}
static void timer_callback(timer_id_t id)
{
IotTimerHandle_t TimerDesc = &xDefaultTimerDesc;
BK_LOGD(IOT_TIMER_TAG, "Timer %d callback\n", id);
if(NULL == TimerDesc->xTimerCallback){
BK_LOGD(IOT_TIMER_TAG, "Null callback %s\n", __func__);
return;
}
TimerDesc->xTimerCallback(TimerDesc->pvUserContext);
/* get the timer end count for time out setting*/
TimerDesc->last_count = bk_timer_get_period(TimerDesc->timer_id);
TimerDesc->timeout_us = 0;
TimerDesc->xTimerCallback = NULL;
TimerDesc->pvUserContext = NULL;
bk_timer_cancel(id);
}
void iot_timer_set_callback( IotTimerHandle_t const pxTimerHandle,
IotTimerCallback_t xCallback,
void * pvUserContext )
{
if(pxTimerHandle == NULL){
BK_LOGE(IOT_TIMER_TAG, "Invalid handler %s\n", __func__);
return ;
}
pxTimerHandle->timer_isr = timer_callback;
pxTimerHandle->xTimerCallback = xCallback;
pxTimerHandle->pvUserContext = pvUserContext;
}
int32_t iot_timer_start( IotTimerHandle_t const pxTimerHandle )
{
if(NULL == pxTimerHandle){
BK_LOGE(IOT_TIMER_TAG, "Invalid handler %s\n", __func__);
return IOT_TIMER_INVALID_VALUE;
}
if(NULL == pxTimerHandle->timer_isr){
if(BK_OK != bk_timer_enable(pxTimerHandle->timer_id)){
BK_LOGE(IOT_TIMER_TAG, "Timer enable failed %s\n", __func__);
}
} else if(BK_OK != bk_timer_delay_with_callback(pxTimerHandle->timer_id, pxTimerHandle->timeout_us, pxTimerHandle->timer_isr)){
BK_LOGE(IOT_TIMER_TAG, "Timer start failed %s\n", __func__);
return IOT_TIMER_SET_FAILED;
}
pxTimerHandle->counter_status = IOT_COUNTER_STARTED;
return IOT_TIMER_SUCCESS;
}
int32_t iot_timer_stop( IotTimerHandle_t const pxTimerHandle )
{
if(NULL == pxTimerHandle){
BK_LOGE(IOT_TIMER_TAG, "Invalid handler %s\n", __func__);
return IOT_TIMER_INVALID_VALUE;
}
if(BK_OK != bk_timer_stop(pxTimerHandle->timer_id)) {
BK_LOGE(IOT_TIMER_TAG, "Timer stop failed %s\n", __func__);
return IOT_TIMER_SET_FAILED;
}
pxTimerHandle->counter_status = IOT_COUNTER_STOPED;
/* reset the last count to zero */
pxTimerHandle->last_count = 0;
return IOT_TIMER_SUCCESS;
}
int32_t iot_timer_get_value( IotTimerHandle_t const pxTimerHandle,
uint64_t * ullMicroSeconds )
{
if(NULL == pxTimerHandle){
BK_LOGE(IOT_TIMER_TAG, "Invalid handler %s\n", __func__);
return IOT_TIMER_INVALID_VALUE;
}
if(NULL == ullMicroSeconds){
BK_LOGE(IOT_TIMER_TAG, "Time buffer is NULL %s\n", __func__);
return IOT_TIMER_INVALID_VALUE;
}
if(IOT_COUNTER_STOPED == pxTimerHandle->counter_status){
BK_LOGE(IOT_TIMER_TAG, "Timer counter not running %s\n", __func__);
return IOT_TIMER_NOT_RUNNING;
}
*ullMicroSeconds = bk_timer_get_time(pxTimerHandle->timer_id, 1, pxTimerHandle->last_count, TIMER_UNIT_US);
return IOT_TIMER_SUCCESS;
}
int32_t iot_timer_delay( IotTimerHandle_t const pxTimerHandle,
uint32_t ulDelayMicroSeconds )
{
if(NULL == pxTimerHandle){
BK_LOGE(IOT_TIMER_TAG, "Invalid handler %s\n", __func__);
return IOT_TIMER_INVALID_VALUE;
}
/* set time out value */
pxTimerHandle->timeout_us = (uint64_t)ulDelayMicroSeconds;
return IOT_TIMER_SUCCESS;
}
int32_t iot_timer_cancel( IotTimerHandle_t const pxTimerHandle )
{
if(NULL == pxTimerHandle){
BK_LOGE(IOT_TIMER_TAG, "Invalid handler %s\n", __func__);
return IOT_TIMER_INVALID_VALUE;
}
/* this will cancel the timer delay and continue counting without resetting the count to zero */
if(BK_OK != bk_timer_cancel(pxTimerHandle->timer_id)){
BK_LOGE(IOT_TIMER_TAG, "Timer delay cancel failed %s\n", __func__);
return IOT_TIMER_FUNCTION_NOT_SUPPORTED;
}
/* set time out to zero */
pxTimerHandle->timeout_us = 0;
/* set the timer isr to NULL */
pxTimerHandle->timer_isr = NULL;
return IOT_TIMER_SUCCESS;
}