openCPU开发demo详解包括线程调度、队列等的使用

OpenCPU开发例程的详细解释,包括各种功能的测试,如线程、队列等 源代码为osi_demo.c
初步学习,可能有误,仅供参考

代码

/* Copyright (C) 2022 FIBOCOM Technologies Limited and/or its affiliates("FIBOCOM").
 * All rights reserved.
 *
 * This software is supplied "AS IS" without any warranties.
 * FIBOCOM assumes no responsibility or liability for the use of the software,
 * conveys no license or title under any patent, copyright, or mask work
 * right to the product. FIBOCOM reserves the right to make changes in the
 * software without notification.  FIBOCOM also make no representation or
 * warranty that such application will be suitable for the specified use
 * without further testing or modification.
 */


#define OSI_LOG_TAG OSI_MAKE_LOG_TAG('M', 'Y', 'A', 'P')

#include "fibo_opencpu.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef __uint32_t uint32_t ;



static void prvInvokeGlobalCtors(void)
{
    extern void (*__init_array_start[])();
    extern void (*__init_array_end[])();

    size_t count = __init_array_end - __init_array_start;
    for (size_t i = 0; i < count; ++i)
        __init_array_start[i]();
}

static void test_ticks()
{
    UINT32 ticks = 0;
    ticks = fibo_get_sys_tick();
    fibo_textTrace("before ticks = %u", ticks);
    fibo_taskSleep(1000);
    ticks = fibo_get_sys_tick();
    fibo_textTrace("after ticks = %u", ticks);
}

uint32_t g_size;
uint32_t g_avail_size;
uint32_t g_max_block_size;
static void test_mem()
{
    char *pt = (char *)fibo_malloc(51200);
    if (pt != NULL)
    {
        fibo_textTrace("malloc address %u", (unsigned int)pt);
        fibo_free(pt);
    }

    fibo_heapinfo_get(&g_size, &g_avail_size, &g_max_block_size);
    fibo_textTrace("g_size = %u, g_avail_size = %u, g_max_block_size = %u", g_size, g_avail_size, g_max_block_size);
}

static void test_reset(int mode)
{
    if (mode == 0)
        fibo_soft_reset();
    else
        fibo_soft_power_off();
}


/* sem test begin */
UINT32 g_test_sem;
static void testSemThread(void *param)
{
    fibo_taskSleep(2000);
    fibo_textTrace("execute sem_signal...");
    fibo_sem_signal(g_test_sem);
    fibo_taskSleep(1000);
    fibo_sem_signal(g_test_sem);
    fibo_thread_delete();
}
static void test_sem()
{
    g_test_sem = fibo_sem_new(0);

    fibo_thread_create(testSemThread, "test_sem", 1024, NULL, OSI_PRIORITY_NORMAL);

    fibo_sem_wait(g_test_sem);
    fibo_textTrace("after sem_wait...");

    fibo_sem_try_wait(g_test_sem, 5000);
    fibo_textTrace("after sem_try_wait...");

    fibo_sem_try_wait(g_test_sem, 5000);
    fibo_textTrace("after sem_try_wait...");
    fibo_sem_free(g_test_sem);
}
/* sem test end */

/* mutex test begin */
UINT32 g_test_mutex;
static void test_mutex()
{
    g_test_mutex = fibo_mutex_create();
    fibo_textTrace("after mutex create...");

    fibo_mutex_lock(g_test_mutex);
    fibo_textTrace("after mutex lock...");

    fibo_mutex_unlock(g_test_mutex);
    fibo_textTrace("after mutex unlock...");

    fibo_mutex_try_lock(g_test_mutex, 3000);
    fibo_textTrace("after mutex try lock...");

    fibo_mutex_delete(g_test_mutex);
    fibo_textTrace("after mutex delete...");
}
/* mytex test end */

/* test timer begin */
void *g_test_timer = NULL;
void *g_test_timer2 = NULL;
void *g_period_timer = NULL;
void *g_period_timer2 = NULL;

void timer_function(void *arg)
{
    fibo_textTrace("timer function execute ...");
    fibo_timer_delete(g_test_timer);
}

void test_timer()
{
    g_test_timer = fibo_timer_create(timer_function, NULL, false);
    fibo_textTrace("test_timer_creat 1...");
    fibo_timer_start(g_test_timer, 6000, false);
}

