Seperate Library

The following method is use the abstract interface to decouple the platform and algorithm.

Platform

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#define ADD_PARAM(params,type,value) \
do { \
params.paramType[i] = type; \
params.paramVal[i] = value; \
}while(0)
/*
* abstract interface for dsp modules
*/
typedef struct PublicApi{
void (* func0)(void * context);
void (* func1)(void *);
void (* func2)(void *);
void (* func3)(void *);
}PublicApi_t;

/**************************************************************************************************
@brief void Func0(void)
@param[in] none
@return none
**************************************************************************************************/
void Func0(Parameters_t * params)
{
struct testdata test;
for(int i = 0;i<param->paramNum;i++)
{
ADD_PARAM(test,params->paramType[i],params->paramVal[i]);
}
}

/**************************************************************************************************
@brief void Func1(void)
@param[in] none
@return none
**************************************************************************************************/
void Func1(void)
{

}
/**************************************************************************************************
@brief void Func2(void)
@param[in] none
@return none
**************************************************************************************************/
void Func2(void)
{

}
/**************************************************************************************************
@brief void Func3(void)
@param[in] none
@return none
**************************************************************************************************/
void Func3(void)
{

}

/**************************************************************************************************
@brief
@param[in] none
@return none
**************************************************************************************************/
void publicInterfaceInit(PublicApi_t *interface)
{
interface.func0 = Func0;
interface.func1 = Func1;
interface.func2 = Func2;
interface.func3 = Func3;
}

/*!
* you should be define it in your main thread loop and register it to your decouple library
*/
int main()
{
PublicApi_t interface;
publicInterfaceInit(&interface);
interfaceRegister(&interface);
}

Library

1
2
3
4
5
6
7
8
9
10
11
12
13
/*! 
* in your library you should instantiate it
*/
PublicApi_t *interfaceReg;
/**************************************************************************************************
@brief void interfaceRegister(PublicApi_t *interface_ptr)
@param[in] none
@return none
**************************************************************************************************/
void interfaceRegister(PublicApi_t *interface_ptr)
{
interfaceReg = interface_ptr;
}

IF you want to register configuration to platform, and the following method can be use

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
* user define structure
*/
typedef struct Parameters{
int address;
int size;
int paramNum;
int* paramType;
int* paramVal;
}Parameters_t;

/**************************************************************************************************
@brief call function
@param[in] none
@return none
**************************************************************************************************/
void testfunc()
{
// configure the parameters for xxx
Parameters_t params = {
.address = 0x1234,
.size = 0x1,
.paramNum = 6,
.paramType = (int[]){
1, 2, 3, 4, 5, 6
},
.paramVal = (int[]){
6, 5, 4, 3, 2, 1
}
};
interfaceReg->func0(&params);
}

zephyr

The following usage is based on zephyr v2.7.

Stack Usage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <zephyr.h>
#include <kernel.h>
#include <kernel_structs.h>
/*!
* stack guard default value
*/
#define STACK_GUARD_VALUE 0xAA

void check_stage_usage(k_tid_t tid,const char *thread_name, size_t stack_size)
{
size_t unused_stack_space;
size_t total_stack_space = stack_size;
struct k_thread *thread = (struct k_thread *) tid;
uint8_t *stack_ptr = (uint8_t *)thread->stack_info.start;
k_thread_stack_space_get(tid,&unused_stack_space);
//calculate the stack size usage
size_t used_stack_space = total_stack_space - unused_stack_space;
double stack_usage = (double)used_stack_space/total_stack_space;

if(stack_usage > 0.8)
{
// TODO
}
/*
The stack sentinel is placed at the far end of the stack, so if the stack grows
beyond its bounds, the sentinel value will be overwritten.
*/
if(stack_ptr[0]!=STACK_GUARD_VALUE)
{
//TOD: stack overflow
}
}

CPU Load

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#define LOOP_CYCLE 669/100
//used to calculate the current thread cpu load
uint32_t last_runtimes;
struct k_thread_runtime_stats stats;
k_thread_runtime_stats_get(k_current_get(),stats);
float cpu_load = (float)100 *(stats.execution_cycles - last_runtimes)/(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC/1000*LOOP_CYCLE);
last_runtimes = stats.execution_cycles;

//used to calculate the total thread cpu load
void thread_runtime_cb(struct k_thread *thread,void *user_data)
{
uint32_t *total*_runtime = (uint32_t *)user_data;
struct k_thread_runtime_stats stats;
k_thread_runtime_stats_get(thread,stats);
*total_runtime += stats.execution_cycles;
}

int get_cpu_load(void)
{
uint64_t total_runtime = 0;
float cpu_load;
k_thread_foreach(thread_runtime_cb,&total_runtime);
cpu_load = (float)100 * (total_runtime - last_total_runtime)/((CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC/1000*LOOP_CYCLE));
prink("cpu load = %.2f%%\n",cpu_load);
last_total_runtime = total_runtime;
return cpu_load;
}