feat: add hdf timer

Signed-off-by: s00442234 <susha@huawei.com>
This commit is contained in:
s00442234 2022-01-07 12:51:45 +08:00
parent ef9ef85aa2
commit 60750ad073
12 changed files with 1282 additions and 0 deletions

100
include/platform/timer_if.h Executable file
View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef TIMER_IF_H
#define TIMER_IF_H
#include "platform_if.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
/**
* @brief Defines a callback that will be invoked when a timer's interrupt involved.
*/
typedef int32_t (*TimerHandleCb)(void);
/**
* @brief Gets a timer.
* This function must be called to get its device handle before operating the timer.
* @param number Indicates a timer id.
* @return If the operation is successful, a pointer to the timer device handle is returned.
* @since 1.0
*/
DevHandle TimerOpen(const uint32_t number);
/**
* @brief Close a timer.
* If you no longer need the timer, call this function to close it
* @param handle Represents a pointer to the timer device handle.
* @since 1.0
*/
void TimerClose(DevHandle handle);
/**
* @brief Start a timer.
* If you need the timer run, call this function to start it
* @param handle Represents a pointer to the timer device handle.
* @return success or fail
* @since 1.0
*/
int32_t TimerStart(DevHandle handle);
/**
* @brief Stop a timer.
* If you no longer need the timer run, call this function to stop it
* @param handle Represents a pointer to the timer device handle.
* @return success or fail
* @since 1.0
*/
int32_t TimerStop(DevHandle handle);
/**
* @brief Set a period timer.
* If you need the timer run, call this function to set timer info
* @param handle Represents a pointer to the timer device handle.
* @param useconds Represents the timer interval.
* @param cb Represents the timer callback function.
* @return success or fail
* @since 1.0
*/
int32_t TimerSet(DevHandle handle, uint32_t useconds, TimerHandleCb cb);
/**
* @brief Set a oneshot timer.
* If you need the timer run, call this function to set timer info
* @param useconds Represents the timer interval.
* @param cb Represents the timer callback function.
* @return success or fail
* @since 1.0
*/
int32_t TimerSetOnce(DevHandle handle, uint32_t useconds, TimerHandleCb cb);
/**
* @brief Get the timer info.
* If you need the timer info, call this function get
* @param handle Represents a pointer to the timer device handle.
* @param useconds Represents the timer interval.
* @param isPeriod Represents whether the timer call once
* @return success or fail
* @since 1.0
*/
int32_t TimerGet(DevHandle handle, uint32_t *useconds, bool *isPeriod);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* TIMER_IF_H */
/** @} */

View File

@ -0,0 +1,147 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef TIMER_CORE_H
#define TIMER_CORE_H
#include "hdf_base.h"
#include "hdf_device_desc.h"
#include "osal_mutex.h"
#include "timer_if.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#define CHECK_NULL_PTR_RETURN_VALUE(ptr, ret) do { \
if ((ptr) == NULL) { \
HDF_LOGE("%s:line %d pointer is null and return ret", __func__, __LINE__); \
return (ret); \
} \
} while (0)
#define CHECK_NULL_PTR_RETURN(ptr) do { \
if ((ptr) == NULL) { \
HDF_LOGE("%s:line %d pointer is null and return", __func__, __LINE__); \
return; \
} \
} while (0)
#define CHECK_PARSER_RESULT_RETURN_VALUE(ret, str) do { \
if (ret != HDF_SUCCESS) { \
HDF_LOGE("%s:line %d %s fail, ret = %d!", __func__, __LINE__, str, ret); \
return HDF_FAILURE; \
} \
} while (0)
struct TimerInfo {
uint32_t number;
TimerHandleCb cb;
uint32_t useconds;
bool isPeriod;
};
struct TimerCntrl {
struct TimerInfo info;
struct DListHead node;
struct TimerCntrlMethod *ops;
void *priv;
struct OsalMutex lock;
};
struct TimerCntrlMethod {
int32_t (*Remove)(struct TimerCntrl *cntrl);
int32_t (*Open)(struct TimerCntrl *cntrl);
int32_t (*Close)(struct TimerCntrl *cntrl);
int32_t (*Start)(struct TimerCntrl *cntrl);
int32_t (*Stop)(struct TimerCntrl *cntrl);
int32_t (*Set)(struct TimerCntrl *cntrl, uint32_t useconds, TimerHandleCb cb);
int32_t (*SetOnce)(struct TimerCntrl *cntrl, uint32_t useconds, TimerHandleCb cb);
int32_t (*Get)(struct TimerCntrl *cntrl, uint32_t *useconds, bool *isPeriod);
};
/**
* @brief add a timer controller to manager list
* @param cntrl Indicates a timer controller.
* @constraints:
* @return success or fail
*/
int32_t TimerCntrlAdd(struct TimerCntrl *cntrl);
/**
* @brief remove a timer controller from manager list
* @param number Indicates a timer id.
* @constraints:
* @return success or fail
*/
int32_t TimerCntrlRemoveByNumber(const uint32_t number);
/**
* @brief Find and return a timer controller by number
* @param number Indicates a timer id.
* @return a timer controller
*/
struct TimerCntrl *TimerCntrlOpen(const uint32_t number);
/**
* @brief close a timer controller
* @param cntrl Indicates a timer controller.
* @return success or fail
*/
int32_t TimerCntrlClose(struct TimerCntrl *cntrl);
/**
* @brief set a timer controller
* @param cntrl Indicates a period timer controller.
* @param useconds Indicates a timer timerout time us.
* @param cb Indicates a timer callback.
* @return success or fail
*/
int32_t TimerCntrlSet(struct TimerCntrl *cntrl, uint32_t useconds, TimerHandleCb cb);
/**
* @brief set a timer controller
* @param cntrl Indicates a timer controller.
* @param useconds Indicates a timer timerout time us.
* @param cb Indicates a timer callback.
* @return success or fail
*/
int32_t TimerCntrlSetOnce(struct TimerCntrl *cntrl, uint32_t useconds, TimerHandleCb cb);
/**
* @brief get a timer controller
* @param cntrl Indicates a timer controller.
* @param useconds Represents the timer interval.
* @param isPeriod Represents whether the timer call once
* @return success or fail
*/
int32_t TimerCntrlGet(struct TimerCntrl *cntrl, uint32_t *useconds, bool *isPeriod);
/**
* @brief start a timer controller
* @param cntrl Indicates a timer controller.
* @return success or fail
*/
int32_t TimerCntrlStart(struct TimerCntrl *cntrl);
/**
* @brief stop a timer controller
* @param cntrl Indicates a timer controller.
* @return success or fail
*/
int32_t TimerCntrlStop(struct TimerCntrl *cntrl);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* TIMER_CORE_H */