void timer_function2(void *arg)
{
    fibo_textTrace("timer function2 execute ...");
    fibo_timer_delete(g_test_timer2);
}

void test_timer2()
{
    g_test_timer2 = fibo_timer_create(timer_function2, NULL, false);
    fibo_textTrace("test_timer_creat 2");

    fibo_timer_start(g_test_timer2, 6000, false);
}

void timer_function_period(void *arg)
{
    static int nr = 5;
    fibo_textTrace("timer period function execute ...");
    nr--;
    if(nr == 0)
        fibo_timer_delete(g_period_timer);
}

void test_timer_period()
{
    g_period_timer = fibo_timer_create(timer_function_period, NULL, false);
    fibo_timer_start(g_period_timer, 3000, true);
}

void timer_function_period2(void *arg)
{
    static int nr = 5;
    fibo_textTrace("timer period function2 execute cnt: %d...", nr);
    nr--;
    if(nr == 0)
    {
        fibo_timer_delete(g_period_timer2);
    }
}

void test_timer_period2()
{
    g_period_timer2 = fibo_timer_create(timer_function_period2, NULL, false);
    fibo_textTrace("test_timer_period2 ...");
    fibo_timer_start(g_period_timer2, 3000, true);
}
/* test timer end */

void test_rand()
{
    srand(1000);
    for (int i = 0; i < 10; i++)
    {
        fibo_textTrace("rand %d : %d", i, rand());
    }
}

/* test queue */
UINT32 g_queue_id = 0;
static void testQueueThread(void *param)
{
    int value = 8888;
    fibo_taskSleep(2000);
    fibo_queue_put(g_queue_id, &value, 0);
    fibo_thread_delete();
}

void test_queue()
{
    int value = 0;
    g_queue_id = fibo_queue_create(5, sizeof(int));
    fibo_thread_create(testQueueThread, "test_queue", 4096, NULL, OSI_PRIORITY_NORMAL);
    fibo_queue_get(g_queue_id, (void *)&value, 0);
    fibo_textTrace("test queue value = %d", value);
}

UINT32 g_queue_id2 = 0;
static void testQueueThread2(void *param)
{
    int i = 0;
    int value = 1111;
    fibo_taskSleep(2000);

    for (i = 1; i < 10; i++)
    {
        value = 1111 *i;
        fibo_queue_put_to_front(g_queue_id2, &value, 0);
        fibo_textTrace("test queue2 value put to front(%d) = %d", i, value);
    }

    fibo_thread_delete();
}

void test_queue2()
{
    int value = 0;
    g_queue_id2 = fibo_queue_create(10, sizeof(int));
    fibo_thread_create(testQueueThread2, "test_queue2", 4096, NULL, OSI_PRIORITY_NORMAL);

    fibo_taskSleep(5000);

    for (int i = 1; i < 10; i++)
    {
        fibo_queue_get(g_queue_id2, (void *)&value, 0);
        fibo_textTrace("test queue2 value get(%d) = %d", i, value);
    }
}

/* test queue end */

static void nullThread(void *param)
{
    for (int n = 0; n < 5; n++)
    {
        fibo_textTrace("null Thread in %d", n);
        fibo_taskSleep(1000);
    }
    fibo_thread_delete();
}


static void oc_osi_demo(void *param)
{
    fibo_textTrace("application thread enter, param 0x%x", param);
    test_ticks(); //测试时钟函数
    test_mem(); //测试内存管理函数
    test_sem(); //测试信号量函数
    test_mutex(); //测试互斥锁函数
    test_timer();  //测试定时器函数
    test_timer2();
    test_rand(); //随机数
    test_queue(); //队列
    test_queue2();
    test_timer_period(); //周期性定时函数
    test_timer_period2();
    test_reset(0); //复位函数

    for (int n = 0; n < 10; n++)
    {
        fibo_textTrace("hello world %d", n);
        fibo_taskSleep(1000);
    }
    fibo_taskSleep(1000);
    //test_reset(0);

    UINT32 thread_id = 0;
    fibo_thread_create_ex(nullThread, "nullthread",
        1024, NULL, OSI_PRIORITY_NORMAL, &thread_id); //创建一个新线程并打印线程ID
    fibo_textTrace("nullThread id = 0x%x", thread_id);

    fibo_thread_delete(); //删除线程
}

