diff --git a/docs/ChangeLog.md b/docs/ChangeLog.md index 0334c420990adc111acbe66837197a5d9c65b3e9..dd8f78379f7aef1414d1dc752b363962e7fd4ee7 100644 --- a/docs/ChangeLog.md +++ b/docs/ChangeLog.md @@ -1,3 +1,19 @@ +# Phytium FreeRTOS SDK 2024-04-23 ChangeLog + +Change Log since 2024-04-13 + +## example + +- modify pwm example, add no letter shell mode, adapt to auto-test system + +# Phytium FreeRTOS SDK 2024-04-22 ChangeLog + +Change Log since 2024-04-19 + +## example + +- modify gdma example, add no letter shell mode, adapt to auto-test system + # Phytium FreeRTOS SDK 2024-04-19 ChangeLog Change Log since 2024-04-19 diff --git a/example/peripheral/dma/gdma/README.md b/example/peripheral/dma/gdma/README.md index 8774ef63a1582c9f4ebc93f251fd47d277cd3112..ad0b2b9eb9ed57f581dc6df3f219074fd3d1566d 100644 --- a/example/peripheral/dma/gdma/README.md +++ b/example/peripheral/dma/gdma/README.md @@ -95,7 +95,7 @@ bootelf -p 0xa0100000 ### 2.4 输出与实验现象 -- 系统进入后,创建任务 GDMA,将启动任务A和任务B,分别搬运数据 +- 系统进入后,创建任务 GDMA MEMCPY 任务,随后自动完成搬运 ``` gdma memcpy @@ -107,8 +107,4 @@ gdma memcpy ## 3. 如何解决问题 -## 4. 修改历史记录 - - - - +## 4. 修改历史记录 \ No newline at end of file diff --git a/example/peripheral/dma/gdma/figs/memcpy_result.png b/example/peripheral/dma/gdma/figs/memcpy_result.png index 0b7acb7842d131e2b7ab91c728266f257f6144b5..f1c4580d446c72ca2377aea53269540af059f62b 100644 Binary files a/example/peripheral/dma/gdma/figs/memcpy_result.png and b/example/peripheral/dma/gdma/figs/memcpy_result.png differ diff --git a/example/peripheral/dma/gdma/inc/gdma_memcpy.h b/example/peripheral/dma/gdma/inc/gdma_memcpy.h index 90ffb99e81a245b8a52f7ab10df4db30839255cc..904700ffb160ea854d609681b928d766dc9e5306 100644 --- a/example/peripheral/dma/gdma/inc/gdma_memcpy.h +++ b/example/peripheral/dma/gdma/inc/gdma_memcpy.h @@ -17,18 +17,21 @@ * Description:  This file is for task create function define * * Modify History: - * Ver   Who        Date         Changes - * ----- ------     --------    -------------------------------------- - * 1.0 zhugengyu 2022/08/26 first commit + * Ver    Who         Date         Changes + * -----  ------      --------     -------------------------------------- + * 1.0 zhugengyu 2022/7/27 init commit + * 3.0 liqiaozhong 2024/4/22 add no letter shell mode, adapt to auto-test system */ -#ifndef GDMA_MEMCPY_H -#define GDMA_MEMCPY_H + +#ifndef GDMA_MEMCPY_H +#define GDMA_MEMCPY_H + +#include "FreeRTOS.h" #ifdef __cplusplus extern "C" { #endif - /***************************** Include Files *********************************/ /************************** Constant Definitions *****************************/ diff --git a/example/peripheral/dma/gdma/main.c b/example/peripheral/dma/gdma/main.c index add4a08b7a03d5ecb085bf35e8da4813ac15d1b9..97ae6397628769e31298e354ea280a58155d0ddb 100644 --- a/example/peripheral/dma/gdma/main.c +++ b/example/peripheral/dma/gdma/main.c @@ -16,31 +16,64 @@ * LastEditTime: 2022-06-17 08:17:59 * Description: This file is for gdma example that running shell task and open scheduler * - * Modify History: - * Ver Who Date Changes - * ----- ------ -------- -------------------------------------- + * Modify History: + * Ver    Who         Date         Changes + * -----  ------      --------     -------------------------------------- + * 1.0 zhugengyu 2022/7/27 init commit + * 2.0 liqiaozhong 2023/11/10 synchronous update with standalone sdk + * 3.0 liqiaozhong 2024/4/22 add no letter shell mode, adapt to auto-test system */ +#include + +#include "FreeRTOS.h" + +#include "sdkconfig.h" + +#ifdef CONFIG_USE_LETTER_SHELL #include "shell.h" #include "shell_port.h" -#include +#else +#include "task.h" +#include "gdma_memcpy.h" -int main(void) +#define GDMA_EXAMPLE_TASK_PRIORITY 2 + +void GdmaExampleTaskEntry() { - BaseType_t ret; + /* example functions */ + FFreeRTOSRunGdmaMemcpy(); - ret = LSUserShellTask() ; + /* end flag */ + printf("[test_end]\r\n"); + vTaskDelete(NULL); +} +#endif + +int main(void) +{ + BaseType_t ret = pdPASS; /* 定义一个创建信息返回值,默认为 pdPASS */ +#ifdef CONFIG_USE_LETTER_SHELL + ret = LSUserShellTask(); +#else + /* used in no-letter-shell mode */ + ret = xTaskCreate((TaskFunction_t)GdmaExampleTaskEntry, /* 任务入口函数 */ + (const char *)"GdmaExampleTaskEntry", /* 任务名字 */ + (uint16_t)4096, /* 任务栈大小 */ + NULL, /* 任务入口函数参数 */ + (UBaseType_t)GDMA_EXAMPLE_TASK_PRIORITY, /* 任务优先级 */ + NULL); /* 任务句柄 */ +#endif if (ret != pdPASS) { goto FAIL_EXIT; } - /* ret = FFreeRTOSRunGdmaMemcpy(); */ - - vTaskStartScheduler(); /* 启动任务,开启调度 */ + /* 启动任务,开启调度 */ + vTaskStartScheduler(); while (1); /* 正常不会执行到这里 */ FAIL_EXIT: - printf("failed 0x%x \r\n", ret); + printf("GDMA example failed in main.c, the ret value is 0x%x. \r\n", ret); return 0; -} +} \ No newline at end of file diff --git a/example/peripheral/dma/gdma/src/cmd_gdma.c b/example/peripheral/dma/gdma/src/cmd_gdma.c index 0883c6219be7ed5d5204923d94a10ab2e9e5d201..c13dc78a0af44dd59b3e9fa202497c41ab53606c 100644 --- a/example/peripheral/dma/gdma/src/cmd_gdma.c +++ b/example/peripheral/dma/gdma/src/cmd_gdma.c @@ -17,20 +17,18 @@ * Description:  This files is for gdma command interface * * Modify History: - * Ver   Who        Date         Changes - * ----- ------     --------    -------------------------------------- - * 1.0 zhugengyu 2022/08/26 first commit + * Ver    Who         Date         Changes + * -----  ------      --------     -------------------------------------- + * 1.0 zhugengyu 2022/7/27 init commit + * 2.0 liqiaozhong 2024/4/22 add no letter shell mode, adapt to auto-test system */ + /***************************** Include Files *********************************/ -#include #include +#include #include "strto.h" -#include "sdkconfig.h" -#include "FreeRTOS.h" - -#include "../src/shell.h" -#include "gdma_memcpy.h" +#include "sdkconfig.h" /************************** Constant Definitions *****************************/ /************************** Variable Definitions *****************************/ @@ -40,16 +38,28 @@ /************************** Function Prototypes ******************************/ /*****************************************************************************/ +#ifdef CONFIG_USE_LETTER_SHELL +#include "../src/shell.h" + +#include "gdma_memcpy.h" + +static void SfudCmdUsage() +{ + printf("Usage:\r\n"); + printf("gdma memcpy\r\n"); + printf("-- Run GDMA memcpy example\r\n"); +} + static int GdmaCmdEntry(int argc, char *argv[]) { int ret = 0; if (!strcmp(argv[1], "memcpy")) { - ret = FFreeRTOSRunGdmaMemcpy(); } return ret; } -SHELL_EXPORT_CMD(SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), gdma, GdmaCmdEntry, test freertos gdma driver); \ No newline at end of file +SHELL_EXPORT_CMD(SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), gdma, GdmaCmdEntry, test freertos gdma driver); +#endif \ No newline at end of file diff --git a/example/peripheral/dma/gdma/src/gdma_memcpy.c b/example/peripheral/dma/gdma/src/gdma_memcpy.c index 487e65d36b825138b419aa6ce5a48495bb9aa718..fa14e616ed53d5a66a908a16824dd385e7dbfbdc 100644 --- a/example/peripheral/dma/gdma/src/gdma_memcpy.c +++ b/example/peripheral/dma/gdma/src/gdma_memcpy.c @@ -21,7 +21,9 @@ * -----  ------      --------     -------------------------------------- * 1.0 zhugengyu 2022/7/27 init commit * 2.0 liqiaozhong 2023/11/10 synchronous update with standalone sdk + * 3.0 liqiaozhong 2024/4/22 add no letter shell mode, adapt to auto-test system */ + /***************************** Include Files *********************************/ #include #include @@ -32,409 +34,209 @@ #include "queue.h" #include "fkernel.h" -#include "fcache.h" #include "fassert.h" #include "fdebug.h" -#include "fio_mux.h" #include "fgdma_os.h" /************************** Constant Definitions *****************************/ -#define FGDMA_CONTROLLER_ID FGDMA0_ID -#define GDMA_CHAN_TRANS_END(chan) (0x1U << (chan)) -#define GDMA_TASKA_CHANNEL_ID 0U -#define GDMA_TASKB_CHANNEL_ID 1U -#define GDMA_TASKA_TRANS_LEN 256U -#define GDMA_TASKB_TRANS_LEN 1024U -#define GDMA_WORK_TASK_NUM 2U -#define GDMA_TRANS_TIMES 3U -/**************************** Type Definitions *******************************/ - -/************************** Variable Definitions *****************************/ -static FFreeRTOSGdma *gdma_instance_p = NULL; -static FFreeRTOSGdmaChanCfg os_channel_config_taska; -static FFreeRTOSGdmaChanCfg os_channel_config_taskb; -static TaskHandle_t task_a = NULL; -static TaskHandle_t task_b = NULL; -static TimerHandle_t exit_timer = NULL; -static EventGroupHandle_t chan_evt = NULL; -static xSemaphoreHandle gdma_task_counter = NULL; -static uint8_t src_a[GDMA_TASKA_TRANS_LEN] __attribute__((aligned(16))) = {0U}; /* should be aligned with both read and write burst size, defalut: 16-byte */ -static uint8_t dst_a[GDMA_TASKA_TRANS_LEN] __attribute__((aligned(16))) = {0U}; -static uint8_t src_b[GDMA_TASKB_TRANS_LEN] __attribute__((aligned(16))) = {0U}; -static uint8_t dst_b[GDMA_TASKB_TRANS_LEN] __attribute__((aligned(16))) = {0U}; -static uint32_t chan_evt_bits = 0U; /* bits that indicate GDMA_CHAN_TRANS_END */ -static bool is_running = FALSE; -/***************** Macros (Inline Functions) Definitions *********************/ #define FGDMA_DEBUG_TAG "GDMA-MEM" #define FGDMA_ERROR(format, ...) FT_DEBUG_PRINT_E(FGDMA_DEBUG_TAG, format, ##__VA_ARGS__) #define FGDMA_WARN(format, ...) FT_DEBUG_PRINT_W(FGDMA_DEBUG_TAG, format, ##__VA_ARGS__) #define FGDMA_INFO(format, ...) FT_DEBUG_PRINT_I(FGDMA_DEBUG_TAG, format, ##__VA_ARGS__) #define FGDMA_DEBUG(format, ...) FT_DEBUG_PRINT_D(FGDMA_DEBUG_TAG, format, ##__VA_ARGS__) -/************************** Function Prototypes ******************************/ -/*****************************************************************************/ -static void GdmaMemcpyExitCallback(TimerHandle_t timer) +/* user-define */ +#define FGDMA_CONTROLLER_ID FGDMA0_ID +#define GDMA_CHANNEL_ID 0U +#define GDMA_TRANS_LEN 1024U +#define GDMA_ADDR_ALIGNMENT 16U +#define GDMA_MEMCPY_TASK_PRIORITY 3 +#define TIMER_OUT (pdMS_TO_TICKS(4000UL)) +/**************************** Type Definitions *******************************/ +enum { - printf("exiting...\r\n"); + GDMA_MEMCPY_SUCCESS = 1, + GDMA_INIT_FAILURE = 2, + GDMA_MEMCPY_FAILURE = 3, +}; +/************************** Variable Definitions *****************************/ +static FFreeRTOSGdma *gdma_instance_p = NULL; +static FFreeRTOSGdmaChanCfg os_channel_config; +static TaskHandle_t gdma_trans_task = NULL; +const UBaseType_t gdma_trans_task_index = 0; /* the index must set to 0 */ +static QueueHandle_t xQueue = NULL; +static uint8_t src_data[GDMA_TRANS_LEN] __attribute__((aligned(GDMA_ADDR_ALIGNMENT))) = {0U}; /* should be aligned with both read and write burst size, defalut: 16-byte */ +static uint8_t dst_data[GDMA_TRANS_LEN] __attribute__((aligned(GDMA_ADDR_ALIGNMENT))) = {0U}; +/***************** Macros (Inline Functions) Definitions *********************/ - if (task_a) /* stop and delete send task */ - { - vTaskDelete(task_a); - task_a = NULL; - } +/**************************** Function Prototypes ****************************/ - if (task_b) /* stop and delete recv task */ - { - vTaskDelete(task_b); - task_a = NULL; - } +/*************************** Function Definitions ****************************/ +static void GdmaMemcpyAckChanXEnd(uint32_t channel_id, void *args) +{ + FASSERT(channel_id < FFREERTOS_GDMA_NUM_OF_CHAN); - if (chan_evt) - { - vEventGroupDelete(chan_evt); - chan_evt = NULL; - chan_evt_bits = 0U; - } + BaseType_t xhigher_priority_task_woken = pdFALSE; + BaseType_t x_result = pdFALSE; - if (gdma_task_counter) - { - vSemaphoreDelete(gdma_task_counter); - gdma_task_counter = NULL; - } + FGDMA_INFO("FreeRTOS ack: GDMA channel-%d transfer end.", channel_id); - if (gdma_instance_p) - { - if (FFREERTOS_GDMA_OK != FFreeRTOSGdmaDeInit(gdma_instance_p)) - { - FGDMA_ERROR("Deinit GDMA instance failed."); - } - gdma_instance_p = NULL; - } + vTaskNotifyGiveIndexedFromISR(gdma_trans_task, gdma_trans_task_index, &xhigher_priority_task_woken); + gdma_trans_task = NULL; /* 将目标任务句柄清空,防止产生不必要的通知 */ + portYIELD_FROM_ISR(xhigher_priority_task_woken); /* 如果中断触发了更高优先级的任务,确保更高优先级的任务尽快执行 */ - if (exit_timer) - { - if (pdPASS != xTimerDelete(exit_timer, 0)) - { - FGDMA_ERROR("Delete exit timer failed."); - } - exit_timer = NULL; - } + return; +} + +static int GdmaInit(void) +{ + int task_res = GDMA_MEMCPY_SUCCESS; - is_running = FALSE; + gdma_instance_p = FFreeRTOSGdmaInit(FGDMA_CONTROLLER_ID); + + return task_res; } -static void GdmaMemcpyAckChanXEnd(uint32_t channel_id, void *args) +static int GdmaMemcpy(void) { - FASSERT(channel_id < FFREERTOS_GDMA_NUM_OF_CHAN); + int task_res = GDMA_MEMCPY_SUCCESS; + uint32_t notify_result; + FError err = FFREERTOS_GDMA_OK; + const TickType_t max_block_time = pdMS_TO_TICKS(3000UL); - BaseType_t xhigher_priority_task_woken = pdFALSE; - BaseType_t x_result = pdFALSE; + /* os channel config set */ + os_channel_config.trans_mode = FFREERTOS_GDMA_OPER_DIRECT; + os_channel_config.src_addr = (uintptr_t)src_data; + os_channel_config.dst_addr = (uintptr_t)dst_data; + os_channel_config.trans_length = GDMA_TRANS_LEN; - FGDMA_INFO("FreeRTOS ack: GDMA chan-%d transfer end.", channel_id); - x_result = xEventGroupSetBitsFromISR(chan_evt, GDMA_CHAN_TRANS_END(channel_id), &xhigher_priority_task_woken); - - if (x_result == pdFALSE) + err = FFreeRTOSGdmaChanConfigure(gdma_instance_p, GDMA_CHANNEL_ID, &os_channel_config); + if (FFREERTOS_GDMA_OK != err) { - FGDMA_ERROR("xEventGroupSetBitsFromISR() fail."); + FGDMA_ERROR("FFreeRTOSGdmaChanConfigure() failed."); + goto memcpy_exit; } - portYIELD_FROM_ISR(xhigher_priority_task_woken); - - return; -} + FFreeRTOSGdmaChanRegisterEvtHandler(gdma_instance_p, + GDMA_CHANNEL_ID, + FFREERTOS_GDMA_CHAN_EVT_TRANS_END, + GdmaMemcpyAckChanXEnd, + NULL); -static unsigned long GdmaMemcpyWaitChanXEnd(uint32_t channel_id) -{ - FASSERT(channel_id < FFREERTOS_GDMA_NUM_OF_CHAN); + memset((void *)src_data, 'A', GDMA_TRANS_LEN); + memset((void *)dst_data, 0, GDMA_TRANS_LEN); - EventBits_t evt_result; + gdma_trans_task = xTaskGetCurrentTaskHandle(); /* store the handle of the calling task. */ - /* block task to wait memcpy finish signal */ - evt_result = xEventGroupWaitBits(chan_evt, GDMA_CHAN_TRANS_END(channel_id), - pdTRUE, pdTRUE, pdMS_TO_TICKS(5000UL)); /* wait for channel end event bit(5s) */ - if ((evt_result & GDMA_CHAN_TRANS_END(channel_id))) /* wait until channel finished memcpy */ + FFreeRTOSGdmaChanStart(gdma_instance_p, GDMA_CHANNEL_ID); + + notify_result = ulTaskNotifyTakeIndexed(gdma_trans_task_index, pdTRUE, max_block_time); /* wait to be notified that the transmission is complete */ + if (notify_result != 1) { - FGDMA_INFO("GDMA memcpy finished. Channel bits: 0x%x.", chan_evt_bits); - return TRUE; + err = FFREERTOS_GDMA_MEMCPY_FAIL; + FGDMA_ERROR("Wait GDMA finish timeout."); + goto memcpy_exit; + } + + /* compare if memcpy success */ + if (0 == memcmp(src_data, dst_data, GDMA_TRANS_LEN)) + { + taskENTER_CRITICAL(); + printf("src buf...\r\n"); + FtDumpHexByte((const uint8_t *)src_data, min((size_t)GDMA_TRANS_LEN, (size_t)64U)); + printf("dst buf...\r\n"); + FtDumpHexByte((const uint8_t *)dst_data, min((size_t)GDMA_TRANS_LEN, (size_t)64U)); + taskEXIT_CRITICAL(); } else { - FGDMA_ERROR("Wait GDMA memcpy timeout. Channel bits: 0x%x, correct value: 0x%x.", evt_result, chan_evt_bits); - return FALSE; + FGDMA_ERROR("src != dst, GDMA memcpy failed."); + goto memcpy_exit; } - return TRUE; -} - -static void GdmaInitTask(void *args) -{ - gdma_instance_p = FFreeRTOSGdmaInit(FGDMA_CONTROLLER_ID); - FASSERT_MSG(gdma_instance_p, "Init gdma controller failed."); - - FASSERT_MSG(gdma_task_counter, "GDMA task counter does not exist."); - for (size_t loop = 0; loop < GDMA_WORK_TASK_NUM; loop++) +memcpy_exit: + if (FFREERTOS_GDMA_OK != FFreeRTOSGdmaChanStop(gdma_instance_p, GDMA_CHANNEL_ID)) { - xSemaphoreGive(gdma_task_counter); + FGDMA_ERROR("FFreeRTOSGdmaChanStop() failed."); } - vTaskDelete(NULL); -} - -static void GdmaMemcpyTaskA(void *args) -{ - FASSERT_MSG(gdma_task_counter, "GDMA task counter does not exist."); - - xSemaphoreTake(gdma_task_counter, portMAX_DELAY); - - char ch = 'A'; - uint8_t times = 0U; - FError err = FFREERTOS_GDMA_OK; - - for (;;) + if (FFREERTOS_GDMA_OK != FFreeRTOSGdmaChanDeconfigure(gdma_instance_p, GDMA_CHANNEL_ID)) { - /* os channel config set */ - os_channel_config_taska.trans_mode = FFREERTOS_GDMA_OPER_DIRECT; - os_channel_config_taska.src_addr = (uintptr_t)src_a; - os_channel_config_taska.dst_addr = (uintptr_t)dst_a; - os_channel_config_taska.trans_length = GDMA_TASKA_TRANS_LEN; - - err = FFreeRTOSGdmaChanConfigure(gdma_instance_p, GDMA_TASKA_CHANNEL_ID, &os_channel_config_taska); - if (FFREERTOS_GDMA_OK != err) - { - FGDMA_ERROR("FFreeRTOSGdmaChanConfigure in channel-%d failed.", GDMA_TASKA_CHANNEL_ID); - goto task_err; - } - - FFreeRTOSGdmaChanRegisterEvtHandler(gdma_instance_p, - GDMA_TASKA_CHANNEL_ID, - FFREERTOS_GDMA_CHAN_EVT_TRANS_END, - GdmaMemcpyAckChanXEnd, - NULL); - - ch = (char)('A' + (times) % 10); /* send different content each time */ - - memset((void *)src_a, ch, GDMA_TASKA_TRANS_LEN); - memset((void *)dst_a, 0, GDMA_TASKA_TRANS_LEN); - - /* Memory barrier operation */ - FCacheDCacheInvalidateRange((uintptr_t)src_a, GDMA_TASKA_TRANS_LEN); - FCacheDCacheInvalidateRange((uintptr_t)dst_a, GDMA_TASKA_TRANS_LEN); - - FGDMA_INFO("[Task-A]start GDMA memcpy data ..."); - FFreeRTOSGdmaChanStart(gdma_instance_p, GDMA_TASKA_CHANNEL_ID); - - /* recv task has high priority, send task will not run before recv task blocked */ - if (!GdmaMemcpyWaitChanXEnd(GDMA_TASKA_CHANNEL_ID)) - { - goto task_err; - } - - FCacheDCacheInvalidateRange((uintptr)src_a, GDMA_TASKA_TRANS_LEN); - FCacheDCacheInvalidateRange((uintptr)dst_a, GDMA_TASKA_TRANS_LEN); - - /* compare if memcpy success */ - if (0 == memcmp(src_a, dst_a, GDMA_TASKA_TRANS_LEN)) - { - taskENTER_CRITICAL(); - printf("\r\n[Task-A]GDMA memcpy success.\r\n"); - printf("[Task-A]src buf...\r\n"); - FtDumpHexByte((const uint8_t *)src_a, min((size_t)GDMA_TASKA_TRANS_LEN, (size_t)64U)); - printf("[Task-A]dst buf...\r\n"); - FtDumpHexByte((const uint8_t *)dst_a, min((size_t)GDMA_TASKA_TRANS_LEN, (size_t)64U)); - taskEXIT_CRITICAL(); - } - else - { - FGDMA_ERROR("[Task-A]src != dst, GDMA memcpy failed."); - goto task_err; - } - - err = FFreeRTOSGdmaChanStop(gdma_instance_p, GDMA_TASKA_CHANNEL_ID); - if (FFREERTOS_GDMA_OK != err) - { - FGDMA_ERROR("FFreeRTOSGdmaChanStop in channel-%d failed.", GDMA_TASKA_CHANNEL_ID); - goto task_err; - } - - err = FFreeRTOSGdmaChanDeconfigure(gdma_instance_p, GDMA_TASKA_CHANNEL_ID); - if (FFREERTOS_GDMA_OK != err) - { - FGDMA_ERROR("FFreeRTOSGdmaChanDeconfigure in channel-%d failed.", GDMA_TASKA_CHANNEL_ID); - goto task_err; - } - - if (times++ > GDMA_TRANS_TIMES) - { - break; - } - - vTaskDelay(pdMS_TO_TICKS(2000U)); /* wait for 2 seconds */ + FGDMA_ERROR("FFreeRTOSGdmaChanDeconfigure() failed."); } -task_err: - (void)FFreeRTOSGdmaChanDeconfigure(gdma_instance_p, GDMA_TASKA_CHANNEL_ID); - printf("[Task-A]exit from GDMA memcpy task.\r\n"); - vTaskSuspend(NULL); /* failed, not able to run, suspend task itself */ + return task_res; } -static void GdmaMemcpyTaskB(void *args) +static void GdmaMemcpyTask() { - FASSERT_MSG(gdma_task_counter, "GDMA task counter does not exist."); - - xSemaphoreTake(gdma_task_counter, portMAX_DELAY); + int task_res = GDMA_MEMCPY_SUCCESS; - char ch = '0'; - uint8_t times = 0U; - FError err = FFREERTOS_GDMA_OK; + task_res = GdmaInit(); + if (task_res != GDMA_MEMCPY_SUCCESS) + { + FGDMA_ERROR("GdmaInit() failed."); + goto task_exit; + } - for (;;) + task_res = GdmaMemcpy(); + if (task_res != GDMA_MEMCPY_SUCCESS) { - /* os channel config set */ - os_channel_config_taskb.trans_mode = FFREERTOS_GDMA_OPER_BDL; - os_channel_config_taskb.src_addr = (uintptr_t)src_b; - os_channel_config_taskb.dst_addr = (uintptr_t)dst_b; - os_channel_config_taskb.trans_length = GDMA_TASKB_TRANS_LEN; - - err = FFreeRTOSGdmaChanConfigure(gdma_instance_p, GDMA_TASKB_CHANNEL_ID, &os_channel_config_taskb); - if (FFREERTOS_GDMA_OK != err) - { - FGDMA_ERROR("FFreeRTOSGdmaChanConfigure in channel-%d failed.", GDMA_TASKB_CHANNEL_ID); - goto task_err; - } - - FFreeRTOSGdmaChanRegisterEvtHandler(gdma_instance_p, - GDMA_TASKB_CHANNEL_ID, - FFREERTOS_GDMA_CHAN_EVT_TRANS_END, - GdmaMemcpyAckChanXEnd, - NULL); - - ch = (char)('0' + (times) % 10); /* send different content each time */ - - memset((void *)src_b, ch, GDMA_TASKB_TRANS_LEN); - memset((void *)dst_b, 0, GDMA_TASKB_TRANS_LEN); - - /* Memory barrier operation */ - FCacheDCacheInvalidateRange((uintptr_t)src_b, GDMA_TASKB_TRANS_LEN); - FCacheDCacheInvalidateRange((uintptr_t)dst_b, GDMA_TASKB_TRANS_LEN); - - FGDMA_INFO("[Task-B]start GDMA memcpy data ..."); - FFreeRTOSGdmaChanStart(gdma_instance_p, GDMA_TASKB_CHANNEL_ID); - - /* recv task has high priority, send task will not run before recv task blocked */ - if (!GdmaMemcpyWaitChanXEnd(GDMA_TASKB_CHANNEL_ID)) - { - goto task_err; - } - - FCacheDCacheInvalidateRange((uintptr)src_b, GDMA_TASKB_TRANS_LEN); - FCacheDCacheInvalidateRange((uintptr)dst_b, GDMA_TASKB_TRANS_LEN); - - /* compare if memcpy success */ - if (0 == memcmp(src_a, dst_a, GDMA_TASKB_TRANS_LEN)) - { - taskENTER_CRITICAL(); - printf("\r\n[Task-B]GDMA memcpy success.\r\n"); - printf("[Task-B]src buf...\r\n"); - FtDumpHexByte((const uint8_t *)src_b, min((size_t)GDMA_TASKB_TRANS_LEN, (size_t)64U)); - printf("[Task-B]dst buf...\r\n"); - FtDumpHexByte((const uint8_t *)dst_b, min((size_t)GDMA_TASKB_TRANS_LEN, (size_t)64U)); - taskEXIT_CRITICAL(); - } - else - { - FGDMA_ERROR("[TaskB]src != dst, GDMA memcpy failed."); - goto task_err; - } - - err = FFreeRTOSGdmaChanStop(gdma_instance_p, GDMA_TASKB_CHANNEL_ID); - if (FFREERTOS_GDMA_OK != err) - { - FGDMA_ERROR("FFreeRTOSGdmaChanStop in channel-%d failed.", GDMA_TASKB_CHANNEL_ID); - goto task_err; - } - - err = FFreeRTOSGdmaChanDeconfigure(gdma_instance_p, GDMA_TASKB_CHANNEL_ID); - if (FFREERTOS_GDMA_OK != err) - { - FGDMA_ERROR("FFreeRTOSGdmaChanDeconfigure in channel-%d failed.", GDMA_TASKB_CHANNEL_ID); - goto task_err; - } - - if (times++ > GDMA_TRANS_TIMES) - { - break; - } - - vTaskDelay(pdMS_TO_TICKS(2000U)); /* wait for 2 seconds */ + FGDMA_ERROR("GdmaMemcpy() failed."); + goto task_exit; } -task_err: - (void)FFreeRTOSGdmaChanDeconfigure(gdma_instance_p, GDMA_TASKB_CHANNEL_ID); - printf("[Task-B]exit from GDMA memcpy task.\r\n"); - vTaskSuspend(NULL); /* failed, not able to run, suspend task itself */ +task_exit: + xQueueSend(xQueue, &task_res, 0); + + vTaskDelete(NULL); } BaseType_t FFreeRTOSRunGdmaMemcpy(void) { - BaseType_t ret = pdPASS; - const TickType_t total_run_time = pdMS_TO_TICKS(30000UL); /* loopback run for 30 secs deadline */ + BaseType_t xReturn = pdPASS; /* 定义一个创建信息返回值,默认为 pdPASS */ + int task_res = 0; - if (is_running) + xQueue = xQueueCreate(1, sizeof(int)); /* 创建消息队列 */ + if (xQueue == NULL) { - FGDMA_ERROR("task is running, please wait for the program to complete."); - return pdPASS; + FGDMA_ERROR("xQueue create failed."); + goto exit; } - is_running = TRUE; - - FASSERT_MSG(NULL == chan_evt, "Event group has been created aready."); - FASSERT_MSG((chan_evt = xEventGroupCreate()) != NULL, "Create event group failed."); - - FASSERT_MSG(NULL == gdma_task_counter, "GDMA task counter has been created aready."); - FASSERT_MSG((gdma_task_counter = xSemaphoreCreateCounting(GDMA_WORK_TASK_NUM, 0U)) != NULL, "create event group failed !!!"); - - taskENTER_CRITICAL(); /* no schedule when create task */ - - ret = xTaskCreate((TaskFunction_t)GdmaInitTask, /* task entry */ - (const char *)"GdmaInitTask",/* task name */ - (uint16_t)1024, /* task stack size in words */ - NULL, /* task params */ - (UBaseType_t)configMAX_PRIORITIES - 1, /* task priority */ - NULL); /* task handler */ - - FASSERT_MSG(pdPASS == ret, "create task failed"); - - ret = xTaskCreate((TaskFunction_t)GdmaMemcpyTaskA, /* task entry */ - (const char *)"GdmaMemcpyTaskA",/* task name */ - (uint16_t)4096, /* task stack size in words */ - NULL, /* task params */ - (UBaseType_t)configMAX_PRIORITIES - 1, /* task priority */ - (TaskHandle_t *)&task_a); /* task handler */ - - FASSERT_MSG(pdPASS == ret, "create task failed"); - - ret = xTaskCreate((TaskFunction_t)GdmaMemcpyTaskB, /* task entry */ - (const char *)"GdmaMemcpyTaskB",/* task name */ - (uint16_t)4096, /* task stack size in words */ - NULL, /* task params */ - (UBaseType_t)configMAX_PRIORITIES - 2, /* task priority */ - (TaskHandle_t *)&task_b); /* task handler */ - - FASSERT_MSG(pdPASS == ret, "create task failed"); - - exit_timer = xTimerCreate("Exit-Timer", /* Text name for the software timer - not used by FreeRTOS. */ - total_run_time, /* The software timer's period in ticks. */ - pdFALSE, /* Setting uxAutoRealod to pdFALSE creates a one-shot software timer. */ - NULL, /* use timer id to pass task data for reference. */ - GdmaMemcpyExitCallback); /* The callback function to be used by the software timer being created. */ - - FASSERT_MSG(NULL != exit_timer, "create exit timer failed"); - - taskEXIT_CRITICAL(); /* allow schedule since task created */ + xReturn = xTaskCreate((TaskFunction_t)GdmaMemcpyTask, /* 任务入口函数 */ + (const char *)"GdmaMemcpyTask", /* 任务名字 */ + (uint16_t)4096, /* 任务栈大小 */ + NULL, /* 任务入口函数参数 */ + (UBaseType_t)GDMA_MEMCPY_TASK_PRIORITY, /* 任务优先级 */ + NULL); /* 任务句柄 */ + if (xReturn == pdFAIL) + { + FGDMA_ERROR("xTaskCreate GdmaMemcpyTask failed."); + goto exit; + } - ret = xTimerStart(exit_timer, 0); /* start */ + xReturn = xQueueReceive(xQueue, &task_res, TIMER_OUT); + if (xReturn == pdFAIL) + { + FGDMA_ERROR("xQueue receive timeout."); + goto exit; + } - FASSERT_MSG(pdPASS == ret, "start exit timer failed"); + exit: + if (xQueue != NULL) + { + vQueueDelete(xQueue); + } - return ret; + if (task_res != GDMA_MEMCPY_SUCCESS) + { + printf("%s@%d: GDMA memcpy example [failure], task_res = %d\r\n", __func__, __LINE__, task_res); + return pdFAIL; + } + else + { + printf("%s@%d: GDMA memcpy example [success].\r\n", __func__, __LINE__); + return pdTRUE; + } } \ No newline at end of file diff --git a/example/peripheral/pwm/README.md b/example/peripheral/pwm/README.md index 91f14ad15356b9c6e6086a18a975ea7f070a21ef..7924b0bf142b87786cc931325ddb4cc553a4292e 100644 --- a/example/peripheral/pwm/README.md +++ b/example/peripheral/pwm/README.md @@ -2,31 +2,44 @@ ## 1. 例程介绍 -本例程示范了freertos环境下的pwm的使用,包括pwm的初始化、pwm占空比周期变化操作; -程序启动后,创建pwm初始化任务,设置pwm时钟分频、周期和占空比等; -创建pwm占空比变化任务FFreeRTOSPwmChangeTask,用于定时变化pwm占空比; -创建单次模式的软件定时器,回调函数为删除FFreeRTOSPwmChangeTask,去初始化pwm,删除软件定时器; 注:E2000共有8个PWM控制器(PWM0~PWM7),每个PWM控制器对应两路CHANNEL -## 2. 如何使用例程 +PWM单通道测试例程 (pwm_single_channel_example.c) -本例程需要用到 -- Phytium开发板(E2000D/E2000Q/PhytiumPi) -- [Phytium freeRTOS SDK](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk) -- [Phytium standalone SDK](https://gitee.com/phytium_embedded/phytium-standalone-sdk) -### 2.1 硬件配置方法 +- 初始化PWM基本配置 +- 对CHANNEL0进行配置,设置为500分频,设置周期寄存器的值为10000(100ms),设置初始脉冲为2000,即初始占空比为20% +- 打开CHANNEL0 COUNTER_OVERFLOW中断和FIFO_EMPTY中断 +- 使能CHANNEL0,脉冲值每隔500ms增加1000,共进行5次变化,每次占空比增加10%,观察输出波形的变化 +- 关闭CHANNEL0,去初始化PWM -本例程支持的硬件平台包括 +PWM死区测试例程 (pwm_dead_band_example.c) -- E2000D -- E2000Q -- PhytiumPi +- 初始化PWM基本配置 +- 对死区进行配置,上升沿和下降沿均打开延迟,延迟配置为800,极性不进行翻转,死区输入源默认选择为pwm0(CHANNEL0),pwm1(CHANNEL1)根据输入源和死区属性的配置输出相应波形 +- 对CHANNEL0进行配置,设置为500分频,设置周期寄存器的值为10000(100ms),设置初始脉冲为2000,即初始占空比为20% +- 使能CHANNEL0,脉冲值每隔500ms增加1000,共进行5次变化,每次占空比增加10%,观察输出波形的变化 +- CHANNEL1作为死区输出,观察死区输出波形的变化 +- 关闭CHANNEL0,去初始化PWM -对应的配置项是, +PWM双通道测试例程 (pwm_dual_channel_example.c) + +- 初始化PWM基本配置 +- 对CHANNEL0进行配置,设置为500分频,设置周期寄存器的值为10000(100ms),设置初始脉冲为2000,即初始占空比为20% +- 对CHANNEL1进行配置,设置为1000分频,设置周期寄存器的值为20000(400ms),设置初始脉冲为2000,即初始占空比为10% +- 打开CHANNEL0和CHANNEL1 COUNTER_OVERFLOW中断和FIFO_EMPTY中断 +- 使能CHANNEL0,脉冲值每隔500ms增加1000,共进行5次变化,每次占空比增加10%,观察输出波形的变化 +- 使能CHANNEL1,脉冲值每隔500ms增加1000,共进行5次变化,每次占空比增加5%,观察输出波形的变化 +- 关闭CHANNEL0和CHANNEL1,去初始化PWM + +## 2. 如何使用例程 + +本例程需要以下硬件, -- CONFIG_TARGET_E2000D -- CONFIG_TARGET_E2000Q -- CONFIG_TARGET_PHYTIUMPI +- E2000D/Q demo板,PhytiumPi +- 串口线和串口上位机 +- 逻辑分析仪/示波器 +- 杜邦线 +### 2.1 硬件配置方法 ### 2.1.1 E2000 - E2000 demo板需外接逻辑分析仪或示波器测试,方法如下 @@ -40,10 +53,6 @@ ### 2.1.2 PhytiumPi - PhytiumPi需外接逻辑分析仪或示波器测试,方法如下 -- PhytiumPI:飞腾派引出多个引脚可供PWM使用 - -![phytiumpi_pwm](./figs/phytiumpi_pwm.png) - PhytiumPI:飞腾派引出多个引脚可供PWM使用 | **引脚** | **控制器与通道** | @@ -107,23 +116,51 @@ bootelf -p 0x90100000 ### 2.4 输出与实验现象 -- 系统进入后,创建pwm初始化任务,创建占空比变化任务,并创建单次模式软件定时器 +>描述输入输出情况,列出存在哪些输出,对应的输出是什么(建议附录相关现象图片)`
` -![create](./figs/create.png) +#### 2.4.1 PWM单通道测试例程 -- 定时器时间到,触发单次模式软件定时器的回调函数,去初始化pwm,删除占空比变化任务,删除软件定时器 +``` +$ pwm single_channel +``` -![delete](./figs/delete.png) +![single_channel](./figs/single_channel.png) -- 输出波形如下所示 +pwm单通道测试对应波形 -![pwm_out](./figs/pwm_out.png) -## 3. 如何解决问题 +![pwm_single_channel_waveform](./figs/pwm_single_channel_waveform.png) + +#### 2.4.2 PWM死区测试例程 -- 如默认用例无法使用或无波形输出,请根据不同的开发板,修改`pwm_example.h`文件中`PWM_TEST_ID`和`PWM_TEST_CHANNEL`两个宏定义,确保`FIOPadSetPwmMux`引脚复用设置正确 +``` +$ pwm dead_band +``` + +![pwm_dead_band](./figs/pwm_dead_band.png) + +pwm死区测试对应波形,参考时钟 FPWM_CLK_FREQ_HZ = 50MHz,上升沿延迟寄存器配置为800,延迟时间为 (1/50MHz)*800 = 16μs + +![pwm_dead_band_waveform](./figs/pwm_dead_band_waveform.png) + +#### 2.4.3 PWM双通道测试例程 + +``` +$ pwm dual_channel +``` + +![pwm_dual_channel](./figs/pwm_dual_channel.png) + +pwm双通道测试对应波形 + +![pwm_dual_channel_waveform](./figs/pwm_dual_channel_waveform.png) + +## 3. 如何解决问题 -- `PWM_TEST_CHANNEL`决定死区输入源,另一个CHANNEL作为输出源。若不想使能死区输出,可将FFreeRTOSPwmDbSet的部分去除,只需调用FFreeRTOSPwmSet即 可。 +- 如默认用例无法使用或无波形输出,请根据不同的开发板,修改`pwm_common.h`文件中`PWM_TEST_ID`和`PWM_TEST_CHANNEL`两个宏定义,确保`FIOPadSetPwmMux`引脚复用设置正确 +- PWM双通道测试例程,默认使用两个通道观测。 +- PWM死区测试例程中,`PWM_TEST_CHANNEL`决定死区输入源,另一个CHANNEL作为输出源。 +- E2000 DEMO V0.8板无法使用PWM4至PWM7,故无法进行本用例 ## 4. 修改历史记录 diff --git a/example/peripheral/pwm/figs/create.png b/example/peripheral/pwm/figs/create.png deleted file mode 100644 index 1ae309e04858bb6e76aa77c1856cad7e8ed2c7c8..0000000000000000000000000000000000000000 Binary files a/example/peripheral/pwm/figs/create.png and /dev/null differ diff --git a/example/peripheral/pwm/figs/delete.png b/example/peripheral/pwm/figs/delete.png deleted file mode 100644 index 98aa8e9d2c5265621755adcb8ba7027c6ca6b4de..0000000000000000000000000000000000000000 Binary files a/example/peripheral/pwm/figs/delete.png and /dev/null differ diff --git a/example/peripheral/pwm/figs/phytiumpi_pwm.png b/example/peripheral/pwm/figs/phytiumpi_pwm.png deleted file mode 100644 index c31475e90c23c77707c53f4c6c3875b433a61a57..0000000000000000000000000000000000000000 Binary files a/example/peripheral/pwm/figs/phytiumpi_pwm.png and /dev/null differ diff --git a/example/peripheral/pwm/figs/pwm_dead_band.png b/example/peripheral/pwm/figs/pwm_dead_band.png new file mode 100644 index 0000000000000000000000000000000000000000..7ed87425f5d264d0def9c30955b83a7488d26d9c Binary files /dev/null and b/example/peripheral/pwm/figs/pwm_dead_band.png differ diff --git a/example/peripheral/pwm/figs/pwm_dead_band_waveform.png b/example/peripheral/pwm/figs/pwm_dead_band_waveform.png new file mode 100644 index 0000000000000000000000000000000000000000..8fba9f85ffb5251093277013c4cc58fc26c607d1 Binary files /dev/null and b/example/peripheral/pwm/figs/pwm_dead_band_waveform.png differ diff --git a/example/peripheral/pwm/figs/pwm_dual_channel.png b/example/peripheral/pwm/figs/pwm_dual_channel.png new file mode 100644 index 0000000000000000000000000000000000000000..594f931d8eb262c2e696b42660927a98a16360e9 Binary files /dev/null and b/example/peripheral/pwm/figs/pwm_dual_channel.png differ diff --git a/example/peripheral/pwm/figs/pwm_dual_channel_waveform.png b/example/peripheral/pwm/figs/pwm_dual_channel_waveform.png new file mode 100644 index 0000000000000000000000000000000000000000..7e2fb7c3d7a47c4e6f47ed7da85d0548a90fc728 Binary files /dev/null and b/example/peripheral/pwm/figs/pwm_dual_channel_waveform.png differ diff --git a/example/peripheral/pwm/figs/pwm_out.png b/example/peripheral/pwm/figs/pwm_out.png deleted file mode 100644 index 6e95e85170a03ca8c0c2798e1d46329925ea9a01..0000000000000000000000000000000000000000 Binary files a/example/peripheral/pwm/figs/pwm_out.png and /dev/null differ diff --git a/example/peripheral/pwm/figs/pwm_single_channel_waveform.png b/example/peripheral/pwm/figs/pwm_single_channel_waveform.png new file mode 100644 index 0000000000000000000000000000000000000000..9dd11999bffe156156d13693aeee1d5e2418e19a Binary files /dev/null and b/example/peripheral/pwm/figs/pwm_single_channel_waveform.png differ diff --git a/example/peripheral/pwm/figs/single_channel.png b/example/peripheral/pwm/figs/single_channel.png new file mode 100644 index 0000000000000000000000000000000000000000..5c15afbe57450d642d37b1632d2eb4ea3ecd3288 Binary files /dev/null and b/example/peripheral/pwm/figs/single_channel.png differ diff --git a/example/peripheral/pwm/inc/pwm_example.h b/example/peripheral/pwm/inc/pwm_example.h index fd7b5c49f6c49dcf720bf3f57ecd133d5f68b137..215320c8530f1087e93d736f699494e519e113f3 100644 --- a/example/peripheral/pwm/inc/pwm_example.h +++ b/example/peripheral/pwm/inc/pwm_example.h @@ -25,21 +25,25 @@ #ifndef PWM_EXAMPLE_H #define PWM_EXAMPLE_H +#include "FreeRTOS.h" #ifdef __cplusplus extern "C" { #endif -#if defined(CONFIG_TARGET_E2000D)||defined(CONFIG_TARGET_E2000Q) +/************************** Constant Definitions *****************************/ +#if defined(CONFIG_E2000Q_DEMO_BOARD)||defined(CONFIG_E2000D_DEMO_BOARD) #define PWM_TEST_ID FPWM6_ID #define PWM_TEST_CHANNEL FPWM_CHANNEL_0 -#elif defined(CONFIG_TARGET_PHYTIUMPI) -#define PWM_TEST_ID FPWM2_ID -#define PWM_TEST_CHANNEL FPWM_CHANNEL_1 +#elif defined(CONFIG_FIREFLY_DEMO_BOARD) +#define PWM_TEST_ID FPWM4_ID +#define PWM_TEST_CHANNEL FPWM_CHANNEL_0 #endif /* pwm test */ -BaseType_t FFreeRTOSPwmCreate(u32 id); +BaseType_t FFreeRTOSPwmDeadBandTaskCreate(); +BaseType_t FFreeRTOSPwmSingleChannelTaskCreate(); +BaseType_t FFreeRTOSPwmDualChannelTaskCreate(); #ifdef __cplusplus } diff --git a/example/peripheral/pwm/main.c b/example/peripheral/pwm/main.c index bfc5c512cef6271925aff9c65ccc1280cf13ba7a..6d288e41f102f8a4ed8351c19912ca83531e2256 100644 --- a/example/peripheral/pwm/main.c +++ b/example/peripheral/pwm/main.c @@ -22,22 +22,44 @@ * 1.0 wangxiaodong 2022/8/24 first release */ +#include +#include "FreeRTOS.h" +#ifdef CONFIG_USE_LETTER_SHELL #include "shell.h" #include "shell_port.h" -#include +#else +#include "task.h" #include "pwm_example.h" +void PwmExampleTaskEntry() +{ + /* example functions */ + FFreeRTOSPwmSingleChannelTaskCreate(); +#ifdef CONFIG_FIREFLY_DEMO_BOARD + FFreeRTOSPwmDeadBandTaskCreate(); + + FFreeRTOSPwmDualChannelTaskCreate(); +#endif + /* end flag */ + printf("[test_end]\r\n"); + vTaskDelete(NULL); +} +#endif + int main(void) { BaseType_t ret; - /* test pwm*/ - ret = FFreeRTOSPwmCreate(PWM_TEST_ID); - if (ret != pdPASS) - { - goto FAIL_EXIT; - } - - ret = LSUserShellTask() ; +#ifdef CONFIG_USE_LETTER_SHELL + ret = LSUserShellTask(); +#else + /* used in no-letter-shell mode */ + ret = xTaskCreate((TaskFunction_t)PwmExampleTaskEntry, /* 任务入口函数 */ + (const char *)"PwmExampleTaskEntry", /* 任务名字 */ + (uint16_t)4096, /* 任务栈大小 */ + NULL, /* 任务入口函数参数 */ + (UBaseType_t)5, /* 任务优先级 */ + NULL); /* 任务句柄 */ +#endif if (ret != pdPASS) { goto FAIL_EXIT; diff --git a/example/peripheral/pwm/makefile b/example/peripheral/pwm/makefile index 13c14898d0f8ad5159f3e5baa6067deda58349eb..dde32d4bb62c074bbbf559bff818f4a2a1826b43 100644 --- a/example/peripheral/pwm/makefile +++ b/example/peripheral/pwm/makefile @@ -2,13 +2,19 @@ PROJECT_DIR = $(CURDIR) FREERTOS_SDK_DIR = $(CURDIR)/../../.. - +include $(PROJECT_DIR)/sdkconfig # # 设置启动镜像名 BOOT_IMG_NAME ?= freertos USER_CSRC := main.c -USER_CSRC += $(wildcard src/*.c) -USER_CSRC += $(wildcard ../common/*.c) +USER_CSRC += src/cmd_pwm.c + +USER_CSRC += src/pwm_single_channel_example.c + +ifdef CONFIG_FIREFLY_DEMO_BOARD +USER_CSRC += src/pwm_dead_band_example.c +USER_CSRC += src/pwm_dual_channel_example.c +endif USER_ASRC := USER_CXXSRC := diff --git a/example/peripheral/pwm/src/cmd_pwm.c b/example/peripheral/pwm/src/cmd_pwm.c new file mode 100644 index 0000000000000000000000000000000000000000..e596a6c88c736895adf97d6d96425b2880337e25 --- /dev/null +++ b/example/peripheral/pwm/src/cmd_pwm.c @@ -0,0 +1,86 @@ +/* + * Copyright : (C) 2022 Phytium Information Technology, Inc. + * All Rights Reserved. + * + * This program is OPEN SOURCE software: you can redistribute it and/or modify it + * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd, + * either version 1.0 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Phytium Public License for more details. + * + * + * FilePath: cmd_pwm.c + * Date: 2022-07-14 14:06:43 + * LastEditTime: 2022-07-14 14:06:43 + * Description:  This files is for gdma command interface + * + * Modify History: + * Ver    Who         Date         Changes + * -----  ------      --------     -------------------------------------- + * 1.0 zhangyan 2024/4/23 init commit + */ + +/***************************** Include Files *********************************/ +#include +#include +#include "strto.h" + +#include "sdkconfig.h" +#include "pwm_example.h" +/************************** Constant Definitions *****************************/ + +/************************** Variable Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +#ifdef CONFIG_USE_LETTER_SHELL +#include "../src/shell.h" + +static void PwmCmdUsage(void) +{ + printf("Usage:\r\n"); + printf("pwm single_channel\r\n"); + printf("-- run pwm single channel at controller \r\n"); +#ifdef CONFIG_FIREFLY_DEMO_BOARD + printf("pwm dead_band\r\n"); + printf("-- run pwm dead band example at controller \r\n"); + printf("pwm dual_channel\r\n"); + printf("-- run pwm dual channel at controller \r\n"); +#endif +} + +static int PwmCmdEntry(int argc, char *argv[]) +{ + int ret = 0; + + if (argc < 2) + { + PwmCmdUsage(); + return -1; + } + /* parser example input args and run example */ + if (!strcmp(argv[1], "single_channel")) + { + ret = FFreeRTOSPwmSingleChannelTaskCreate(); + } +#ifdef CONFIG_FIREFLY_DEMO_BOARD + if (!strcmp(argv[1], "dead_band")) + { + ret = FFreeRTOSPwmDeadBandTaskCreate(); + } + + if (!strcmp(argv[1], "dual_channel")) + { + ret = FFreeRTOSPwmDualChannelTaskCreate(); + } +#endif + + return ret; +} +SHELL_EXPORT_CMD(SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), pwm, PwmCmdEntry, test freertos pwm driver); +#endif \ No newline at end of file diff --git a/example/peripheral/pwm/src/pwm_example.c b/example/peripheral/pwm/src/pwm_dead_band_example.c similarity index 43% rename from example/peripheral/pwm/src/pwm_example.c rename to example/peripheral/pwm/src/pwm_dead_band_example.c index 17f264fd74359b4fe0d82b19efa24332422d93f3..59c2d72e3498e98f522e53c1906d4a24ed61c690 100644 --- a/example/peripheral/pwm/src/pwm_example.c +++ b/example/peripheral/pwm/src/pwm_dead_band_example.c @@ -11,7 +11,7 @@ * See the Phytium Public License for more details. * * - * FilePath: pwm_example.c + * FilePath: pwm_dead_band_example.c * Date: 2022-07-11 11:32:48 * LastEditTime: 2022-07-11 11:32:48 * Description: This file is for pwm test example functions. @@ -20,23 +20,26 @@ * Ver   Who         Date          Changes * ----- ------      --------     -------------------------------------- * 1.0 wangxiaodong 2022/8/24 first release + * 1.1 zhangyan 2024/4/23 refactoring */ #include #include "FreeRTOSConfig.h" #include "FreeRTOS.h" #include "task.h" -#include "timers.h" -#include "fpwm.h" #include "fpwm_os.h" -#include "fcpu_info.h" #include "fio_mux.h" #include "pwm_example.h" +#include "fparameters.h" -/* The periods assigned to the one-shot timers. */ -#define ONE_SHOT_TIMER_PERIOD ( pdMS_TO_TICKS( 300000UL ) ) +#define FPWM_DEBUG_TAG "PWM_DEAD_BAND_TEST" +#define FPWM_ERROR(format, ...) FT_DEBUG_PRINT_E(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) +#define FPWM_WARN(format, ...) FT_DEBUG_PRINT_W(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) +#define FPWM_INFO(format, ...) FT_DEBUG_PRINT_I(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) +#define FPWM_DEBUG(format, ...) FT_DEBUG_PRINT_D(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) /* pwm pulse change period */ -#define PWM_CHANGE_PERIOD ( pdMS_TO_TICKS( 2000UL )) +#define PWM_CHANGE_PERIOD (pdMS_TO_TICKS(500UL)) +#define TIMER_OUT (pdMS_TO_TICKS(4000UL)) /* pwm pulse amplitude of periodic variation */ #define PWM_PULSE_CHANGE 1000 @@ -45,54 +48,56 @@ #define PWM_PERIOD 10000 #define PWM_PULSE 2000 -/* test task number */ -#define TEST_TASK_NUM 1 -static xSemaphoreHandle xCountingSemaphore; - -static xTaskHandle change_handle; -static TimerHandle_t xOneShotTimer; +enum +{ + PWM_TEST_SUCCESS = 0, + PWM_TEST_UNKNOWN = 1, + PWM_INIT_FAILED = 2, + PWM_CHANGE_FAILED = 3, +}; +static QueueHandle_t xQueue = NULL; static FFreeRTOSPwm *os_pwm_ctrl_p; -static void FFreeRTOSPwmDelete(FFreeRTOSPwm *os_pwm_p); - -static void FFreeRTOSPwmInitTask(void *pvParameters) +static void PwmDelete(FFreeRTOSPwm *os_pwm_p) { - /* The pwm_id to use is passed in via the parameter. - Cast this to a pwm_id pointer. */ - u32 pwm_id = (u32)(uintptr)pvParameters; + FFreeRTOSPwmEnable(os_pwm_p, PWM_TEST_CHANNEL, FALSE); + FFreeRTOSPwmDeinit(os_pwm_p); + FIOMuxDeInit(); +} +static FError PwmInit(u32 pwm_id) +{ FError ret = FPWM_SUCCESS; + /* init iomux */ FIOMuxInit(); - /* set channel 0 and 1 iopad*/ -#if defined(CONFIG_TARGET_E2000) || defined(CONFIG_TARGET_PHYTIUMPI) - FIOPadSetPwmMux(pwm_id, 0); - FIOPadSetPwmMux(pwm_id, 1); -#endif + FIOPadSetPwmMux(pwm_id, FPWM_CHANNEL_0); + FIOPadSetPwmMux(pwm_id, FPWM_CHANNEL_1); /* init pwm controller */ os_pwm_ctrl_p = FFreeRTOSPwmInit(pwm_id); if (os_pwm_ctrl_p == NULL) { - printf("FFreeRTOSPwmInit failed.\n"); - goto pwm_init_exit; + FPWM_ERROR("FFreeRTOSPwmInit failed.\n"); + ret = FPWM_ERR_INVAL_PARM; + return ret; } /* set pwm db config */ FPwmDbVariableConfig db_cfg; memset(&db_cfg, 0, sizeof(db_cfg)); - db_cfg.db_rise_cycle = 500; - db_cfg.db_fall_cycle = 500; - db_cfg.db_polarity_sel = FPWM_DB_AHC; + db_cfg.db_rise_cycle = 800; + db_cfg.db_fall_cycle = 800; + db_cfg.db_polarity_sel = FPWM_DB_AH; /*将死区输入源设置为当前测试使用的CHANNEL*/ db_cfg.db_in_mode = PWM_TEST_CHANNEL == FPWM_CHANNEL_0 ? FPWM_DB_IN_MODE_PWM0 : FPWM_DB_IN_MODE_PWM1; db_cfg.db_out_mode = FPWM_DB_OUT_MODE_ENABLE_RISE_FALL; ret = FFreeRTOSPwmDbSet(os_pwm_ctrl_p, &db_cfg); if (FPWM_SUCCESS != ret) { - printf("FFreeRTOSPwmDbSet failed.\n"); - goto pwm_init_exit; + FPWM_ERROR("FFreeRTOSPwmDbSet failed.\n"); + return ret; } /* start pwm config */ FPwmVariableConfig pwm_cfg; @@ -107,8 +112,8 @@ static void FFreeRTOSPwmInitTask(void *pvParameters) ret = FFreeRTOSPwmSet(os_pwm_ctrl_p, PWM_TEST_CHANNEL, &pwm_cfg); if (FPWM_SUCCESS != ret) { - printf("FFreeRTOSPwmSet failed.\n"); - goto pwm_init_exit; + FPWM_ERROR("FFreeRTOSPwmSet failed.\n"); + return ret; } memset(&db_cfg, 0, sizeof(db_cfg)); @@ -132,137 +137,107 @@ static void FFreeRTOSPwmInitTask(void *pvParameters) printf("pwm_cfg.pwm_polarity = %d\n", pwm_cfg.pwm_polarity); printf("pwm_cfg.pwm_duty_source_mode = %d\n", pwm_cfg.pwm_duty_source_mode); - FFreeRTOSPwmEnable(os_pwm_ctrl_p, PWM_TEST_CHANNEL, TRUE); - - printf("FFreeRTOSPwmInitTask execute successfully.\r\n"); - - for (int i = 0; i < TEST_TASK_NUM; i++) + ret = FFreeRTOSPwmEnable(os_pwm_ctrl_p, PWM_TEST_CHANNEL, TRUE); + if (FPWM_SUCCESS != ret) { - xSemaphoreGive(xCountingSemaphore); + FPWM_ERROR("FFreeRTOSPwmEnable failed.\n"); + return ret; } -pwm_init_exit: - vTaskDelete(NULL); - + return ret; } -static void FFreeRTOSPwmChangeTask(void *pvParameters) +static FError PwmChange() { - xSemaphoreTake(xCountingSemaphore, portMAX_DELAY); + FError ret = FPWM_SUCCESS; u32 pwm_pulse = PWM_PULSE; /* As per most tasks, this task is implemented in an infinite loop. */ - for (;;) + for (int i = 0; i < 2; i++) { - FFreeRTOSPwmPulseSet(os_pwm_ctrl_p, PWM_TEST_CHANNEL, pwm_pulse); - - printf("FFreeRTOSPwmChangeTask run, pwm_pulse: %d\r\n", pwm_pulse); + ret = FFreeRTOSPwmPulseSet(os_pwm_ctrl_p, PWM_TEST_CHANNEL, pwm_pulse); + if (FPWM_SUCCESS != ret) + { + FPWM_ERROR("FFreeRTOSPwmPulseSet failed."); + return ret; + } + printf("pwm_pulse: %d\r\n", pwm_pulse); pwm_pulse = (pwm_pulse + PWM_PULSE_CHANGE) % PWM_PERIOD; vTaskDelay(PWM_CHANGE_PERIOD); } -} -static void prvOneShotTimerCallback(TimerHandle_t xTimer) -{ - /* Output a string to show the time at which the callback was executed. */ - printf("One-shot timer callback executing, which will delete FFreeRTOSPwmChangeTask.\r\n"); - /* deinit iomux */ - FIOMuxDeInit(); - - FFreeRTOSPwmDelete(os_pwm_ctrl_p); + return ret; } -/* create pwm test, id is pwm module number */ -BaseType_t FFreeRTOSPwmCreate(u32 id) +static void FFreeRTOSPwmDeadBandTask() { - FASSERT(id < FPWM_NUM); - BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */ - BaseType_t xTimerStarted = pdPASS; + FError ret = FPWM_SUCCESS; + int task_res = PWM_TEST_SUCCESS; - xCountingSemaphore = xSemaphoreCreateCounting(TEST_TASK_NUM, 0); - if (xCountingSemaphore == NULL) + ret = PwmInit(PWM_TEST_ID); + if (ret != FPWM_SUCCESS) { - printf("FFreeRTOSPwmCreate xCountingSemaphore create failed.\r\n"); - return pdFAIL; + FPWM_ERROR("PwmInit failed."); + task_res = PWM_INIT_FAILED; + goto task_exit; } - taskENTER_CRITICAL(); //进入临界区 - /* pwm init task */ - xReturn = xTaskCreate((TaskFunction_t)FFreeRTOSPwmInitTask, /* 任务入口函数 */ - (const char *)"FFreeRTOSPwmInitTask",/* 任务名字 */ - (uint16_t)1024, /* 任务栈大小 */ - (void *)(uintptr)id,/* 任务入口函数参数 */ - (UBaseType_t)configMAX_PRIORITIES - 1, /* 任务的优先级 */ - NULL); /* 任务控制 */ - - /* pwm占空比变化任务 */ - xReturn = xTaskCreate((TaskFunction_t)FFreeRTOSPwmChangeTask, /* 任务入口函数 */ - (const char *)"FFreeRTOSPwmChangeTask",/* 任务名字 */ - (uint16_t)1024, /* 任务栈大小 */ - NULL,/* 任务入口函数参数 */ - (UBaseType_t)configMAX_PRIORITIES - 1, /* 任务的优先级 */ - (TaskHandle_t *)&change_handle); /* 任务控制 */ - - /* Create the one shot software timer, storing the handle to the created - software timer in xOneShotTimer. */ - xOneShotTimer = xTimerCreate("OneShot Software Timer", /* Text name for the software timer - not used by FreeRTOS. */ - ONE_SHOT_TIMER_PERIOD, /* The software timer's period in ticks. */ - pdFALSE, /* Setting uxAutoRealod to pdFALSE creates a one-shot software timer. */ - 0, /* This example use the timer id. */ - prvOneShotTimerCallback); /* The callback function to be used by the software timer being created. */ - - /* Check the timers were created. */ - if (xOneShotTimer != NULL) - { - /* Start the software timers, using a block time of 0 (no block time). - The scheduler has not been started yet so any block time specified here - would be ignored anyway. */ - xTimerStarted = xTimerStart(xOneShotTimer, 0); - - /* The implementation of xTimerStart() uses the timer command queue, and - xTimerStart() will fail if the timer command queue gets full. The timer - service task does not get created until the scheduler is started, so all - commands sent to the command queue will stay in the queue until after - the scheduler has been started. Check both calls to xTimerStart() - passed. */ - if (xTimerStarted != pdPASS) - { - vPrintf("CreateSoftwareTimerTasks xTimerStart failed.\r\n"); - } - } - else + ret = PwmChange(); + if (ret != FPWM_SUCCESS) { - vPrintf("CreateSoftwareTimerTasks xTimerCreate failed.\r\n"); + FPWM_ERROR("PwmChange failed."); + task_res = PWM_CHANGE_FAILED; + goto task_exit; } - taskEXIT_CRITICAL(); //退出临界区 +task_exit: + xQueueSend(xQueue, &task_res, 0); - return xReturn; + vTaskDelete(NULL); } -static void FFreeRTOSPwmDelete(FFreeRTOSPwm *os_pwm_p) +/* create pwm test, id is pwm module number */ +BaseType_t FFreeRTOSPwmDeadBandTaskCreate() { - BaseType_t xReturn = pdPASS; - FFreeRTOSPwmEnable(os_pwm_p, PWM_TEST_CHANNEL, FALSE); - FFreeRTOSPwmDeinit(os_pwm_p); + BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */ + int task_res = PWM_TEST_UNKNOWN; - if (change_handle) + xQueue = xQueueCreate(1, sizeof(int)); /* 创建消息队列 */ + if (xQueue == NULL) { - vTaskDelete(change_handle); - vPrintf("Delete FFreeRTOSPwmChangeTask successfully.\r\n"); + FPWM_ERROR("xQueue create failed."); + goto exit; } - /* delete count sem */ - vSemaphoreDelete(xCountingSemaphore); + xReturn = xTaskCreate((TaskFunction_t)FFreeRTOSPwmDeadBandTask, /* 任务入口函数 */ + (const char *)"FFreeRTOSPwmDeadBandTask", /* 任务名字 */ + (uint16_t)4096, /* 任务栈大小 */ + NULL, /* 任务入口函数参数 */ + (UBaseType_t)2, /* 任务优先级 */ + NULL); /* 任务句柄 */ + if (xReturn == pdFAIL) + { + FPWM_ERROR("xTaskCreate GdmaMemcpyTask failed."); + goto exit; + } - /* delete timer */ - xReturn = xTimerDelete(xOneShotTimer, 0); - if (xReturn != pdPASS) + xReturn = xQueueReceive(xQueue, &task_res, TIMER_OUT); + if (xReturn == pdFAIL) { - vPrintf("Delete OneShot Software Timer failed.\r\n"); + FPWM_ERROR("xQueue receive timeout."); + goto exit; + } + +exit: + PwmDelete(os_pwm_ctrl_p); + vQueueDelete(xQueue); + if (task_res != PWM_TEST_SUCCESS) + { + printf("%s@%d: pwm dead band example [failure], task_res = %d\r\n", __func__, __LINE__, task_res); + return pdFAIL; } else { - vPrintf("Delete OneShot Software Timer successfully.\r\n"); + printf("%s@%d: pwm dead band example [success].\r\n", __func__, __LINE__); + return pdTRUE; } - -} \ No newline at end of file +} diff --git a/example/peripheral/pwm/src/pwm_dual_channel_example.c b/example/peripheral/pwm/src/pwm_dual_channel_example.c new file mode 100644 index 0000000000000000000000000000000000000000..c0c41c1c659fab492bdd2c8be44ac21ed57ffac7 --- /dev/null +++ b/example/peripheral/pwm/src/pwm_dual_channel_example.c @@ -0,0 +1,237 @@ +/* + * Copyright : (C) 2022 Phytium Information Technology, Inc. + * All Rights Reserved. + * + * This program is OPEN SOURCE software: you can redistribute it and/or modify it + * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd, + * either version 1.0 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Phytium Public License for more details. + * + * + * FilePath: pwm_dual_channel_example.c + * Date: 2022-07-11 11:32:48 + * LastEditTime: 2022-07-11 11:32:48 + * Description: This file is for pwm test example functions. + * + * Modify History: + * Ver   Who         Date          Changes + * ----- ------      --------     -------------------------------------- + * 1.0 wangxiaodong 2022/8/24 first release + * 1.1 zhangyan 2024/4/23 refactoring + */ +#include +#include "FreeRTOSConfig.h" +#include "FreeRTOS.h" +#include "task.h" +#include "fpwm_os.h" +#include "fio_mux.h" +#include "pwm_example.h" +#include "fparameters.h" + +#define FPWM_DEBUG_TAG "PWM_DUAL_CHANNEL_TEST" +#define FPWM_ERROR(format, ...) FT_DEBUG_PRINT_E(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) +#define FPWM_WARN(format, ...) FT_DEBUG_PRINT_W(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) +#define FPWM_INFO(format, ...) FT_DEBUG_PRINT_I(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) +#define FPWM_DEBUG(format, ...) FT_DEBUG_PRINT_D(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) + +/* pwm pulse change period */ +#define PWM_CHANGE_PERIOD (pdMS_TO_TICKS(500UL)) +#define TIMER_OUT (pdMS_TO_TICKS(10000UL)) +/* pwm pulse amplitude of periodic variation */ +#define PWM_PULSE_CHANGE 1000 + +/* pwm primary config */ +#define PWM_PERIOD 10000 +#define PWM_PULSE 2000 + +enum +{ + PWM_TEST_SUCCESS = 0, + PWM_TEST_UNKNOWN = 1, + PWM_INIT_FAILED = 2, + PWM_CHANGE_FAILED = 3, +}; + +static QueueHandle_t xQueue = NULL; +static FFreeRTOSPwm *os_pwm_ctrl_p; + +static void PwmDelete(FFreeRTOSPwm *os_pwm_p) +{ + FFreeRTOSPwmEnable(os_pwm_p, FPWM_CHANNEL_0, FALSE); + FFreeRTOSPwmEnable(os_pwm_p, FPWM_CHANNEL_1, FALSE); + FFreeRTOSPwmDeinit(os_pwm_p); + FIOMuxDeInit(); +} + +static FError PwmInit(u32 pwm_id) +{ + FError ret = FPWM_SUCCESS; + + /* init iomux */ + FIOMuxInit(); + FIOPadSetPwmMux(pwm_id, FPWM_CHANNEL_0); + FIOPadSetPwmMux(pwm_id, FPWM_CHANNEL_1); + + /* init pwm controller */ + os_pwm_ctrl_p = FFreeRTOSPwmInit(pwm_id); + if (os_pwm_ctrl_p == NULL) + { + FPWM_ERROR("FFreeRTOSPwmInit failed.\n"); + ret = FPWM_ERR_INVAL_PARM; + return ret; + } + + /* start pwm config */ + FPwmVariableConfig pwm_cfg; + memset(&pwm_cfg, 0, sizeof(pwm_cfg)); + pwm_cfg.tim_ctrl_mode = FPWM_MODULO; + pwm_cfg.tim_ctrl_div = 500 - 1; + pwm_cfg.pwm_period = 10000; + pwm_cfg.pwm_pulse = PWM_PULSE; + pwm_cfg.pwm_mode = FPWM_OUTPUT_COMPARE; + pwm_cfg.pwm_polarity = FPWM_POLARITY_NORMAL; + pwm_cfg.pwm_duty_source_mode = FPWM_DUTY_CCR; + ret = FFreeRTOSPwmSet(os_pwm_ctrl_p, FPWM_CHANNEL_0, &pwm_cfg); + if (FPWM_SUCCESS != ret) + { + FPWM_ERROR("FFreeRTOSPwmSet failed.\n"); + return ret; + } + + memset(&pwm_cfg, 0, sizeof(pwm_cfg)); + pwm_cfg.tim_ctrl_mode = FPWM_MODULO; + pwm_cfg.tim_ctrl_div = 1000 - 1; + pwm_cfg.pwm_period = 20000; + pwm_cfg.pwm_pulse = PWM_PULSE; + pwm_cfg.pwm_mode = FPWM_OUTPUT_COMPARE; + pwm_cfg.pwm_polarity = FPWM_POLARITY_NORMAL; + pwm_cfg.pwm_duty_source_mode = FPWM_DUTY_CCR; + ret = FFreeRTOSPwmSet(os_pwm_ctrl_p, FPWM_CHANNEL_1, &pwm_cfg); + if (FPWM_SUCCESS != ret) + { + FPWM_ERROR("FFreeRTOSPwmSet failed.\n"); + return ret; + } + + ret = FFreeRTOSPwmEnable(os_pwm_ctrl_p, FPWM_CHANNEL_0, TRUE); + if (FPWM_SUCCESS != ret) + { + FPWM_ERROR("FFreeRTOSPwmEnable failed.\n"); + return ret; + } + + ret = FFreeRTOSPwmEnable(os_pwm_ctrl_p, FPWM_CHANNEL_1, TRUE); + if (FPWM_SUCCESS != ret) + { + FPWM_ERROR("FFreeRTOSPwmEnable failed.\n"); + return ret; + } + + return ret; +} + +static FError PwmChange() +{ + FError ret = FPWM_SUCCESS; + u32 pwm_pulse = PWM_PULSE; + /* As per most tasks, this task is implemented in an infinite loop. */ + for (int i = 0; i < 5; i++) + { + ret = FFreeRTOSPwmPulseSet(os_pwm_ctrl_p, FPWM_CHANNEL_0, pwm_pulse); + if (FPWM_SUCCESS != ret) + { + FPWM_ERROR("FFreeRTOSPwmPulseSet failed."); + return ret; + } + + ret = FFreeRTOSPwmPulseSet(os_pwm_ctrl_p, FPWM_CHANNEL_1, pwm_pulse); + if (FPWM_SUCCESS != ret) + { + FPWM_ERROR("FFreeRTOSPwmPulseSet failed."); + return ret; + } + + printf("pwm_pulse: %d\r\n", pwm_pulse); + pwm_pulse = (pwm_pulse + PWM_PULSE_CHANGE) % PWM_PERIOD; + vTaskDelay(PWM_CHANGE_PERIOD); + } + + return ret; +} + +static void FFreeRTOSPwmDualChannelTask() +{ + FError ret = FPWM_SUCCESS; + int task_res = PWM_TEST_SUCCESS; + + ret = PwmInit(PWM_TEST_ID); + if (ret != FPWM_SUCCESS) + { + FPWM_ERROR("PwmInit failed."); + task_res = PWM_INIT_FAILED; + goto task_exit; + } + + ret = PwmChange(); + if (ret != FPWM_SUCCESS) + { + FPWM_ERROR("PwmChange failed."); + task_res = PWM_CHANGE_FAILED; + goto task_exit; + } + +task_exit: + xQueueSend(xQueue, &task_res, 0); + + vTaskDelete(NULL); +} + +/* create pwm test, id is pwm module number */ +BaseType_t FFreeRTOSPwmDualChannelTaskCreate() +{ + BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */ + int task_res = PWM_TEST_UNKNOWN; + + xQueue = xQueueCreate(1, sizeof(int)); /* 创建消息队列 */ + if (xQueue == NULL) + { + FPWM_ERROR("xQueue create failed."); + goto exit; + } + + xReturn = xTaskCreate((TaskFunction_t)FFreeRTOSPwmDualChannelTask, /* 任务入口函数 */ + (const char *)"FFreeRTOSPwmDualChannelTask", /* 任务名字 */ + (uint16_t)4096, /* 任务栈大小 */ + NULL, /* 任务入口函数参数 */ + (UBaseType_t)2, /* 任务优先级 */ + NULL); /* 任务句柄 */ + if (xReturn == pdFAIL) + { + FPWM_ERROR("xTaskCreate GdmaMemcpyTask failed."); + goto exit; + } + + xReturn = xQueueReceive(xQueue, &task_res, TIMER_OUT); + if (xReturn == pdFAIL) + { + FPWM_ERROR("xQueue receive timeout."); + goto exit; + } + +exit: + PwmDelete(os_pwm_ctrl_p); + vQueueDelete(xQueue); + if (task_res != PWM_TEST_SUCCESS) + { + printf("%s@%d: pwm dual channel example [failure], task_res = %d\r\n", __func__, __LINE__, task_res); + return pdFAIL; + } + else + { + printf("%s@%d: pwm dual channel example [success].\r\n", __func__, __LINE__); + return pdTRUE; + } +} diff --git a/example/peripheral/pwm/src/pwm_single_channel_example.c b/example/peripheral/pwm/src/pwm_single_channel_example.c new file mode 100644 index 0000000000000000000000000000000000000000..104d65266ad474d6b68d49ea446ddd53cdd1e176 --- /dev/null +++ b/example/peripheral/pwm/src/pwm_single_channel_example.c @@ -0,0 +1,207 @@ +/* + * Copyright : (C) 2022 Phytium Information Technology, Inc. + * All Rights Reserved. + * + * This program is OPEN SOURCE software: you can redistribute it and/or modify it + * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd, + * either version 1.0 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Phytium Public License for more details. + * + * + * FilePath: pwm_single_channel_example.c + * Date: 2022-07-11 11:32:48 + * LastEditTime: 2022-07-11 11:32:48 + * Description: This file is for pwm test example functions. + * + * Modify History: + * Ver   Who         Date          Changes + * ----- ------      --------     -------------------------------------- + * 1.0 wangxiaodong 2022/8/24 first release + * 1.1 zhangyan 2024/4/23 refactoring + */ +#include +#include "FreeRTOSConfig.h" +#include "FreeRTOS.h" +#include "task.h" +#include "fpwm_os.h" +#include "fio_mux.h" +#include "pwm_example.h" +#include "fparameters.h" + +#define FPWM_DEBUG_TAG "PWM_SINGLE_CHANNEL_TEST" +#define FPWM_ERROR(format, ...) FT_DEBUG_PRINT_E(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) +#define FPWM_WARN(format, ...) FT_DEBUG_PRINT_W(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) +#define FPWM_INFO(format, ...) FT_DEBUG_PRINT_I(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) +#define FPWM_DEBUG(format, ...) FT_DEBUG_PRINT_D(FPWM_DEBUG_TAG, format, ##__VA_ARGS__) + +/* pwm pulse change period */ +#define PWM_CHANGE_PERIOD (pdMS_TO_TICKS(500UL)) +#define TIMER_OUT (pdMS_TO_TICKS(10000UL)) +/* pwm pulse amplitude of periodic variation */ +#define PWM_PULSE_CHANGE 1000 + +/* pwm primary config */ +#define PWM_DIV 500 +#define PWM_PERIOD 10000 +#define PWM_PULSE 2000 + +enum +{ + PWM_TEST_SUCCESS = 0, + PWM_TEST_UNKNOWN = 1, + PWM_INIT_FAILED = 2, + PWM_CHANGE_FAILED = 3, +}; + +static QueueHandle_t xQueue = NULL; +static FFreeRTOSPwm *os_pwm_ctrl_p; + +static void PwmDelete(FFreeRTOSPwm *os_pwm_p) +{ + FFreeRTOSPwmEnable(os_pwm_p, PWM_TEST_CHANNEL, FALSE); + FFreeRTOSPwmDeinit(os_pwm_p); + FIOMuxDeInit(); +} + +static FError PwmInit(u32 pwm_id) +{ + FError ret = FPWM_SUCCESS; + + /* init iomux */ + FIOMuxInit(); + FIOPadSetPwmMux(pwm_id, PWM_TEST_CHANNEL); + + /* init pwm controller */ + os_pwm_ctrl_p = FFreeRTOSPwmInit(pwm_id); + if (os_pwm_ctrl_p == NULL) + { + FPWM_ERROR("FFreeRTOSPwmInit failed.\n"); + ret = FPWM_ERR_INVAL_PARM; + return ret; + } + + /* start pwm config */ + FPwmVariableConfig pwm_cfg; + memset(&pwm_cfg, 0, sizeof(pwm_cfg)); + pwm_cfg.tim_ctrl_mode = FPWM_MODULO; + pwm_cfg.tim_ctrl_div = PWM_DIV - 1; + pwm_cfg.pwm_period = PWM_PERIOD; + pwm_cfg.pwm_pulse = PWM_PULSE; + pwm_cfg.pwm_mode = FPWM_OUTPUT_COMPARE; + pwm_cfg.pwm_polarity = FPWM_POLARITY_NORMAL; + pwm_cfg.pwm_duty_source_mode = FPWM_DUTY_CCR; + ret = FFreeRTOSPwmSet(os_pwm_ctrl_p, PWM_TEST_CHANNEL, &pwm_cfg); + if (FPWM_SUCCESS != ret) + { + FPWM_ERROR("FFreeRTOSPwmSet failed.\n"); + return ret; + } + + ret = FFreeRTOSPwmEnable(os_pwm_ctrl_p, PWM_TEST_CHANNEL, TRUE); + if (FPWM_SUCCESS != ret) + { + FPWM_ERROR("FFreeRTOSPwmEnable failed.\n"); + return ret; + } + + return ret; +} + +static FError PwmChange() +{ + FError ret = FPWM_SUCCESS; + u32 pwm_pulse = PWM_PULSE; + /* As per most tasks, this task is implemented in an infinite loop. */ + for (int i = 0; i < 5; i++) + { + ret = FFreeRTOSPwmPulseSet(os_pwm_ctrl_p, PWM_TEST_CHANNEL, pwm_pulse); + if (FPWM_SUCCESS != ret) + { + FPWM_ERROR("FFreeRTOSPwmPulseSet failed."); + return ret; + } + + printf("pwm_pulse: %d\r\n", pwm_pulse); + pwm_pulse = (pwm_pulse + PWM_PULSE_CHANGE) % PWM_PERIOD; + vTaskDelay(PWM_CHANGE_PERIOD); + } + + return ret; +} + +static void FFreeRTOSSingleChannelTask() +{ + FError ret = FPWM_SUCCESS; + int task_res = PWM_TEST_SUCCESS; + + ret = PwmInit(PWM_TEST_ID); + if (ret != FPWM_SUCCESS) + { + FPWM_ERROR("PwmInit failed."); + task_res = PWM_INIT_FAILED; + goto task_exit; + } + + ret = PwmChange(); + if (ret != FPWM_SUCCESS) + { + FPWM_ERROR("PwmChange failed."); + task_res = PWM_CHANGE_FAILED; + goto task_exit; + } + +task_exit: + xQueueSend(xQueue, &task_res, 0); + + vTaskDelete(NULL); +} + +/* create pwm test, id is pwm module number */ +BaseType_t FFreeRTOSPwmSingleChannelTaskCreate() +{ + BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */ + int task_res = PWM_TEST_UNKNOWN; + + xQueue = xQueueCreate(1, sizeof(int)); /* 创建消息队列 */ + if (xQueue == NULL) + { + FPWM_ERROR("xQueue create failed."); + goto exit; + } + + xReturn = xTaskCreate((TaskFunction_t)FFreeRTOSSingleChannelTask, /* 任务入口函数 */ + (const char *)"FFreeRTOSSingleChannelTask", /* 任务名字 */ + (uint16_t)4096, /* 任务栈大小 */ + NULL, /* 任务入口函数参数 */ + (UBaseType_t)2, /* 任务优先级 */ + NULL); /* 任务句柄 */ + if (xReturn == pdFAIL) + { + FPWM_ERROR("xTaskCreate GdmaMemcpyTask failed."); + goto exit; + } + + xReturn = xQueueReceive(xQueue, &task_res, TIMER_OUT); + if (xReturn == pdFAIL) + { + FPWM_ERROR("xQueue receive timeout."); + goto exit; + } + +exit: + PwmDelete(os_pwm_ctrl_p); + vQueueDelete(xQueue); + if (task_res != PWM_TEST_SUCCESS) + { + printf("%s@%d: pwm single channel example [failure], task_res = %d\r\n", __func__, __LINE__, task_res); + return pdFAIL; + } + else + { + printf("%s@%d: pwm single channel example [success].\r\n", __func__, __LINE__); + return pdTRUE; + } +} diff --git a/example/peripheral/spi/src/sfud_read_write.c b/example/peripheral/spi/src/sfud_read_write.c index 0e6bf718b0cf6369b2a5a7445e56e0119b4308f6..26244e5701642c8a95218c81ce52b98daa14f353 100644 --- a/example/peripheral/spi/src/sfud_read_write.c +++ b/example/peripheral/spi/src/sfud_read_write.c @@ -175,7 +175,7 @@ write_exit: if (SFUD_SUCCESS != sfud_ret) { task_res = SPI_SFUD_WRITE_FAILURE; - xQueueSend(xQueue, &task_res, 0);; + xQueueSend(xQueue, &task_res, 0); } return sfud_ret; @@ -238,7 +238,7 @@ read_exit: if (SFUD_SUCCESS != sfud_ret) { task_res = SPI_SFUD_READ_FAILURE; - xQueueSend(xQueue, &task_res, 0);; + xQueueSend(xQueue, &task_res, 0); } return sfud_ret;