View File

@ -0,0 +1,302 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "timer_core.h"
#include "hdf_log.h"
#include "osal_mem.h"
#include "osal_time.h"
#include "securec.h"
#define HDF_LOG_TAG timer_core
struct TimerManager {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct DListHead timerListHead;
struct OsalMutex lock;
};
static struct TimerManager *g_timerManager = NULL;
int32_t TimerCntrlAdd(struct TimerCntrl *cntrl)
{
CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_PARAM);
CHECK_NULL_PTR_RETURN_VALUE(cntrl->ops, HDF_ERR_INVALID_PARAM);
struct TimerCntrl *pos = NULL;
struct TimerCntrl *tmp = NULL;
struct TimerManager *manager = g_timerManager;
CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->timerListHead, struct TimerCntrl, node) {
if (cntrl->info.number == pos->info.number) {
HDF_LOGE("%s: timer[%u] existed", __func__, cntrl->info.number);
return HDF_FAILURE;
}
}
// init info
if (OsalMutexInit(&cntrl->lock) != HDF_SUCCESS) {
HDF_LOGE("%s: OsalMutexInit %u failed", __func__, cntrl->info.number);
return HDF_FAILURE;
}
if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
return HDF_ERR_DEVICE_BUSY;
}
DListInsertTail(&cntrl->node, &manager->timerListHead);
(void)OsalMutexUnlock(&manager->lock);
HDF_LOGI("%s: add timer number[%u] success", __func__, cntrl->info.number);
return HDF_SUCCESS;
}
int32_t TimerCntrlRemoveByNumber(const uint32_t number)
{
struct TimerCntrl *pos = NULL;
struct TimerCntrl *tmp = NULL;
struct TimerManager *manager = g_timerManager;
CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
HDF_LOGE("%s: OsalMutexLock failed", __func__);
return HDF_ERR_DEVICE_BUSY;
}
DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->timerListHead, struct TimerCntrl, node) {
if (number == pos->info.number) {
if ((pos->ops->Remove != NULL) && (pos->ops->Remove(pos) != HDF_SUCCESS)) {
HDF_LOGE("%s: remove %u failed", __func__, pos->info.number);
}
(void)OsalMutexDestroy(&pos->lock);
DListRemove(&pos->node);
OsalMemFree(pos);
break;
}
}
(void)OsalMutexUnlock(&manager->lock);
HDF_LOGI("%s: remove timer %u success", __func__, number);
return HDF_SUCCESS;
}
struct TimerCntrl *TimerCntrlOpen(const uint32_t number)
{
struct TimerCntrl *pos = NULL;
struct TimerManager *manager = g_timerManager;
CHECK_NULL_PTR_RETURN_VALUE(manager, NULL);
if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
HDF_LOGE("%s: OsalMutexLock failed", __func__);
return NULL;
}
DLIST_FOR_EACH_ENTRY(pos, &manager->timerListHead, struct TimerCntrl, node) {
if (number == pos->info.number) {
(void)OsalMutexUnlock(&manager->lock);
return pos;
}
}
(void)OsalMutexUnlock(&manager->lock);
HDF_LOGE("%s: open %u failed", __func__, number);
return NULL;
}
int32_t TimerCntrlClose(struct TimerCntrl *cntrl)
{
CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
return HDF_ERR_DEVICE_BUSY;
}
if ((cntrl->ops->Close != NULL) && (cntrl->ops->Close(cntrl) != HDF_SUCCESS)) {
HDF_LOGE("%s: close %u failed", __func__, cntrl->info.number);
(void)OsalMutexUnlock(&cntrl->lock);
return HDF_FAILURE;
}
(void)OsalMutexUnlock(&cntrl->lock);
return HDF_SUCCESS;
}
int32_t TimerCntrlSet(struct TimerCntrl *cntrl, uint32_t useconds, TimerHandleCb cb)
{
CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
CHECK_NULL_PTR_RETURN_VALUE(cb, HDF_ERR_INVALID_OBJECT);
if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
return HDF_ERR_DEVICE_BUSY;
}
if ((cntrl->ops->Set != NULL) && (cntrl->ops->Set(cntrl, useconds, cb) != HDF_SUCCESS)) {
HDF_LOGE("%s: set %u failed", __func__, cntrl->info.number);
(void)OsalMutexUnlock(&cntrl->lock);
return HDF_FAILURE;
}
(void)OsalMutexUnlock(&cntrl->lock);
return HDF_SUCCESS;
}
int32_t TimerCntrlSetOnce(struct TimerCntrl *cntrl, uint32_t useconds, TimerHandleCb cb)
{
CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
CHECK_NULL_PTR_RETURN_VALUE(cb, HDF_ERR_INVALID_OBJECT);
if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
return HDF_ERR_DEVICE_BUSY;
}
if ((cntrl->ops->SetOnce != NULL) && (cntrl->ops->SetOnce(cntrl, useconds, cb) != HDF_SUCCESS)) {
HDF_LOGE("%s: setOnce %u failed", __func__, cntrl->info.number);
(void)OsalMutexUnlock(&cntrl->lock);
return HDF_FAILURE;
}
(void)OsalMutexUnlock(&cntrl->lock);
return HDF_SUCCESS;
}
int32_t TimerCntrlGet(struct TimerCntrl *cntrl, uint32_t *useconds, bool *isPeriod)
{
CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
CHECK_NULL_PTR_RETURN_VALUE(useconds, HDF_ERR_INVALID_OBJECT);
CHECK_NULL_PTR_RETURN_VALUE(isPeriod, HDF_ERR_INVALID_OBJECT);
if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
return HDF_ERR_DEVICE_BUSY;
}
*useconds = cntrl->info.useconds;
*isPeriod = cntrl->info.isPeriod;
(void)OsalMutexUnlock(&cntrl->lock);
return HDF_SUCCESS;
}
int32_t TimerCntrlStart(struct TimerCntrl *cntrl)
{
CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
return HDF_ERR_DEVICE_BUSY;
}
if ((cntrl->ops->Start != NULL) && (cntrl->ops->Start(cntrl) != HDF_SUCCESS)) {
HDF_LOGE("%s: start %u failed", __func__, cntrl->info.number);
(void)OsalMutexUnlock(&cntrl->lock);
return HDF_FAILURE;
}
(void)OsalMutexUnlock(&cntrl->lock);
return HDF_SUCCESS;
}
int32_t TimerCntrlStop(struct TimerCntrl *cntrl)
{
CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
return HDF_ERR_DEVICE_BUSY;
}
if ((cntrl->ops->Stop != NULL) && (cntrl->ops->Stop(cntrl) != HDF_SUCCESS)) {
HDF_LOGE("%s: stop %u failed", __func__, cntrl->info.number);
(void)OsalMutexUnlock(&cntrl->lock);
return HDF_FAILURE;
}
(void)OsalMutexUnlock(&cntrl->lock);
return HDF_SUCCESS;
}
int32_t TimerListRemoveAll(void)
{
struct TimerCntrl *pos = NULL;
struct TimerCntrl *tmp = NULL;
struct TimerManager *manager = g_timerManager;
if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
HDF_LOGE("%s: lock regulator manager fail", __func__);
return HDF_ERR_DEVICE_BUSY;
}
DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->timerListHead, struct TimerCntrl, node) {
if ((pos->ops->Remove != NULL) && (pos->ops->Remove(pos) != HDF_SUCCESS)) {
HDF_LOGE("%s: remove %u failed", __func__, pos->info.number);
}
DListRemove(&pos->node);
(void)OsalMutexDestroy(&pos->lock);
OsalMemFree(pos);
}
(void)OsalMutexUnlock(&manager->lock);
HDF_LOGI("%s: remove all regulator success", __func__);
return HDF_SUCCESS;
}
static int32_t TimerManagerBind(struct HdfDeviceObject *device)
{
int32_t ret;
struct TimerManager *manager = NULL;
CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_OBJECT);
manager = (struct TimerManager *)OsalMemCalloc(sizeof(*manager));
if (manager == NULL) {
HDF_LOGE("%s: malloc manager fail!", __func__);
return HDF_ERR_MALLOC_FAIL;
}
ret = OsalMutexInit(&manager->lock);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: mutex init fail:%d", __func__, ret);
OsalMemFree(manager);
manager = NULL;
return HDF_FAILURE;
}
manager->device = device;
device->service = &manager->service;
DListHeadInit(&manager->timerListHead);
g_timerManager = manager;
HDF_LOGI("%s: success", __func__);
return HDF_SUCCESS;
}
static int32_t TimerManagerInit(struct HdfDeviceObject *device)
{
(void)device;
HDF_LOGI("%s: success", __func__);
return HDF_SUCCESS;
}
static void TimerManagerRelease(struct HdfDeviceObject *device)
{
HDF_LOGI("%s: Enter!", __func__);
CHECK_NULL_PTR_RETURN(device);
if (TimerListRemoveAll() != HDF_SUCCESS) {
HDF_LOGE("%s: failed", __func__);
}
struct TimerManager *manager = (struct TimerManager *)device->service;
CHECK_NULL_PTR_RETURN(manager);
OsalMutexDestroy(&manager->lock);
OsalMemFree(manager);
g_timerManager = NULL;
}
struct HdfDriverEntry g_timerManagerEntry = {
.moduleVersion = 1,
.Bind = TimerManagerBind,
.Init = TimerManagerInit,
.Release = TimerManagerRelease,
.moduleName = "HDF_PLATFORM_TIMER_MANAGER",
};
HDF_INIT(g_timerManagerEntry);

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "timer_if.h"
#include "hdf_log.h"
#include "timer_core.h"
DevHandle TimerOpen(const uint32_t number)
{
return (DevHandle)TimerCntrlOpen(number);
}
void TimerClose(DevHandle handle)
{
struct TimerCntrl *cntrl = (struct TimerCntrl *)handle;
if (cntrl == NULL) {
HDF_LOGE("%s: cntrl is null", __func__);
return;
}
if (TimerCntrlClose(cntrl) != HDF_SUCCESS) {
HDF_LOGE("%s: TimerCntrlClose fail", __func__);
return;
}
}
int32_t TimerSet(DevHandle handle, uint32_t useconds, TimerHandleCb cb)
{
struct TimerCntrl *cntrl = (struct TimerCntrl *)handle;
if (cntrl == NULL || cb == NULL) {
HDF_LOGE("%s: cntrl is null", __func__);
return HDF_FAILURE;
}
if (TimerCntrlSet(cntrl, useconds, cb) != HDF_SUCCESS) {
HDF_LOGE("%s: TimerCntrlSet fail", __func__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t TimerSetOnce(DevHandle handle, uint32_t useconds, TimerHandleCb cb)
{
struct TimerCntrl *cntrl = (struct TimerCntrl *)handle;
if (cntrl == NULL || cb == NULL) {
HDF_LOGE("%s: cntrl is null", __func__);
return HDF_FAILURE;
}
if (TimerCntrlSetOnce(cntrl, useconds, cb) != HDF_SUCCESS) {
HDF_LOGE("%s: TimerCntrlSetOnce fail", __func__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t TimerGet(DevHandle handle, uint32_t *useconds, bool *isPeriod)
{
struct TimerCntrl *cntrl = (struct TimerCntrl *)handle;
if (cntrl == NULL || useconds == NULL || isPeriod == NULL) {
HDF_LOGE("%s: param is null", __func__);
return HDF_FAILURE;
}
if (TimerCntrlGet(cntrl, useconds, isPeriod) != HDF_SUCCESS) {
HDF_LOGE("%s: TimerCntrlGet fail", __func__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t TimerStart(DevHandle handle)
{
struct TimerCntrl *cntrl = (struct TimerCntrl *)handle;
if (cntrl == NULL) {
HDF_LOGE("%s: cntrl is null", __func__);
return HDF_FAILURE;
}
if (TimerCntrlStart(cntrl) != HDF_SUCCESS) {
HDF_LOGE("%s: TimerCntrlStart fail", __func__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t TimerStop(DevHandle handle)
{
struct TimerCntrl *cntrl = (struct TimerCntrl *)handle;
if (cntrl == NULL) {
HDF_LOGE("%s: cntrl is null", __func__);
return HDF_FAILURE;
}
if (TimerCntrlStop(cntrl) != HDF_SUCCESS) {
HDF_LOGE("%s: TimerCntrlStop fail", __func__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <gtest/gtest.h>
#include <string>
#include <unistd.h>
#include "hdf_uhdf_test.h"
#include "hdf_io_service_if.h"
using namespace testing::ext;
enum TimerTestCmd {
TIMER_START_TEST = 1,
TIMER_TEST_SET,
TIMER_TEST_SETONCE,
TIMER_TEST_GET,
TIMER_TEST_START,
TIMER_TEST_STOP,
TIMER_MULTI_THREAD_TEST,
TIMER_RELIABILITY_TEST,
};
class HdfLiteTimerTest : public testing::Test {
public:
static void SetUpTestCase();
static void TearDownTestCase();
void SetUp();
void TearDown();
};
void HdfLiteTimerTest::SetUpTestCase()
{
HdfTestOpenService();
}
void HdfLiteTimerTest::TearDownTestCase()
{
HdfTestCloseService();
}
void HdfLiteTimerTest::SetUp()
{
}
void HdfLiteTimerTest::TearDown()
{
}
/**
* @tc.name: TimerTestSet001
* @tc.desc: timer set test
* @tc.type: FUNC
* @tc.require: NA
*/
HWTEST_F(HdfLiteTimerTest, TimerTestSet001, TestSize.Level1)
{
struct HdfTestMsg msg = {TEST_PAL_TIMER_TYPE, TIMER_TEST_SET, -1};
EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
}
/**
* @tc.name: TimerTestSetOnce001
* @tc.desc: timer set once test
* @tc.type: FUNC
* @tc.require: NA
*/
HWTEST_F(HdfLiteTimerTest, TimerTestSetOnce001, TestSize.Level1)
{
struct HdfTestMsg msg = {TEST_PAL_TIMER_TYPE, TIMER_TEST_SETONCE, -1};
EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
}
/**
* @tc.name: TimerTestGet001
* @tc.desc: timer get test
* @tc.type: FUNC
* @tc.require: NA
*/
HWTEST_F(HdfLiteTimerTest, TimerTestGet001, TestSize.Level1)
{
struct HdfTestMsg msg = {TEST_PAL_TIMER_TYPE, TIMER_TEST_GET, -1};
EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
}
/**
* @tc.name: TimerTestStart001
* @tc.desc: timer start test
* @tc.type: FUNC
* @tc.require: NA
*/
HWTEST_F(HdfLiteTimerTest, TimerTestStart001, TestSize.Level1)
{
struct HdfTestMsg msg = {TEST_PAL_TIMER_TYPE, TIMER_TEST_START, -1};
EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
}
/**
* @tc.name: TimerTestStop001
* @tc.desc: timer stop test
* @tc.type: FUNC
* @tc.require: NA
*/
HWTEST_F(HdfLiteTimerTest, TimerTestStop001, TestSize.Level1)
{
struct HdfTestMsg msg = {TEST_PAL_TIMER_TYPE, TIMER_TEST_STOP, -1};
EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
}
/**
* @tc.name: TimerTestMultiThread001
* @tc.desc: timer multi thread test
* @tc.type: FUNC
* @tc.require: NA
*/
HWTEST_F(HdfLiteTimerTest, TimerTestMultiThread001, TestSize.Level1)
{
struct HdfTestMsg msg = {TEST_PAL_TIMER_TYPE, TIMER_MULTI_THREAD_TEST, -1};
EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
}
/**
* @tc.name: TimerTestReliability001
* @tc.desc: timer reliability test
* @tc.type: FUNC
* @tc.require: NA
*/
HWTEST_F(HdfLiteTimerTest, TimerTestReliability001, TestSize.Level1)
{
struct HdfTestMsg msg = {TEST_PAL_TIMER_TYPE, TIMER_RELIABILITY_TEST, -1};
EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
}

View File

@ -70,6 +70,9 @@
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PWM) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PWM)
#include "hdf_pwm_entry_test.h"
#endif
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_TIMER) || defined(CONFIG_DRIVERS_HDF_PLATFORM_TIMER)
#include "hdf_timer_entry_test.h"
#endif
#endif
#if defined(LOSCFG_DRIVERS_HDF_WIFI) || defined(CONFIG_DRIVERS_HDF_WIFI)
#include "hdf_wifi_test.h"
@ -149,6 +152,9 @@ HdfTestFuncList g_hdfTestFuncList[] = {
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PWM) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PWM)
{ TEST_PAL_PWM_TYPE, HdfPwmUnitTestEntry },
#endif
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_TIMER) || defined(CONFIG_DRIVERS_HDF_PLATFORM_TIMER)
{ TEST_PAL_TIMER_TYPE, HdfTimerUnitTestEntry },
#endif
#endif
{ TEST_CONFIG_TYPE, HdfConfigEntry },
{ TEST_OSAL_ITEM, HdfOsalEntry },

View File

@ -60,6 +60,7 @@ typedef enum {
TEST_PAL_I3C_TYPE = 22,
TEST_PAL_MIPI_CSI_TYPE = 23,
TEST_PAL_DAC_TYPE = 24,
TEST_PAL_TIMER_TYPE = 25,
TEST_PAL_MANAGER_TYPE = 196,
TEST_PAL_DEVICE_TYPE = 197,
TEST_PAL_QUEUE_TYPE = 198,

View File

@ -56,6 +56,7 @@ enum HdfTestSubModuleCmd {
TEST_PAL_I3C_TYPE = 22,
TEST_PAL_MIPI_CSI_TYPE = 23,
TEST_PAL_DAC_TYPE = 24,
TEST_PAL_TIMER_TYPE = 25,
TEST_PAL_MANAGER_TYPE = 196,
TEST_PAL_DEVICE_TYPE = 197,
TEST_PAL_QUEUE_TYPE = 198,

View File

@ -0,0 +1,380 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "timer_test.h"
#include "device_resource_if.h"
#include "hdf_log.h"
#include "osal_thread.h"
#include "osal_time.h"
#include "timer_if.h"
#define HDF_LOG_TAG timer_test_c
static bool g_theard1Flag;
static bool g_theard2Flag;
struct TimerTestFunc {
enum TimerTestCmd type;
int32_t (*Func)(struct TimerTest *test);
};
int32_t TimerTestcaseCb(void)
{
static uint16_t num = 0;
num++;
if (num >= TIMER_TEST_PERIOD_TIMES) {
HDF_LOGD("->>>>>>>>>>>%s:num exceed max", __func__);
g_theard2Flag = true;
}
return HDF_SUCCESS;
}
int32_t TimerTestcaseOnceCb(void)
{
HDF_LOGD("->>>>>>>>>>>%s:", __func__);
g_theard1Flag = true;
return HDF_SUCCESS;
}
static int32_t TimerSetTest(struct TimerTest *test)
{
if (test == NULL || test->handle == NULL) {
HDF_LOGE("%s: test null", __func__);
return HDF_ERR_INVALID_OBJECT;
}
TimerSet(test->handle, test->uSecond, TimerTestcaseCb);
return HDF_SUCCESS;
}
static int32_t TimerSetOnceTest(struct TimerTest *test)
{
if (test == NULL || test->handle == NULL) {
HDF_LOGE("%s: test null", __func__);
return HDF_ERR_INVALID_OBJECT;
}
TimerSetOnce(test->handle, test->uSecond, TimerTestcaseOnceCb);
return HDF_SUCCESS;
}
static int32_t TimerGetTest(struct TimerTest *test)
{
if (test == NULL || test->handle == NULL) {
HDF_LOGE("%s: test null", __func__);
return HDF_ERR_INVALID_OBJECT;
}
uint32_t uSecond;
bool isPeriod;
TimerGet(test->handle, &uSecond, &isPeriod);
HDF_LOGD("%s:[%d][%d]", __func__, uSecond, isPeriod);
return HDF_SUCCESS;
}
static int32_t TimerStartTest(struct TimerTest *test)
{
if (test == NULL || test->handle == NULL) {
HDF_LOGE("%s: test null", __func__);
return HDF_ERR_INVALID_OBJECT;
}
TimerStart(test->handle);
return HDF_SUCCESS;
}
static int32_t TimerStopTest(struct TimerTest *test)
{
if (test == NULL || test->handle == NULL) {
HDF_LOGE("%s: test null", __func__);
return HDF_ERR_INVALID_OBJECT;
}
TimerStop(test->handle);
return HDF_SUCCESS;
}
static int TimerOnceTestThreadFunc(void *param)
{
DevHandle handle = (DevHandle)param;
if (handle == NULL) {
HDF_LOGE("%s: timer test get handle fail", __func__);
g_theard1Flag = true;
return HDF_FAILURE;
}
if(TimerSetOnce(handle, TIMER_TEST_TIME_USECONDS, TimerTestcaseOnceCb) != HDF_SUCCESS) {
HDF_LOGE("%s: TimerSetOnce fail", __func__);
g_theard1Flag = true;
return HDF_FAILURE;
}
if (TimerStart(handle) != HDF_SUCCESS) {
HDF_LOGE("%s: TimerStart fail", __func__);
g_theard1Flag = true;
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int TimerPeriodTestThreadFunc(void *param)
{
DevHandle handle = (DevHandle)param;
if (handle == NULL) {
HDF_LOGE("%s: timer test get handle fail", __func__);
g_theard2Flag = true;
return HDF_FAILURE;
}
if(TimerSet(handle, TIMER_TEST_TIME_USECONDS, TimerTestcaseCb) != HDF_SUCCESS) {
HDF_LOGE("%s: TimerSet fail", __func__);
g_theard2Flag = true;
return HDF_FAILURE;
}
if (TimerStart(handle) != HDF_SUCCESS) {
HDF_LOGE("%s: TimerStart fail", __func__);
g_theard2Flag = true;
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t TimerTestMultiThread(struct TimerTest *test)
{
int32_t ret;
uint32_t time = 0;
struct OsalThread thread1, thread2;
struct OsalThreadParam cfg1, cfg2;
DevHandle handle1 = NULL;
DevHandle handle2 = NULL;
if (test == NULL) {
HDF_LOGE("%s: timer test NULL", __func__);
return HDF_FAILURE;
}
thread1.realThread = NULL;
thread2.realThread = NULL;
do {
handle1 = TimerOpen(TIMER_TEST_TIME_ID_THREAD1);
if (handle1 == NULL) {
HDF_LOGE("%s: timer test get handle1 fail", __func__);
ret = HDF_FAILURE;
break;
}
handle2 = TimerOpen(TIMER_TEST_TIME_ID_THREAD2);
if (handle1 == NULL) {
HDF_LOGE("%s: timer test get handle2 fail", __func__);
ret = HDF_FAILURE;
break;
}
ret = OsalThreadCreate(&thread1, (OsalThreadEntry)TimerOnceTestThreadFunc, (void *)handle1);
if (ret != HDF_SUCCESS) {
HDF_LOGE("create test once timer fail:%d", ret);
ret = HDF_FAILURE;
break;
}
ret = OsalThreadCreate(&thread2, (OsalThreadEntry)TimerPeriodTestThreadFunc, (void *)handle2);
if (ret != HDF_SUCCESS) {
HDF_LOGE("create test period timer fail:%d", ret);
ret = HDF_FAILURE;
break;
}
cfg1.name = "TimerTestThread-once";
cfg2.name = "TimerTestThread-period";
cfg1.priority = cfg2.priority = OSAL_THREAD_PRI_DEFAULT;
cfg1.stackSize = cfg2.stackSize = TIMER_TEST_STACK_SIZE;
ret = OsalThreadStart(&thread1, &cfg1);
if (ret != HDF_SUCCESS) {
HDF_LOGE("start test thread1 fail:%d", ret);
ret = HDF_FAILURE;
break;
}
ret = OsalThreadStart(&thread2, &cfg2);
if (ret != HDF_SUCCESS) {
HDF_LOGE("start test thread2 fail:%d", ret);
ret = HDF_FAILURE;
break;
}
while (g_theard1Flag == false || g_theard2Flag == false) {
HDF_LOGD("[%d]waitting testing timer thread finish...", time);
OsalSleep(TIMER_TEST_WAIT_TIMEOUT);
time++;
if (time > TIMER_TEST_WAIT_TIMES) {
break;
}
}
ret = HDF_SUCCESS;
} while(0);
if (handle1 != NULL) {
TimerClose(handle1);
handle1 = NULL;
}
if (handle2 != NULL) {
TimerClose(handle2);
handle2 = NULL;
}
if (thread1.realThread != NULL) {
(void)OsalThreadDestroy(&thread1);
}
if (thread2.realThread != NULL) {
(void)OsalThreadDestroy(&thread2);
}
g_theard1Flag = false;
g_theard2Flag = false;
return ret;
}
int32_t TimerTestReliability(struct TimerTest *test)
{
if (test == NULL || test->handle == NULL) {
HDF_LOGE("%s: test null", __func__);
return HDF_ERR_INVALID_OBJECT;
}
TimerSet(test->handle, test->uSecond, NULL);
TimerSetOnce(test->handle, test->uSecond, NULL);
TimerStart(NULL);
return HDF_SUCCESS;
}
static struct TimerTestFunc g_timerTestFunc[] = {
{TIMER_TEST_SET, TimerSetTest},
{TIMER_TEST_SETONCE, TimerSetOnceTest},
{TIMER_TEST_GET, TimerGetTest},
{TIMER_TEST_START, TimerStartTest},
{TIMER_TEST_STOP, TimerStopTest},
{TIMER_RELIABILITY_TEST, TimerTestMultiThread},
{TIMER_MULTI_THREAD_TEST, TimerTestReliability},
};
static int32_t TimerTestEntry(struct TimerTest *test, int32_t cmd)
{
int32_t i;
int32_t ret = HDF_ERR_NOT_SUPPORT;
if (test == NULL) {
HDF_LOGE("%s: test null cmd %d", __func__, cmd);
return HDF_ERR_INVALID_OBJECT;
}
if (cmd != TIMER_MULTI_THREAD_TEST) {
test->handle = TimerOpen(test->number);
if (test->handle == NULL) {
HDF_LOGE("%s: timer test get handle fail", __func__);
return HDF_FAILURE;
}
}
for (i = 0; i < sizeof(g_timerTestFunc) / sizeof(g_timerTestFunc[0]); i++) {
if (cmd == g_timerTestFunc[i].type && g_timerTestFunc[i].Func != NULL) {
ret = g_timerTestFunc[i].Func(test);
break;
}
}
if (cmd != TIMER_MULTI_THREAD_TEST) {
TimerClose(test->handle);
}
return ret;
}
static int32_t TimerTestBind(struct HdfDeviceObject *device)
{
static struct TimerTest test;
if (device != NULL) {
device->service = &test.service;
} else {
HDF_LOGE("%s: device is NULL", __func__);
}
HDF_LOGD("%s: success", __func__);
return HDF_SUCCESS;
}
static int32_t TimerTestInitFromHcs(struct TimerTest *test, const struct DeviceResourceNode *node)
{
int32_t ret;
struct DeviceResourceIface *face = NULL;
face = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
if (face == NULL) {
HDF_LOGE("%s: face is null", __func__);
return HDF_FAILURE;
}
if (face->GetUint32 == NULL) {
HDF_LOGE("%s: GetUint32 not support", __func__);
return HDF_ERR_NOT_SUPPORT;
}
ret = face->GetUint32(node, "number", &test->number, 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read id fail!", __func__);
return HDF_FAILURE;
}
ret = face->GetUint32(node, "useconds", &test->uSecond, 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read useconds fail!", __func__);
return HDF_FAILURE;
}
ret = face->GetUint32(node, "isPeriod", &test->isPeriod, 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read isPeriod fail!", __func__);
return HDF_FAILURE;
}
HDF_LOGD("timer test init:number[%u][%u][%d]", test->number, test->uSecond, test->isPeriod);
return HDF_SUCCESS;
}
static int32_t TimerTestInit(struct HdfDeviceObject *device)
{
struct TimerTest *test = NULL;
if (device == NULL || device->service == NULL || device->property == NULL) {
HDF_LOGE("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
test = (struct TimerTest *)device->service;
if (TimerTestInitFromHcs(test, device->property) != HDF_SUCCESS) {
HDF_LOGE("%s: RegulatorTestInitFromHcs failed", __func__);
return HDF_FAILURE;
}
test->TestEntry = TimerTestEntry;
g_theard1Flag = false;
g_theard2Flag = false;
HDF_LOGD("%s: success", __func__);
return HDF_SUCCESS;
}
static void TimerTestRelease(struct HdfDeviceObject *device)
{
(void)device;
}
struct HdfDriverEntry g_timerTestEntry = {
.moduleVersion = 1,
.Bind = TimerTestBind,
.Init = TimerTestInit,
.Release = TimerTestRelease,
.moduleName = "PLATFORM_TIMER_TEST",
};
HDF_INIT(g_timerTestEntry);

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef TIMER_TEST_H
#define TIMER_TEST_H
#include "hdf_device_desc.h"
#include "platform_if.h"
enum TimerTestCmd {
TIMER_START_TEST = 1,
TIMER_TEST_SET,
TIMER_TEST_SETONCE,
TIMER_TEST_GET,
TIMER_TEST_START,
TIMER_TEST_STOP,
TIMER_MULTI_THREAD_TEST,
TIMER_RELIABILITY_TEST,
};
#define TIMER_TEST_STACK_SIZE (1024 * 100)
#define TIMER_TEST_WAIT_TIMES 20
#define TIMER_TEST_WAIT_TIMEOUT 5
#define TIMER_TEST_PERIOD_TIMES 2
#define TIMER_TEST_TIME_ID_THREAD1 3
#define TIMER_TEST_TIME_ID_THREAD2 5
#define TIMER_TEST_TIME_USECONDS 5000
struct TimerTest {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
int32_t (*TestEntry)(struct TimerTest *test, int32_t cmd);
DevHandle handle;
uint32_t number;
uint32_t uSecond;
uint32_t isPeriod;
};
static inline struct TimerTest *GetTimerTest(void)
{
return (struct TimerTest *)DevSvcManagerClntGetService("TIMER_TEST");
}
#endif /* TIMER_TEST_H */

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "hdf_timer_entry_test.h"
#include "hdf_log.h"
#include "timer_test.h"
#define HDF_LOG_TAG hdf_timer_entry_test
int32_t HdfTimerUnitTestEntry(HdfTestMsg *msg)
{
struct TimerTest *test = NULL;
if (msg == NULL) {
return HDF_FAILURE;
}
test = GetTimerTest();
if (test == NULL || test->TestEntry == NULL) {
HDF_LOGE("%s: tester is NULL!\n", __func__);
msg->result = HDF_FAILURE;
return HDF_FAILURE;
}
msg->result = test->TestEntry(test, msg->subCmd);
return msg->result;
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef HDF_TIMER_ENTRY_TEST_H
#define HDF_TIMER_ENTRY_TEST_H
#include "hdf_main_test.h"
int32_t HdfTimerUnitTestEntry(HdfTestMsg *msg);
#endif /* HDF_TIMER_ENTRY_TEST_H */