void* appimg_enter(void *param) //入口函数
{
    fibo_textTrace("application image enter, param 0x%x", param);

    prvInvokeGlobalCtors();

    fibo_thread_create(oc_osi_demo, "oc_osi_demo", 1024, NULL, OSI_PRIORITY_NORMAL);
    return 0;
}

void appimg_exit(void) //退出函数
{
    fibo_textTrace("application image exit");
}



部分系统函数

fibo_textTrace(输出日志)

INT32 fibo_textTrace
(
char *fmt, …
)

TRACE 输出的接口。从抓 LOG 的工具 coolwatcher 输出,fmt 字符串长度最大 255。

fibo_thread_create(创建线程)

(
void* pvTaskCode,
INT8 * pcName,
UINT32 usStackDepth,
void *pvParameters,
UINT32 uxPriority
)

任务函数接口
任务名称
任务栈大小,接口 U32 类型数据,理论可申请0xFFFFFFFF 这么大的栈空间,实际单个最大可 250K 左右,内存一般剩余 2M 多空间

任务函数输入参数
任务优先级

fibo_heapinfo_get(获取内存堆信息)

  • 是一个函数,它用于获取当前系统内存堆的信息,返回值是一个指向结构体 fibo_heap_info_t 的指针,结构体 fibo_heap_info_t 包含以下字段:
  • total_size:表示当前系统内存堆的总大小(单位:字节)。
  • used_size:表示当前系统内存堆已被使用的大小(单位:字节)。
  • max_free_size:表示当前系统内存堆中最大可用内存块的大小(单位:字节)。
  • frag_size:表示当前系统内存堆中内存碎片的大小(单位:字节)。

调用 fibo_heapinfo_get() 函数可以获取当前系统内存堆的信息,方便开发者进行内存管理和优化。通常在调试和优化阶段使用该函数,可以帮助开发者发现内存泄漏、内存碎片等问题。

fibo_sem_signal(信号量操作)

信号量+1,信号量为一个 UINT8 的值,使用时需要保证其不会溢出

fibo_sem_wait

信号量-1,当信号量为0时产生进程调度操作

fibo_sem_try_wait

与上述一致,但是增加了超时机制

fibo_malloc(申请内存)

举例:char *pt = (char *)fibo_malloc(51200);

获取内存地址:fibo_textTrace(“malloc address %u”, (unsigned int)pt);

释放内存:fibo_free(pt);

函数

appimg_enter(入口函数)

void* appimg_enter(void *param)
{
    fibo_textTrace("application image enter, param 0x%x", param);

    prvInvokeGlobalCtors();//初始化全局静态构造函数

    fibo_thread_create(oc_osi_demo, "oc_osi_demo", 1024, NULL, OSI_PRIORITY_NORMAL);
    return 0;
}

所有代码都会从入口函数开始执行,先初始化,再创建主线程

prvInvokeGlobalCtors(初始化)

static void prvInvokeGlobalCtors(void)
{
    extern void (*__init_array_start[])();
    extern void (*__init_array_end[])();

    size_t count = __init_array_end - __init_array_start;
    for (size_t i = 0; i < count; ++i)
        __init_array_start[i]();
}

这段代码的作用是调用全局静态构造函数(Global Static Constructor),也被称为初始化函数。全局静态构造函数是在程序启动时自动调用的一些函数,它们用于初始化全局静态变量或执行一些其他的初始化工作。

这段代码中,首先声明了两个外部变量 __init_array_start[]__init_array_end[],它们是在链接器脚本(Linker Script)中定义的符号,用于指示存储在程序的 .init_array 段中的初始化函数的起始地址和结束地址。在 C++ 中,全局静态构造函数是按照它们在 .init_array 段中出现的顺序来调用的。

接下来,代码计算了存储在 .init_array 段中的初始化函数的数量(即 count = __init_array_end - __init_array_start)。然后,通过一个 for 循环依次调用这些初始化函数,从而完成全局静态构造函数的调用过程。

这段代码是用于调用全局静态构造函数的,一般来说在标准 C/C++ 环境下编写的程序中都会包含这段代码。但是在嵌入式开发中,是否必须依赖于具体的开发环境和目标平台。

test_sem_thread(测试线程)

static void testSemThread(void *param)
{
    fibo_taskSleep(2000);
    fibo_textTrace("execute sem_signal...");
    fibo_sem_signal(g_test_sem);
    fibo_taskSleep(1000);
    fibo_sem_signal(g_test_sem);
    fibo_thread_delete();
}

test_sem(测试信号量)

static void test_sem()
{
    g_test_sem = fibo_sem_new(0);

    fibo_thread_create(testSemThread, "test_sem", 1024, NULL, OSI_PRIORITY_NORMAL);

    fibo_sem_wait(g_test_sem);
    fibo_textTrace("after sem_wait...");

    fibo_sem_try_wait(g_test_sem, 5000);
    fibo_textTrace("after sem_try_wait...");

    fibo_sem_try_wait(g_test_sem, 5000);
    fibo_textTrace("after sem_try_wait...");
    fibo_sem_free(g_test_sem);
}
  1. 这段代码的执行顺序如下:
    1. 主线程中创建一个初始值为0的信号量g_test_sem。
    2. 主线程创建一个名为"test_sem"的新线程testSemThread,并将信号量g_test_sem作为参数传递给该线程。
    3. testSemThread线程等待2秒钟,然后执行第一次信号量信号操作:使用fibo_sem_signal函数释放g_test_sem信号量。
    4. 主线程中调用fibo_sem_wait函数等待信号量g_test_sem。
    5. 当testSemThread释放g_test_sem信号量时,主线程的fibo_sem_wait函数返回,主线程输出"after sem_wait…"。
    6. 主线程中使用fibo_sem_try_wait函数尝试等待g_test_sem信号量,等待时间为5秒。
    7. testSemThread线程执行第二次信号量信号操作:使用fibo_sem_signal函数再次释放g_test_sem信号量。
    8. 主线程的fibo_sem_try_wait函数尝试等待g_test_sem信号量时,因为信号量已经被释放,所以不会等待,fibo_sem_try_wait函数返回0,主线程输出"after sem_try_wait…"。
    9. 主线程中再次使用fibo_sem_try_wait函数尝试等待g_test_sem信号量,等待时间为5秒。
    10. 因为g_test_sem信号量已经被释放,主线程的fibo_sem_try_wait函数不会等待,直接返回0,主线程输出"after sem_try_wait…"。
    11. 主线程释放g_test_sem信号量,并使用fibo_sem_free函数释放信号量内存。
    12. testSemThread线程调用fibo_thread_delete函数结束线程的执行。

test_queue2 (测试队列)

UINT32 g_queue_id2 = 0;
static void testQueueThread2(void *param)
{
    int i = 0;
    int value = 1111;
    fibo_taskSleep(2000);

    for (i = 1; i < 10; i++)
    {
        value = 1111 *i;
        fibo_queue_put_to_front(g_queue_id2, &value, 0);
        fibo_textTrace("test queue2 value put to front(%d) = %d", i, value);
    }

    fibo_thread_delete();
}

void test_queue2()
{
    int value = 0;
    g_queue_id2 = fibo_queue_create(10, sizeof(int));
    fibo_thread_create(testQueueThread2, "test_queue2", 4096, NULL, OSI_PRIORITY_NORMAL);

    fibo_taskSleep(5000);

    for (int i = 1; i < 10; i++)
    {
        fibo_queue_get(g_queue_id2, (void *)&value, 0);
        fibo_textTrace("test queue2 value get(%d) = %d", i, value);
    }
}

程序实现了在主线程中创建一个线程,在该线程中创建队列后返回主线程打印的功能

执行顺序为

  1. 在主线程中创建一个队列 g_queue_id2,大小为 10,元素类型为 int;
  2. 在主线程中创建一个名为 testQueueThread2 的线程,优先级为正常优先级,栈大小为 4096;
  3. testQueueThread2 线程启动,等待 2s 后开始执行以下循环: a. 将 value 设为 1111*i; b. 将 value 放入队列 g_queue_id2 的队首; c. 打印输出 “test queue2 value put to front(%d) = %d”;
  4. 主线程等待 5s;
  5. 在主线程中进行以下循环,共执行 9 次: a. 从队列 g_queue_id2 的队首取出一个元素,存储到 value 中; b. 打印输出 “test queue2 value get(%d) = %d”;
  6. 程序执行结束。

猜你喜欢

转载自blog.csdn.net/weixin_44738872/article/details/129565115
今日推荐