├── .gitignore ├── Makefile ├── README.md ├── app ├── main.c ├── osal_main.c ├── print_task.c ├── statistics_task.c └── task_event.h ├── build.bfg ├── doc └── OSAL_API.pdf ├── hal ├── timer.c └── timer.h └── osal ├── osal.c ├── osal.h ├── osal_event.c ├── osal_event.h ├── osal_memory.c ├── osal_memory.h ├── osal_msg.c ├── osal_msg.h ├── osal_timer.c ├── osal_timer.h └── type.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | 38 | # Debug files 39 | *.dSYM/ 40 | *.su 41 | *.idb 42 | *.pdb 43 | 44 | # Kernel Module Compile Results 45 | *.mod* 46 | *.cmd 47 | modules.order 48 | Module.symvers 49 | Mkfile.old 50 | dkms.conf 51 | 52 | # user 53 | tags 54 | .tags 55 | obj/ 56 | build/ 57 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #工程名称 2 | TARGET = linux-osal-example 3 | 4 | #设置编译器 5 | #CC = arm-linux-gnueabihf-gcc 6 | CC = gcc 7 | 8 | #获取当前工作目录 9 | TOP=. 10 | 11 | #设置源文件后缀,c或cpp 12 | EXT = c 13 | 14 | #设置源文件搜索路径 15 | VPATH += $(TOP)/app:$(TOP)/hal:$(TOP)/osal 16 | 17 | #设置自定义源文件目录 18 | APP_DIR = $(TOP)/app 19 | HARD_DIR = $(TOP)/hal 20 | 21 | #设置中间目标文件目录 22 | OBJ_DIR = $(TOP)/obj 23 | 24 | #设定头文件包含目录 25 | INC_FLAGS += -I $(TOP)/app 26 | INC_FLAGS += -I $(TOP)/osal 27 | INC_FLAGS += -I $(TOP)/hal 28 | 29 | #编译选项 30 | CFLAGS += -W -g -O0 -std=gnu11 31 | 32 | #链接选项 33 | LFLAGS += -pthread 34 | 35 | #固定源文件添加 36 | C_SRC += $(shell find $(TOP)/app -name '*.$(EXT)') 37 | C_SRC += $(shell find $(TOP)/hal -name '*.$(EXT)') 38 | C_SRC += $(shell find $(TOP)/osal -name '*.$(EXT)') 39 | 40 | #自定义源文件添加 41 | # C_SRC += $(HARD_DIR)/uart.c $(APP_DIR)/ipc_udp.c 42 | 43 | #中间目标文件 44 | #C_OBJ += $(C_SRC:%.$(EXT)=%.o) 45 | C_SRC_NODIR = $(notdir $(C_SRC)) 46 | C_OBJ = $(patsubst %.$(EXT), $(OBJ_DIR)/%.o,$(C_SRC_NODIR)) 47 | 48 | #依赖文件 49 | C_DEP = $(patsubst %.$(EXT), $(OBJ_DIR)/%.d,$(C_SRC_NODIR)) 50 | 51 | .PHONY: all clean rebuild ctags 52 | 53 | all:$(C_OBJ) 54 | @echo "linking object to $(TARGET).elf" 55 | @$(CC) $(C_OBJ) -o $(TARGET).elf $(LFLAGS) 56 | 57 | $(OBJ_DIR)/%.o:%.$(EXT) 58 | @mkdir -p obj 59 | @echo "building $<" 60 | @$(CC) -c $(CFLAGS) $(INC_FLAGS) -o $@ $< 61 | 62 | -include $(C_DEP) 63 | $(OBJ_DIR)/%.d:%.$(EXT) 64 | @mkdir -p obj 65 | @echo "making $@" 66 | @set -e;rm -f $@;$(CC) -MM $(CFLAGS) $(INC_FLAGS) $< > $@.$$$$;sed 's,\($*\)\.o[ :]*,$(OBJ_DIR)/\1.o $(OBJ_DIR)/\1.d:,g' < $@.$$$$ > $@;rm -f $@.$$$$ 67 | 68 | clean: 69 | -rm -f obj/* 70 | -rm -f $(shell find ./ -name '*.elf') 71 | 72 | rebuild: clean all 73 | 74 | ctags: 75 | @ctags -R `pwd` 76 | @echo "making tags file" 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OSAL 2 | 3 | OSAL(operating system abstraction layer),操作系统抽象层,是一种以实现多任务为核心的系统资源管理机制,实现了类似操作系统的某些功能,但并不能称之为真正意义上的操作系统。本OSAL仓库源码来源于TI CC2530的zigbee协议栈Z-Stack中,剥离了其应用相关及不通用的功能模块,提取其最核心的事件驱动型多任务内核。OSAL的实现源码非常精简高效,总共约1100多行,全部纯C语言实现,最小资源占用要求为RAM约512Byte,ROM约2KB。理论上可以移植至全部支持C语言的芯片平台。 4 | 5 | ## OSAL移植的接口 6 | 7 | | OSAL接口 | 说明 | 8 | | -- | -- | 9 | | Message Management API | 消息管理 | 10 | | Task Synchronization API | 任务同步 | 11 | | Timer Management API | 定时器管理 | 12 | | Memory Management API | 内存管理 | 13 | 14 | ## 移植说明 15 | 16 | 1. 完成hal\timer.c文件,为系统提供滴答时钟,建议滴答心跳的周期为1~10ms,并对应修改hal\timer.h中的宏定义TICK_PERIOD_MS为相应心跳毫秒值; 17 | 2. 修改osal\type.h文件中的全局中断开关宏定义(可为空),根据需要修改数据类型的宏定义,根据实际芯片字长修改“halDataAlign_t”类型; 18 | 3. 根据需要修改osal\osal_memory.h文件中的内存池大小定义,默认最大为32768字节,osal\osal_memory.c中osalMemHdr_t类型需要确保长度为16bit或以上,非8位单片机需要设定内存池的字节对齐; 19 | 4. 添加任务函数中的任务优先级数值大的任务则优先级高; 20 | 5. 根据需要修改osal\osal_memory.h文件中的OSALMEM_METRICS定义,有效则开启内存统计功能; 21 | 22 | 各API的使用可参考doc下的官方API手册《OSAL_API.pdf》。 23 | 24 | ## 动态内存管理拓展说明 25 | 26 | OSAL中默认使用15位的数据标识管理内存,最大能管理32768字节,需要增加管理更多的动态内存可按照以下方式拓展: 27 | 28 | 1. 注释掉osal_memory.c中的内存大小编译限制; 29 | 2. 替换osal_memory.c中的全部uint16为osalMemHdr_t; 30 | 3. 修改osal_memory.h中的osalMemHdr_t类型宏为halDataAlign_t,确保芯片字长halDataAlign_t为32bit; 31 | 4. 修改osal_memory.c中的宏定义OSALMEM_IN_USE为0x80000000; 32 | 33 | ## 编译运行 34 | 35 | 本仓库在linux下可以直接编译运行基础例程,例程定义了两个任务,任务一使用定时器API进行定时触发打印事件,并累计打印次数,每累计5次就会向任务二发送统计事件,任务二接收任务一发送的统计事件后进行统计结果的打印输出。 36 | 37 | 编译: 38 | 39 | ```shell 40 | wat@wat:~$ make 41 | building ./app/main.c 42 | building ./app/osal_main.c 43 | building ./app/print_task.c 44 | building ./app/statistics_task.c 45 | building ./hal/timer.c 46 | building ./osal/osal_msg.c 47 | building ./osal/osal_event.c 48 | building ./osal/osal_timer.c 49 | building ./osal/osal_memory.c 50 | building ./osal/osal.c 51 | linking object to linux-osal-example.elf 52 | 53 | real 0m0.585s 54 | user 0m0.332s 55 | sys 0m0.242s 56 | ``` 57 | 58 | 运行: 59 | 60 | ```shell 61 | wat@wat:~$ ./linux-osal-example.elf 62 | Init hal timer ok ! 63 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 64 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 65 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 66 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 67 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 68 | Statistics task receive print task printf count : 5 69 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 70 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 71 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 72 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 73 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 74 | Statistics task receive print task printf count : 10 75 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 76 | Print task printing, total memory : 6144 byte, used memory : 92 byte ! 77 | ...... 78 | ``` 79 | -------------------------------------------------------------------------------- /app/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.c 3 | * @brief osal运行例程入口 4 | * @version 0.1 5 | * @date 2019-07-25 6 | * @author WatWu 7 | */ 8 | 9 | #include "task_event.h" 10 | 11 | /** 12 | * @brief 程序入口 13 | * @param argc [传入的参数数量] 14 | * @param argv [传入的参数列表] 15 | * @return int [无] 16 | */ 17 | int main(int argc, char *argv[]) 18 | { 19 | argc = argc; 20 | argv = argv; 21 | 22 | osal_main(); 23 | } 24 | -------------------------------------------------------------------------------- /app/osal_main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file osal_main.c 3 | * @brief osal操作系统运行主函数,添加任务在此文件中添加 4 | * @version 0.1 5 | * @date 2019-07-25 6 | * @author WatWu 7 | */ 8 | 9 | #include "task_event.h" 10 | 11 | void osal_main(void) 12 | { 13 | //系统硬件、外设等初始化 14 | 15 | //禁止中断 16 | HAL_DISABLE_INTERRUPTS(); 17 | 18 | //osal操作系统初始化 19 | osal_init_system(); 20 | 21 | //添加任务 22 | osal_add_Task(print_task_init, print_task_event_process, 1); 23 | osal_add_Task(statistics_task_init, statistics_task_event_process, 2); 24 | 25 | //添加的任务统一进行初始化 26 | osal_Task_init(); 27 | 28 | osal_mem_kick(); 29 | 30 | //允许中断 31 | HAL_ENABLE_INTERRUPTS(); 32 | 33 | //设置初始任务事件,上电就需要自动轮询的任务事件可在此添加 34 | 35 | //启动osal系统,不会再返回 36 | osal_start_system(); 37 | } 38 | -------------------------------------------------------------------------------- /app/print_task.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file print_task.c 3 | * @brief 打印任务 4 | * @version 0.1 5 | * @date 2019-07-25 6 | * @author WatWu 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "task_event.h" 14 | 15 | uint8 print_task_id; //记录打印任务的任务ID 16 | 17 | /** 18 | * @brief 任务初始化 19 | * @param task_id [初始化时分配给当前任务的任务ID,标记区分每一个任务] 20 | */ 21 | void print_task_init(uint8 task_id) 22 | { 23 | print_task_id = task_id; 24 | 25 | //开启一个循环定时器,每秒向打印任务发送PRINTF_STR事件 26 | osal_start_reload_timer(print_task_id, PRINTF_STR, 1000 / TICK_PERIOD_MS); 27 | } 28 | 29 | /** 30 | * @brief 当前任务的事件回调处理函数 31 | * @param task_id [任务ID] 32 | * @param task_event [收到的本任务事件] 33 | * @return uint16 [未处理的事件] 34 | */ 35 | uint16 print_task_event_process(uint8 task_id, uint16 task_event) 36 | { 37 | if(task_event & SYS_EVENT_MSG) //判断是否为系统消息事件 38 | { 39 | osal_sys_msg_t *msg_pkt; 40 | msg_pkt = (osal_sys_msg_t *)osal_msg_receive(task_id); //从消息队列获取一条消息 41 | 42 | while(msg_pkt) 43 | { 44 | switch(msg_pkt->hdr.event) //判断该消息事件类型 45 | { 46 | default: 47 | break; 48 | } 49 | 50 | osal_msg_deallocate((uint8 *)msg_pkt); //释放消息内存 51 | msg_pkt = (osal_sys_msg_t *)osal_msg_receive(task_id); //读取下一条消息 52 | } 53 | 54 | // return unprocessed events 55 | return (task_event ^ SYS_EVENT_MSG); 56 | } 57 | 58 | if(task_event & PRINTF_STR) 59 | { 60 | static int print_count = 0; 61 | printf("Print task printing, total memory : %d byte, used memory : %d byte !\n", MAXMEMHEAP, osal_heap_mem_used()); 62 | 63 | print_count++; 64 | if(print_count % 5 == 0 && print_count != 0) 65 | { 66 | //向统计任务发送消息 67 | general_msg_data_t *msg; 68 | msg = (general_msg_data_t*)osal_msg_allocate(sizeof(general_msg_data_t) + sizeof(int)); 69 | if(msg != NULL) 70 | { 71 | //消息结构体的data数据指针偏移至申请到的内存的数据段 72 | //msg->data = (unsigned char*)( msg + sizeof(osal_event_hdr_t) ); 73 | msg->data = (unsigned char*)(msg + 1); 74 | 75 | msg->hdr.event = PRINTF_STATISTICS; 76 | msg->hdr.status = 0; 77 | *((int*)msg->data) = print_count; 78 | 79 | osal_msg_send(statistics_task_id, (uint8*)msg); 80 | } 81 | } 82 | 83 | return task_event ^ PRINTF_STR; //处理完后需要清除事件位 84 | } 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /app/statistics_task.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file statistics_task.c 3 | * @brief 统计任务 4 | * @version 0.1 5 | * @date 2019-07-25 6 | * @author WatWu 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "task_event.h" 14 | 15 | uint8 statistics_task_id; //记录统计任务的任务ID 16 | 17 | /** 18 | * @brief 任务初始化 19 | * @param task_id [初始化时分配给当前任务的任务ID,标记区分每一个任务] 20 | */ 21 | void statistics_task_init(uint8 task_id) 22 | { 23 | statistics_task_id = task_id; 24 | } 25 | 26 | /** 27 | * @brief 当前任务的事件回调处理函数 28 | * @param task_id [任务ID] 29 | * @param task_event [收到的本任务事件] 30 | * @return uint16 [未处理的事件] 31 | */ 32 | uint16 statistics_task_event_process(uint8 task_id, uint16 task_event) 33 | { 34 | if(task_event & SYS_EVENT_MSG) //判断是否为系统消息事件 35 | { 36 | osal_sys_msg_t *msg_pkt; 37 | msg_pkt = (osal_sys_msg_t *)osal_msg_receive(task_id); //从消息队列获取一条消息 38 | 39 | while(msg_pkt) 40 | { 41 | switch(msg_pkt->hdr.event) //判断该消息事件类型 42 | { 43 | case PRINTF_STATISTICS: 44 | { 45 | int count = *(int*)(((general_msg_data_t*)msg_pkt)->data); 46 | printf("Statistics task receive print task printf count : %d\n", count); 47 | break; 48 | } 49 | 50 | default: 51 | break; 52 | } 53 | 54 | osal_msg_deallocate((uint8 *)msg_pkt); //释放消息内存 55 | msg_pkt = (osal_sys_msg_t *)osal_msg_receive(task_id); //读取下一条消息 56 | } 57 | 58 | // return unprocessed events 59 | return (task_event ^ SYS_EVENT_MSG); 60 | } 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /app/task_event.h: -------------------------------------------------------------------------------- 1 | #ifndef APPLICATION_H 2 | #define APPLICATION_H 3 | 4 | #include "osal.h" 5 | #include "osal_timer.h" 6 | #include "osal_event.h" 7 | #include "osal_memory.h" 8 | #include "osal_msg.h" 9 | 10 | //全局变量声明 11 | /*****************************************************************************/ 12 | 13 | typedef struct 14 | { 15 | osal_event_hdr_t hdr; //操作系统事件结构 16 | unsigned char *data; //命令帧操作数 17 | } general_msg_data_t; //自定义通用消息格式结构体 18 | 19 | /*****************************************************************************/ 20 | 21 | //所有任务的任务ID、初始化函数、事件处理函数、任务事件都统一在此文件声明或定义 22 | /*****************************************************************************/ 23 | 24 | //任务ID声明 25 | extern uint8 print_task_id; 26 | extern uint8 statistics_task_id; 27 | 28 | //任务初始化函数声明 29 | void print_task_init(uint8 task_id); 30 | void statistics_task_init(uint8 task_id); 31 | 32 | //任务事件处理函数声明 33 | uint16 print_task_event_process(uint8 task_id, uint16 task_event); 34 | uint16 statistics_task_event_process(uint8 task_id, uint16 task_event); 35 | 36 | //任务事件定义 37 | //系统消息事件,默认保留为osal系统使用,用于收发消息 38 | #define SYS_EVENT_MSG 0x8000 39 | 40 | //打印任务的任务事件定义 41 | #define PRINTF_STR 0X0001 //打印字符串事件 42 | 43 | //统计任务的系统消息事件定义 44 | #define PRINTF_STATISTICS 1 //打印统计消息事件 45 | 46 | /*****************************************************************************/ 47 | 48 | void osal_main(void); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /build.bfg: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | osal_files = find_files(['app', 'hal', 'osal'], '*.c') 4 | 5 | global_options(['-W', '-g', '-O0', '-std=gnu11'], lang='c') 6 | global_link_options(['-pthread']) 7 | 8 | executable('osal_test', files=osal_files, includes=['osal', 'hal', 'app'], compile_options=['-Wall'], lang='c') 9 | -------------------------------------------------------------------------------- /doc/OSAL_API.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcuwty/osal/9fabed30b0af7d4fd24c6dd5a2c70313a4f84927/doc/OSAL_API.pdf -------------------------------------------------------------------------------- /hal/timer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file timer.c 3 | * @brief 硬件定时器实现,为osal操作系统提供系统滴答心跳时钟,移植时需要修改该文件 4 | * @version 0.1 5 | * @date 2019-07-25 6 | * @author WatWu 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "timer.h" 17 | #include "osal_timer.h" 18 | 19 | //此处添加硬件定时器中断溢出函数,中断周期1~10ms,并在中断函数中调用系统时钟更新函数osal_update_timers() 20 | //即每次系统滴答心跳时调用一次osal_update_timers() 21 | 22 | //当前例程基于linux运行,使用线程休眠的方式模拟硬件定时器来实现心跳 23 | 24 | static pthread_t hal_timer_pthread_fd; 25 | 26 | /** 27 | * @brief 定时器线程,为osal提供滴答心跳,在单片机平台应该使用硬件定时器实现 28 | * @param pro [线程函数参数列表] 29 | * @return void* [无] 30 | */ 31 | static void* hal_timer_pthread(void *pro) 32 | { 33 | pro = pro; 34 | while(1) 35 | { 36 | usleep(10 * 1000); //10ms的心跳 37 | osal_update_timers(); 38 | } 39 | 40 | return 0; 41 | } 42 | 43 | /** 44 | * @brief 硬件定时器初始化,设定系统时钟 45 | */ 46 | void OSAL_TIMER_TICKINIT(void) 47 | { 48 | //创建定时器线程,使用线程来模拟定时器 49 | int ret = pthread_create(&hal_timer_pthread_fd, NULL, hal_timer_pthread, NULL); 50 | if(ret != 0) 51 | { 52 | perror("Create hal timer error"); 53 | exit(1); 54 | } 55 | printf("Init hal timer ok !\n"); 56 | } 57 | 58 | /** 59 | * @brief 开启硬件定时器,OSAL会根据程序中软件定时器的实际使用动态开启和关闭,为空则一直开启 60 | */ 61 | void OSAL_TIMER_TICKSTART(void) 62 | { 63 | 64 | } 65 | 66 | /** 67 | * @brief 关闭硬件定时器,为空则一直不关闭 68 | */ 69 | void OSAL_TIMER_TICKSTOP(void) 70 | { 71 | 72 | } 73 | -------------------------------------------------------------------------------- /hal/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMER_H 2 | #define TIMER_H 3 | 4 | #include "type.h" 5 | 6 | #define TICK_PERIOD_MS 10 7 | 8 | extern void OSAL_TIMER_TICKINIT(void); 9 | extern void OSAL_TIMER_TICKSTART(void); 10 | extern void OSAL_TIMER_TICKSTOP(void); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /osal/osal.c: -------------------------------------------------------------------------------- 1 | #include "osal.h" 2 | #include "osal_event.h" 3 | #include "osal_memory.h" 4 | 5 | #include 6 | 7 | osal_msg_q_t osal_qHead; 8 | 9 | /********************************************************************* 10 | * @fn osal_init_system 11 | * 12 | * @brief 13 | * 14 | * This function initializes the "task" system by creating the 15 | * tasks defined in the task table (OSAL_Tasks.h). 16 | * 17 | * @param void 18 | * 19 | * @return ZSUCCESS 20 | */ 21 | uint8 osal_init_system(void) 22 | { 23 | // Initialize the Memory Allocation System 24 | osal_mem_init(); 25 | 26 | // Initialize the message queue 27 | osal_qHead = NULL; 28 | 29 | #if defined( OSAL_TOTAL_MEM ) 30 | osal_msg_cnt = 0; 31 | #endif 32 | 33 | osalTimerInit(); 34 | osal_init_TaskHead(); 35 | 36 | return (ZSUCCESS); 37 | } 38 | 39 | /********************************************************************* 40 | * @fn osal_start_system 41 | * 42 | * @brief 43 | * 44 | * This function is the main loop function of the task system. It 45 | * will look through all task events and call the task_event_processor() 46 | * function for the task with the event. If there are no events (for 47 | * all tasks), this function puts the processor into Sleep. 48 | * This Function doesn't return. 49 | * 50 | * @param void 51 | * 52 | * @return none 53 | */ 54 | void osal_start_system(void) 55 | { 56 | uint16 events; 57 | uint16 retEvents; 58 | 59 | while(1) 60 | { 61 | TaskActive = osalNextActiveTask(); 62 | if(TaskActive) 63 | { 64 | HAL_ENTER_CRITICAL_SECTION(); 65 | events = TaskActive->events; 66 | // Clear the Events for this task 67 | TaskActive->events = 0; 68 | HAL_EXIT_CRITICAL_SECTION(); 69 | 70 | if(events != 0) 71 | { 72 | // Call the task to process the event(s) 73 | if(TaskActive->pfnEventProcessor) 74 | { 75 | retEvents = (TaskActive->pfnEventProcessor)(TaskActive->taskID, events); 76 | 77 | // Add back unprocessed events to the current task 78 | HAL_ENTER_CRITICAL_SECTION(); 79 | TaskActive->events |= retEvents; 80 | HAL_EXIT_CRITICAL_SECTION(); 81 | } 82 | } 83 | } 84 | } 85 | } 86 | 87 | /********************************************************************* 88 | * @fn osal_strlen 89 | * 90 | * @brief 91 | * 92 | * Calculates the length of a string. The string must be null 93 | * terminated. 94 | * 95 | * @param char *pString - pointer to text string 96 | * 97 | * @return int - number of characters 98 | */ 99 | int osal_strlen(char *pString) 100 | { 101 | return (int)(strlen(pString)); 102 | } 103 | 104 | /********************************************************************* 105 | * @fn osal_memcpy 106 | * 107 | * @brief 108 | * 109 | * Generic memory copy. 110 | * 111 | * Note: This function differs from the standard memcpy(), since 112 | * it returns the pointer to the next destination uint8. The 113 | * standard memcpy() returns the original destination address. 114 | * 115 | * @param dst - destination address 116 | * @param src - source address 117 | * @param len - number of bytes to copy 118 | * 119 | * @return pointer to end of destination buffer 120 | */ 121 | void *osal_memcpy(void *dst, const void *src, unsigned int len) 122 | { 123 | uint8 *pDst; 124 | const uint8 *pSrc; 125 | 126 | pSrc = src; 127 | pDst = dst; 128 | 129 | while(len--) 130 | *pDst++ = *pSrc++; 131 | 132 | return (pDst); 133 | } 134 | 135 | /********************************************************************* 136 | * @fn osal_revmemcpy 137 | * 138 | * @brief Generic reverse memory copy. Starts at the end of the 139 | * source buffer, by taking the source address pointer and moving 140 | * pointer ahead "len" bytes, then decrementing the pointer. 141 | * 142 | * Note: This function differs from the standard memcpy(), since 143 | * it returns the pointer to the next destination uint8. The 144 | * standard memcpy() returns the original destination address. 145 | * 146 | * @param dst - destination address 147 | * @param src - source address 148 | * @param len - number of bytes to copy 149 | * 150 | * @return pointer to end of destination buffer 151 | */ 152 | void *osal_revmemcpy(void *dst, const void *src, unsigned int len) 153 | { 154 | uint8 *pDst; 155 | const uint8 *pSrc; 156 | 157 | pSrc = src; 158 | pSrc += (len - 1); 159 | pDst = dst; 160 | 161 | while(len--) 162 | *pDst++ = *pSrc--; 163 | 164 | return (pDst); 165 | } 166 | 167 | /********************************************************************* 168 | * @fn osal_memdup 169 | * 170 | * @brief Allocates a buffer [with osal_mem_alloc()] and copies 171 | * the src buffer into the newly allocated space. 172 | * 173 | * @param src - source address 174 | * @param len - number of bytes to copy 175 | * 176 | * @return pointer to the new allocated buffer, or NULL if 177 | * allocation problem. 178 | */ 179 | void *osal_memdup(const void *src, unsigned int len) 180 | { 181 | uint8 *pDst; 182 | 183 | pDst = osal_mem_alloc(len); 184 | if(pDst) 185 | { 186 | osal_memcpy(pDst, src, len); 187 | } 188 | 189 | return ((void *)pDst); 190 | } 191 | 192 | /********************************************************************* 193 | * @fn osal_memcmp 194 | * 195 | * @brief 196 | * 197 | * Generic memory compare. 198 | * 199 | * @param src1 - source 1 addrexx 200 | * @param src2 - source 2 address 201 | * @param len - number of bytes to compare 202 | * 203 | * @return TRUE - same, FALSE - different 204 | */ 205 | uint8 osal_memcmp(const void *src1, const void *src2, unsigned int len) 206 | { 207 | const uint8 *pSrc1; 208 | const uint8 *pSrc2; 209 | 210 | pSrc1 = src1; 211 | pSrc2 = src2; 212 | 213 | while(len--) 214 | { 215 | if(*pSrc1++ != *pSrc2++) 216 | return FALSE; 217 | } 218 | return TRUE; 219 | } 220 | 221 | /********************************************************************* 222 | * @fn osal_memset 223 | * 224 | * @brief 225 | * 226 | * Set memory buffer to value. 227 | * 228 | * @param dest - pointer to buffer 229 | * @param value - what to set each uint8 of the message 230 | * @param size - how big 231 | * 232 | * @return pointer to destination buffer 233 | */ 234 | void *osal_memset(void *dest, uint8 value, int len) 235 | { 236 | return memset(dest, value, len); 237 | } 238 | -------------------------------------------------------------------------------- /osal/osal.h: -------------------------------------------------------------------------------- 1 | #ifndef OSAL_H 2 | #define OSAL_H 3 | 4 | #include "type.h" 5 | 6 | typedef struct 7 | { 8 | void *next; 9 | uint16 len; 10 | uint8 dest_id; 11 | } osal_msg_hdr_t; 12 | 13 | typedef struct 14 | { 15 | uint8 event; 16 | uint8 status; 17 | } osal_event_hdr_t; 18 | 19 | typedef struct 20 | { 21 | osal_event_hdr_t hdr; 22 | uint8* Data_t; 23 | } osal_sys_msg_t; //默认系统消息结构体 24 | 25 | typedef void *osal_msg_q_t; 26 | 27 | extern osal_msg_q_t osal_qHead; 28 | extern uint8 tasksCnt; //任务数量统计 29 | 30 | extern uint8 osal_init_system(void); 31 | int osal_strlen(char *pString); 32 | void *osal_memcpy(void *dst, const void *src, unsigned int len); 33 | void *osal_revmemcpy(void *dst, const void *src, unsigned int len); 34 | void *osal_memdup(const void *src, unsigned int len); 35 | uint8 osal_memcmp(const void *src1, const void *src2, unsigned int len); 36 | void *osal_memset(void *dest, uint8 value, int len); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /osal/osal_event.c: -------------------------------------------------------------------------------- 1 | #include "osal_event.h" 2 | #include "osal_memory.h" 3 | 4 | OsalTadkREC_t *TaskHead; 5 | OsalTadkREC_t *TaskActive; 6 | 7 | uint8 Task_id; //任务ID统计 8 | uint8 tasksCnt; //任务数量统计 9 | 10 | /********************************************************************* 11 | * @fn osal_set_event 12 | * 13 | * @brief 14 | * 15 | * This function is called to set the event flags for a task.The 16 | * event passed in is OR'd into the task's event variable. 17 | * 18 | * @param byte task_id - receiving tasks ID 19 | * @param byte event_flag - what event to set 20 | * 21 | * @return ZSUCCESS, INVALID_TASK 22 | */ 23 | uint8 osal_set_event(byte task_id, uint16 event_flag) 24 | { 25 | OsalTadkREC_t *srchTask; 26 | 27 | srchTask = osalFindTask(task_id); 28 | if(srchTask) 29 | { 30 | // Hold off interrupts 31 | HAL_ENTER_CRITICAL_SECTION(); 32 | // Stuff the event bit(s) 33 | srchTask->events |= event_flag; 34 | // Release interrupts 35 | HAL_EXIT_CRITICAL_SECTION(); 36 | } 37 | else 38 | return (INVALID_TASK); 39 | 40 | return (ZSUCCESS); 41 | } 42 | 43 | /********************************************************************* 44 | * @fn osal_clear_event 45 | * 46 | * @brief 47 | * 48 | * This function is called to clear the event flags for a task. The 49 | * event passed in is masked out of the task's event variable. 50 | * 51 | * @param uint8 task_id - receiving tasks ID 52 | * @param uint8 event_flag - what event to clear 53 | * 54 | * @return SUCCESS, INVALID_TASK 55 | */ 56 | uint8 osal_clear_event(uint8 task_id, uint16 event_flag) 57 | { 58 | OsalTadkREC_t *srchTask; 59 | 60 | srchTask = osalFindTask(task_id); 61 | if(srchTask) 62 | { 63 | // Hold off interrupts 64 | HAL_ENTER_CRITICAL_SECTION(); 65 | // Stuff the event bit(s) 66 | srchTask->events &= ~event_flag; 67 | // Release interrupts 68 | HAL_EXIT_CRITICAL_SECTION(); 69 | } 70 | else 71 | return (INVALID_TASK); 72 | 73 | return (ZSUCCESS); 74 | } 75 | 76 | /*************************************************************************** 77 | * @fn osal_init_TaskHead 78 | * 79 | * @brief init task link's head 80 | * 81 | * @param none 82 | * 83 | * @return 84 | */ 85 | void osal_init_TaskHead(void) 86 | { 87 | TaskHead = (OsalTadkREC_t *)NULL; 88 | TaskActive = (OsalTadkREC_t *)NULL; 89 | Task_id = 0; 90 | } 91 | 92 | /*************************************************************************** 93 | * @fn osal_Task_init 94 | * 95 | * @brief init task 96 | * 97 | * @param none 98 | * 99 | * @return 100 | */ 101 | void osal_Task_init(void) 102 | { 103 | TaskActive = TaskHead; 104 | while(TaskActive) 105 | { 106 | if(TaskActive->pfnInit) 107 | { 108 | TaskActive->pfnInit(TaskActive->taskID); 109 | } 110 | TaskActive = TaskActive->next; 111 | } 112 | TaskActive = (OsalTadkREC_t *)NULL; 113 | } 114 | 115 | /*************************************************************************** 116 | * @fn osal_add_Task 117 | * 118 | * @brief osal_add_Task 119 | * 120 | * @param none 121 | * 122 | * @return 123 | */ 124 | void osal_add_Task(pTaskInitFn pfnInit, 125 | pTaskEventHandlerFn pfnEventProcessor, 126 | uint8 taskPriority) 127 | { 128 | OsalTadkREC_t *TaskNew; 129 | OsalTadkREC_t *TaskSech; 130 | OsalTadkREC_t **TaskPTR; 131 | TaskNew = osal_mem_alloc(sizeof(OsalTadkREC_t)); 132 | if(TaskNew) 133 | { 134 | TaskNew->pfnInit = pfnInit; 135 | TaskNew->pfnEventProcessor = pfnEventProcessor; 136 | TaskNew->taskID = Task_id++; 137 | TaskNew->events = 0; 138 | TaskNew->taskPriority = taskPriority; 139 | TaskNew->next = (OsalTadkREC_t *)NULL; 140 | 141 | TaskPTR = &TaskHead; 142 | TaskSech = TaskHead; 143 | 144 | tasksCnt++; //任务数量统计 145 | 146 | while(TaskSech) 147 | { 148 | if(TaskNew->taskPriority > TaskSech->taskPriority) 149 | { 150 | TaskNew->next = TaskSech; 151 | *TaskPTR = TaskNew; 152 | return; 153 | } 154 | TaskPTR = &TaskSech->next; 155 | TaskSech = TaskSech->next; 156 | } 157 | *TaskPTR = TaskNew; 158 | } 159 | return; 160 | } 161 | 162 | /********************************************************************* 163 | * @fn osalNextActiveTask 164 | * 165 | * @brief This function will return the next active task. 166 | * 167 | * NOTE: Task queue is in priority order. We can stop at the 168 | * first task that is "ready" (events element non-zero) 169 | * 170 | * @param none 171 | * 172 | * @return pointer to the found task, NULL if not found 173 | */ 174 | OsalTadkREC_t *osalNextActiveTask(void) 175 | { 176 | OsalTadkREC_t *TaskSech; 177 | 178 | // Start at the beginning 179 | TaskSech = TaskHead; 180 | 181 | // When found or not 182 | while(TaskSech) 183 | { 184 | if(TaskSech->events) 185 | { 186 | // task is highest priority that is ready 187 | return TaskSech; 188 | } 189 | TaskSech = TaskSech->next; 190 | } 191 | return NULL; 192 | } 193 | 194 | /********************************************************************* 195 | * @fn osalFindActiveTask 196 | * 197 | * @brief This function will return the taskid task. 198 | * 199 | * NOTE: Task queue is in priority order. We can stop at the 200 | * first task that is "ready" (events element non-zero) 201 | * 202 | * @param task_id 203 | * 204 | * @return pointer to the found task, NULL if not found 205 | */ 206 | OsalTadkREC_t *osalFindTask(uint8 taskID) 207 | { 208 | OsalTadkREC_t *TaskSech; 209 | TaskSech = TaskHead; 210 | while(TaskSech) 211 | { 212 | if(TaskSech->taskID == taskID) 213 | { 214 | return (TaskSech); 215 | } 216 | TaskSech = TaskSech->next; 217 | } 218 | return ((OsalTadkREC_t *)NULL); 219 | } 220 | -------------------------------------------------------------------------------- /osal/osal_event.h: -------------------------------------------------------------------------------- 1 | #ifndef OSAL_EVENT_H 2 | #define OSAL_EVENT_H 3 | 4 | #include "type.h" 5 | #include "osal_timer.h" 6 | 7 | typedef void (*pTaskInitFn)(uint8 task_id); 8 | typedef uint16(*pTaskEventHandlerFn)(uint8 task_id, uint16 task_event); 9 | 10 | /** 11 | * @brief 任务链表 12 | */ 13 | typedef struct OSALTaskREC 14 | { 15 | struct OSALTaskREC *next; 16 | pTaskInitFn pfnInit; //任务初始化函数指针 17 | pTaskEventHandlerFn pfnEventProcessor; //任务事件处理函数指针 18 | uint8 taskID; //任务ID 19 | uint8 taskPriority; //任务优先级 20 | uint16 events; //任务事件 21 | } OsalTadkREC_t; 22 | 23 | extern OsalTadkREC_t *TaskActive; 24 | 25 | extern void osal_start_system(void); 26 | extern void osal_add_Task(pTaskInitFn pfnInit, pTaskEventHandlerFn pfnEventProcessor, uint8 taskPriority); 27 | extern void osal_Task_init(void); 28 | extern void osal_init_TaskHead(void); 29 | extern OsalTadkREC_t *osalNextActiveTask(void); 30 | extern OsalTadkREC_t *osalFindTask(uint8 taskID); 31 | extern uint8 osal_set_event(byte task_id, uint16 event_flag); 32 | extern uint8 osal_clear_event(uint8 task_id, uint16 event_flag); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /osal/osal_memory.c: -------------------------------------------------------------------------------- 1 | #include "osal_memory.h" 2 | #include "type.h" 3 | 4 | #if ( MAXMEMHEAP >= 32768 ) //内存管理默认使用15位数据标识,最大能管理32768字节 5 | #error MAXMEMHEAP is too big to manage! 6 | #endif 7 | 8 | //查找到合适的内存块之后,就要决定是否对此内存块进行分割。 9 | //如果内存块过大的话必然会造成内存的浪费。 10 | //如果内存块的大小减去要申请的内存块的值大于OSALMEM_MIN_BLKSZ(4byte), 11 | //则分割此内存块。并初使化分割出来的内存分配控制块头。 12 | #if !defined ( OSALMEM_MIN_BLKSZ ) 13 | #define OSALMEM_MIN_BLKSZ 4 14 | #endif 15 | 16 | #if !defined ( OSALMEM_SMALL_BLKSZ ) 17 | #define OSALMEM_SMALL_BLKSZ 16 //固定内存分配区域的固定长度,16字节 18 | #endif 19 | 20 | #if !defined ( OSALMEM_GUARD ) 21 | #define OSALMEM_GUARD TRUE // TBD - Hacky workaround til Bugzilla 1252 is fixed! 22 | #define OSALMEM_READY 0xE2 23 | #endif 24 | 25 | //内存分配返回的是一个指向分配区域的指针,指针的长度是内存控制头和内存对齐方式中较大的一个。 26 | //并且这个长度也是最小分配单元的长度。在OSAL中它的长度是16bit。 27 | //此处需要根据实际编译环境修改,确保osalMemHdr_t长度为16bit或以上 28 | typedef halDataAlign_t osalMemHdr_t; 29 | 30 | /********************************************************************* 31 | * CONSTANTS 32 | */ 33 | 34 | #define OSALMEM_IN_USE 0x8000 //内存控制头(16位)最高位标识该内存块是否被使用 35 | 36 | /* This number sets the size of the small-block bucket. Although profiling 37 | * shows max simultaneous alloc of 16x18, timing without profiling overhead 38 | * shows that the best worst case is achieved with the following. 39 | 根据程序的概要分析,最大的同时分配的大小是16x18, 如果不进行程序概要分析, 40 | 在定时分析系统的开销时,最坏情况里面的最好情况的内存分配大小是232(byte)的长度。 41 | 所以把固定分配区域的长度定义为232(byte)。 42 | */ 43 | #define SMALLBLKHEAP 232 44 | 45 | //内存分配返回的是一个指向分配区域的指针,指针的长度是内存控制头和内存对齐方式中较大的一个。 46 | //并且这个长度也是最小分配单元的长度。在些OSAL中它的长度是16bit。 47 | //此处需要根据实际编译环境修改,确保osalMemHdr_t长度为16bit或以上 48 | // To maintainalignment of the pointer returned, reserve the greater 49 | // space for the memory block header. 50 | #define HDRSZ ( (sizeof ( halDataAlign_t ) > sizeof( osalMemHdr_t )) ? \ 51 | sizeof ( halDataAlign_t ) : sizeof( osalMemHdr_t ) ) 52 | 53 | #if ( OSALMEM_GUARD ) 54 | static byte ready = 0; 55 | #endif 56 | 57 | static osalMemHdr_t *ff1; // First free block in the small-block bucket. 58 | static osalMemHdr_t *ff2; // First free block after the small-block bucket. 59 | 60 | #if defined( EXTERNAL_RAM ) 61 | static byte *theHeap = (byte *)EXT_RAM_BEG; 62 | #else 63 | static halDataAlign_t _theHeap[ MAXMEMHEAP / sizeof(halDataAlign_t) ]; 64 | // static __align(32) halDataAlign_t _theHeap[ MAXMEMHEAP / sizeof( halDataAlign_t ) ]; 65 | //根据实际使用的芯片设定内存对齐,__align(32),非常重要!!! 66 | static byte *theHeap = (byte *)_theHeap; 67 | #endif 68 | 69 | #if OSALMEM_METRICS 70 | static uint16 blkMax; // Max cnt of all blocks ever seen at once. 71 | static uint16 blkCnt; // Current cnt of all blocks. 72 | static uint16 blkFree; // Current cnt of free blocks. 73 | static uint16 memAlo; // Current total memory allocated. 74 | static uint16 memMax; // Max total memory ever allocated at once. 75 | #endif 76 | /********************************************************************* 77 | * LOCAL FUNCTIONS 78 | */ 79 | 80 | /********************************************************************* 81 | * @fn osal_mem_init 82 | * 83 | * @brief Initialize the heap memory management system. 84 | * 85 | * @param void 86 | * 87 | * @return void 88 | */ 89 | void osal_mem_init(void) 90 | { 91 | osalMemHdr_t *tmp; 92 | // Setup a NULL block at the end of the heap for fast comparisons with zero. 93 | //整个内存池最后的两个字节清零,避免分配内存产生溢出 94 | tmp = (osalMemHdr_t *)theHeap + (MAXMEMHEAP / HDRSZ) - 1; 95 | *tmp = 0; 96 | 97 | // Setup a small-block bucket. 98 | //设置固定长度内存区长度,232字节,内存区第一个字保存该区长度 99 | tmp = (osalMemHdr_t *)theHeap; 100 | *tmp = SMALLBLKHEAP; 101 | 102 | // Setup the wilderness. 103 | //设置可变产地内存区长度,内存区第一个字保存该区长度 104 | tmp = (osalMemHdr_t *)theHeap + (SMALLBLKHEAP / HDRSZ); 105 | *tmp = ((MAXMEMHEAP / HDRSZ) * HDRSZ) - SMALLBLKHEAP - HDRSZ; 106 | 107 | #if ( OSALMEM_GUARD ) 108 | ready = OSALMEM_READY; 109 | #endif 110 | 111 | // Setup a NULL block that is never freed so that the small-block bucket 112 | // is never coalesced with the wilderness. 113 | ff1 = tmp; 114 | ff2 = osal_mem_alloc(0); 115 | ff1 = (osalMemHdr_t *)theHeap; 116 | /* 117 | 上述语句将在固定长度分配区域和可变分配区域之间申请一个0大小的内存块, 118 | 相当于在固定分配区域和可变分配区域之间保留了一个一直处于使用状态, 119 | 但是指向长度为0的一个内存分配控制块。 120 | 这个内存块的是将两个分配区域隔离开,以免和可变长度分配区域合并。 121 | */ 122 | 123 | #if ( OSALMEM_METRICS ) 124 | /* Start with the small-block bucket and the wilderness - don't count the 125 | * end-of-heap NULL block nor the end-of-small-block NULL block. 126 | */ 127 | blkCnt = blkFree = 2; 128 | memAlo = 0; 129 | #endif 130 | } 131 | 132 | /********************************************************************* 133 | * @fn osal_mem_kick 134 | * 135 | * @brief Kick the ff1 pointer out past the long-lived OSAL Task blocks. 136 | * Invoke this once after all long-lived blocks have been allocated - 137 | * presently at the end of osal_init_system(). 138 | * 使FF1跳过固定长度区域,指向FF2(可变长度区域),也就是这个意思: 139 | * 如果在固定分配区域中没有申请内存成功, 140 | * 调用此函数后它将修改指向固定分配区域的指针使指针指向可变分配区域, 141 | * 然后再调用osal_mem_alloc 它将在可变长度分配区域中进行内存分配。 142 | * 143 | * @param void 144 | * 145 | * @return void 146 | */ 147 | void osal_mem_kick(void) 148 | { 149 | //halIntState_t intState; 150 | HAL_ENTER_CRITICAL_SECTION(); // Hold off interrupts. 151 | 152 | /* Logic in osal_mem_free() will ratchet ff1 back down to the first free 153 | * block in the small-block bucket. 154 | */ 155 | ff1 = ff2; 156 | 157 | HAL_EXIT_CRITICAL_SECTION(); // Re-enable interrupts. 158 | } 159 | 160 | /********************************************************************* 161 | * @fn osal_mem_alloc 162 | * 163 | * @brief Implementation of the allocator functionality. 164 | * 165 | * @param size - number of bytes to allocate from the heap. 166 | * 167 | * @return void * - pointer to the heap allocation; NULL if error or failure. 168 | */ 169 | void *osal_mem_alloc(uint16 size) 170 | { 171 | osalMemHdr_t *prev; 172 | osalMemHdr_t *hdr; 173 | uint16 tmp; 174 | byte coal = 0; 175 | 176 | #if ( OSALMEM_GUARD ) 177 | // Try to protect against premature use by HAL / OSAL. 178 | if(ready != OSALMEM_READY) 179 | { 180 | osal_mem_init(); 181 | } 182 | #endif 183 | 184 | size += HDRSZ; 185 | 186 | // Calculate required bytes to add to 'size' to align to halDataAlign_t. 187 | //根据实际的芯片的字长halDataAlign_t进行字节对齐 188 | if(sizeof(halDataAlign_t) == 2) 189 | { 190 | size += (size & 0x01); 191 | } 192 | else if(sizeof(halDataAlign_t) != 1) 193 | { 194 | const byte mod = size % sizeof(halDataAlign_t); 195 | 196 | if(mod != 0) 197 | { 198 | size += (sizeof(halDataAlign_t) - mod); 199 | } 200 | } 201 | 202 | HAL_ENTER_CRITICAL_SECTION(); // Hold off interrupts. 203 | 204 | // Smaller allocations are first attempted in the small-block bucket. 205 | if(size <= OSALMEM_SMALL_BLKSZ) 206 | { 207 | hdr = ff1; 208 | } 209 | else 210 | { 211 | hdr = ff2; 212 | } 213 | tmp = *hdr; 214 | 215 | do 216 | { 217 | if(tmp & OSALMEM_IN_USE) 218 | { 219 | tmp ^= OSALMEM_IN_USE; //该片已被使用,得出长度 220 | coal = 0; //找到空内存标志清零,因为遇到了一片已使用的内存 221 | } 222 | else //该片未被使用 223 | { 224 | if(coal != 0) //上轮查找有找到空内存,但空间不够 225 | { 226 | #if ( OSALMEM_METRICS ) 227 | blkCnt--; //内存合并,总内存块计数减一 228 | blkFree--; //内存合并,空闲内存块计数减一 229 | #endif 230 | *prev += *hdr; //加上本次找到的空内存大小 231 | 232 | if(*prev >= size) //加上后内存大小符合申请需要 233 | { 234 | hdr = prev; //返回该内存块 235 | tmp = *hdr; //得出长度 236 | break; 237 | } 238 | } 239 | else //上轮查找未找到空内存 240 | { 241 | if(tmp >= size) //该片内存大小符合需求,跳出查找循环 242 | { 243 | break; 244 | } 245 | 246 | coal = 1; //该片内存大小不符合需求,标记找到一块空内存 247 | prev = hdr; //记录该内存 248 | } 249 | } 250 | 251 | hdr = (osalMemHdr_t *)((byte *)hdr + tmp); //偏移至下一片内存区域 252 | 253 | tmp = *hdr; //读取该区域长度 254 | if(tmp == 0) 255 | { 256 | hdr = ((void *)NULL); 257 | break; 258 | } 259 | } while(1); 260 | 261 | if(hdr != ((void *)NULL)) 262 | { 263 | tmp -= size; //本次申请后剩余长度 264 | // Determine whether the threshold for splitting is met. 265 | if(tmp >= OSALMEM_MIN_BLKSZ) //剩余空间大于最小需求空间,分割内存供下次申请 266 | { 267 | // Split the block before allocating it. 268 | osalMemHdr_t *next = (osalMemHdr_t *)((byte *)hdr + size); //偏移 269 | *next = tmp; //记录未使用区域剩余长度 270 | *hdr = (size | OSALMEM_IN_USE); //标志本次申请区域已被使用,并记录本次使用长度 271 | 272 | #if ( OSALMEM_METRICS ) 273 | blkCnt++; //内存分割,总内存块计数加一 274 | if(blkMax < blkCnt) 275 | { 276 | blkMax = blkCnt; //调整内存块数量最大值 277 | } 278 | memAlo += size; //调整已用内存大小 279 | #endif 280 | } 281 | else 282 | { 283 | #if ( OSALMEM_METRICS ) 284 | memAlo += *hdr; 285 | blkFree--; //内存不分割,空闲内存块计数减一 286 | #endif 287 | 288 | *hdr |= OSALMEM_IN_USE; 289 | } 290 | 291 | #if ( OSALMEM_METRICS ) 292 | if(memMax < memAlo) 293 | { 294 | memMax = memAlo; 295 | } 296 | #endif 297 | 298 | hdr++; //偏移,返回实际申请的内存地址 299 | } 300 | 301 | HAL_EXIT_CRITICAL_SECTION(); // Re-enable interrupts. 302 | 303 | return (void *)hdr; 304 | } 305 | 306 | /********************************************************************* 307 | * @fn osal_mem_free 308 | * 309 | * @brief Implementation of the de-allocator functionality. 310 | * 311 | * @param ptr - pointer to the memory to free. 312 | * 313 | * @return void 314 | */ 315 | void osal_mem_free(void *ptr) 316 | { 317 | osalMemHdr_t *currHdr; 318 | //halIntState_t intState; 319 | 320 | #if ( OSALMEM_GUARD ) 321 | // Try to protect against premature use by HAL / OSAL. 322 | if(ready != OSALMEM_READY) 323 | { 324 | osal_mem_init(); 325 | } 326 | #endif 327 | 328 | HAL_ENTER_CRITICAL_SECTION(); // Hold off interrupts. 329 | 330 | currHdr = (osalMemHdr_t *)ptr - 1; 331 | 332 | *currHdr &= ~OSALMEM_IN_USE; 333 | 334 | if(ff1 > currHdr) 335 | { 336 | ff1 = currHdr; 337 | } 338 | 339 | #if OSALMEM_METRICS 340 | memAlo -= *currHdr; 341 | blkFree++; 342 | #endif 343 | 344 | HAL_EXIT_CRITICAL_SECTION(); // Re-enable interrupts. 345 | } 346 | 347 | #if OSALMEM_METRICS 348 | /********************************************************************* 349 | * @fn osal_heap_block_max 350 | * 351 | * @brief Return the maximum number of blocks ever allocated at once. 352 | * 353 | * @param none 354 | * 355 | * @return Maximum number of blocks ever allocated at once. 356 | */ 357 | uint16 osal_heap_block_max(void) 358 | { 359 | return blkMax; 360 | } 361 | 362 | /********************************************************************* 363 | * @fn osal_heap_block_cnt 364 | * 365 | * @brief Return the current number of blocks now allocated. 366 | * 367 | * @param none 368 | * 369 | * @return Current number of blocks now allocated. 370 | */ 371 | uint16 osal_heap_block_cnt(void) 372 | { 373 | return blkCnt; 374 | } 375 | 376 | /********************************************************************* 377 | * @fn osal_heap_block_free 378 | * 379 | * @brief Return the current number of free blocks. 380 | * 381 | * @param none 382 | * 383 | * @return Current number of free blocks. 384 | */ 385 | uint16 osal_heap_block_free(void) 386 | { 387 | return blkFree; 388 | } 389 | 390 | /********************************************************************* 391 | * @fn osal_heap_mem_used 392 | * 393 | * @brief Return the current number of bytes allocated. 394 | * 395 | * @param none 396 | * 397 | * @return Current number of bytes allocated. 398 | */ 399 | uint16 osal_heap_mem_used(void) 400 | { 401 | return memAlo; 402 | } 403 | 404 | /********************************************************************* 405 | * @fn osal_heap_high_water 406 | * 407 | * @brief Return the highest byte ever allocated in the heap. 408 | * 409 | * @param none 410 | * 411 | * @return Highest number of bytes ever used by the stack. 412 | */ 413 | uint16 osal_heap_high_water(void) 414 | { 415 | #if ( OSALMEM_METRICS ) 416 | return memMax; 417 | #else 418 | return MAXMEMHEAP; 419 | #endif 420 | } 421 | 422 | //返回内存使用率 423 | uint16 osal_heap_mem_usage_rate(void) 424 | { 425 | return (uint16)(memAlo / (MAXMEMHEAP / 100)); 426 | } 427 | 428 | #endif 429 | -------------------------------------------------------------------------------- /osal/osal_memory.h: -------------------------------------------------------------------------------- 1 | #ifndef OSALMEM_METRICS_H 2 | #define OSALMEM_METRICS_H 3 | 4 | #include "type.h" 5 | 6 | #define MAXMEMHEAP 1024*6 //内存池大小,单位字节 7 | 8 | #define OSALMEM_METRICS 1 //定义有效则开启内存统计 9 | 10 | void osal_mem_init(void); 11 | void osal_mem_kick(void); 12 | void *osal_mem_alloc(uint16 size); 13 | void osal_mem_free(void *ptr); 14 | 15 | #if OSALMEM_METRICS 16 | uint16 osal_heap_block_max(void); 17 | uint16 osal_heap_block_cnt(void); 18 | uint16 osal_heap_block_free(void); 19 | uint16 osal_heap_mem_used(void); 20 | uint16 osal_heap_high_water(void); 21 | uint16 osal_heap_mem_usage_rate(void); 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /osal/osal_msg.c: -------------------------------------------------------------------------------- 1 | #include "osal_msg.h" 2 | #include "osal_memory.h" 3 | #include "osal_event.h" 4 | 5 | #define SYS_EVENT_MSG 0x8000 6 | 7 | /********************************************************************* 8 | * @fn osal_msg_allocate 9 | * 10 | * @brief 11 | * 12 | * This function is called by a task to allocate a message buffer 13 | * into which the task will encode the particular message it wishes 14 | * to send. This common buffer scheme is used to strictly limit the 15 | * creation of message buffers within the system due to RAM size 16 | * limitations on the microprocessor. Note that all message buffers 17 | * are a fixed size (at least initially). The parameter len is kept 18 | * in case a message pool with varying fixed message sizes is later 19 | * created (for example, a pool of message buffers of size LARGE, 20 | * MEDIUM and SMALL could be maintained and allocated based on request 21 | * from the tasks). 22 | * 23 | * @param uint8 len - wanted buffer length 24 | * @return pointer to allocated buffer or NULL if allocation failed. 25 | */ 26 | uint8 * osal_msg_allocate(uint16 len) 27 | { 28 | osal_msg_hdr_t *hdr; 29 | 30 | if(len == 0) 31 | { 32 | return (NULL); 33 | } 34 | 35 | hdr = (osal_msg_hdr_t *) osal_mem_alloc((short)(len + sizeof(osal_msg_hdr_t))); 36 | if(hdr) 37 | { 38 | hdr->next = NULL; 39 | hdr->len = len; 40 | hdr->dest_id = TASK_NO_TASK; 41 | return ((uint8 *)(hdr + 1)); 42 | } 43 | else 44 | { 45 | return (NULL); 46 | } 47 | } 48 | 49 | /********************************************************************* 50 | * @fn osal_msg_deallocate 51 | * 52 | * @brief 53 | * 54 | * This function is used to deallocate a message buffer. This function 55 | * is called by a task (or processing element) after it has finished 56 | * processing a received message. 57 | * 58 | * 59 | * @param uint8 *msg_ptr - pointer to new message buffer 60 | * 61 | * @return SUCCESS, INVALID_MSG_POINTER 62 | */ 63 | uint8 osal_msg_deallocate(uint8 *msg_ptr) 64 | { 65 | uint8 *x; 66 | 67 | if(msg_ptr == NULL) 68 | { 69 | return (INVALID_MSG_POINTER); 70 | } 71 | 72 | // don't deallocate queued buffer 73 | if(OSAL_MSG_ID(msg_ptr) != TASK_NO_TASK) 74 | { 75 | return (MSG_BUFFER_NOT_AVAIL); 76 | } 77 | 78 | x = (uint8 *)((uint8 *)msg_ptr - sizeof(osal_msg_hdr_t)); 79 | 80 | osal_mem_free((void *)x); 81 | 82 | return (SUCCESS); 83 | } 84 | 85 | /********************************************************************* 86 | * @fn osal_msg_send 87 | * 88 | * @brief 89 | * 90 | * This function is called by a task to send a command message to 91 | * another task or processing element. The sending_task field must 92 | * refer to a valid task, since the task ID will be used 93 | * for the response message. This function will also set a message 94 | * ready event in the destination tasks event list. 95 | * 96 | * 97 | * @param uint8 destination task - Send msg to? Task ID 98 | * @param uint8 *msg_ptr - pointer to new message buffer 99 | * @param uint8 len - length of data in message 100 | * 101 | * @return SUCCESS, INVALID_TASK, INVALID_MSG_POINTER 102 | */ 103 | uint8 osal_msg_send(uint8 destination_task, uint8 *msg_ptr) 104 | { 105 | if(msg_ptr == NULL) 106 | { 107 | return (INVALID_MSG_POINTER); 108 | } 109 | 110 | if(destination_task >= tasksCnt) 111 | { 112 | osal_msg_deallocate(msg_ptr); 113 | return (INVALID_TASK); 114 | } 115 | 116 | // Check the message header 117 | if(OSAL_MSG_NEXT(msg_ptr) != NULL || 118 | OSAL_MSG_ID(msg_ptr) != TASK_NO_TASK) 119 | { 120 | osal_msg_deallocate(msg_ptr); 121 | return (INVALID_MSG_POINTER); 122 | } 123 | 124 | OSAL_MSG_ID(msg_ptr) = destination_task; 125 | 126 | // queue message 127 | osal_msg_enqueue(&osal_qHead, msg_ptr); 128 | 129 | // Signal the task that a message is waiting 130 | osal_set_event(destination_task, SYS_EVENT_MSG); 131 | 132 | return (SUCCESS); 133 | } 134 | 135 | /********************************************************************* 136 | * @fn osal_msg_receive 137 | * 138 | * @brief 139 | * 140 | * This function is called by a task to retrieve a received command 141 | * message. The calling task must deallocate the message buffer after 142 | * processing the message using the osal_msg_deallocate() call. 143 | * 144 | * @param uint8 task_id - receiving tasks ID 145 | * 146 | * @return *uint8 - message information or NULL if no message 147 | */ 148 | uint8 *osal_msg_receive(uint8 task_id) 149 | { 150 | osal_msg_hdr_t *listHdr; 151 | osal_msg_hdr_t *prevHdr = NULL; 152 | osal_msg_hdr_t *foundHdr = NULL; 153 | 154 | 155 | // Hold off interrupts 156 | HAL_ENTER_CRITICAL_SECTION(); 157 | 158 | // Point to the top of the queue 159 | listHdr = osal_qHead; 160 | 161 | // Look through the queue for a message that belongs to the asking task 162 | while(listHdr != NULL) 163 | { 164 | if((listHdr - 1)->dest_id == task_id) 165 | { 166 | if(foundHdr == NULL) 167 | { 168 | // Save the first one 169 | foundHdr = listHdr; 170 | } 171 | else 172 | { 173 | // Second msg found, stop looking 174 | break; 175 | } 176 | } 177 | if(foundHdr == NULL) 178 | { 179 | prevHdr = listHdr; 180 | } 181 | listHdr = OSAL_MSG_NEXT(listHdr); 182 | } 183 | 184 | // Is there more than one? 185 | if(listHdr != NULL) 186 | { 187 | // Yes, Signal the task that a message is waiting 188 | osal_set_event(task_id, SYS_EVENT_MSG); 189 | } 190 | else 191 | { 192 | // No more 193 | osal_clear_event(task_id, SYS_EVENT_MSG); 194 | } 195 | 196 | // Did we find a message? 197 | if(foundHdr != NULL) 198 | { 199 | // Take out of the link list 200 | osal_msg_extract(&osal_qHead, foundHdr, prevHdr); 201 | } 202 | 203 | // Release interrupts 204 | HAL_EXIT_CRITICAL_SECTION(); 205 | 206 | return ((uint8*) foundHdr); 207 | } 208 | 209 | /************************************************************************************************** 210 | * @fn osal_msg_find 211 | * 212 | * @brief This function finds in place an OSAL message matching the task_id and event 213 | * parameters. 214 | * 215 | * input parameters 216 | * 217 | * @param task_id - The OSAL task id that the enqueued OSAL message must match. 218 | * @param event - The OSAL event id that the enqueued OSAL message must match. 219 | * 220 | * output parameters 221 | * 222 | * None. 223 | * 224 | * @return NULL if no match, otherwise an in place pointer to the matching OSAL message. 225 | ************************************************************************************************** 226 | */ 227 | osal_event_hdr_t *osal_msg_find(uint8 task_id, uint8 event) 228 | { 229 | osal_msg_hdr_t *pHdr; 230 | 231 | 232 | HAL_ENTER_CRITICAL_SECTION(); // Hold off interrupts. 233 | 234 | pHdr = osal_qHead; // Point to the top of the queue. 235 | 236 | // Look through the queue for a message that matches the task_id and event parameters. 237 | while(pHdr != NULL) 238 | { 239 | if(((pHdr - 1)->dest_id == task_id) && (((osal_event_hdr_t *)pHdr)->event == event)) 240 | { 241 | break; 242 | } 243 | 244 | pHdr = OSAL_MSG_NEXT(pHdr); 245 | } 246 | 247 | HAL_EXIT_CRITICAL_SECTION(); // Release interrupts. 248 | 249 | return (osal_event_hdr_t *)pHdr; 250 | } 251 | 252 | /********************************************************************* 253 | * @fn osal_msg_enqueue 254 | * 255 | * @brief 256 | * 257 | * This function enqueues an OSAL message into an OSAL queue. 258 | * 259 | * @param osal_msg_q_t *q_ptr - OSAL queue 260 | * @param void *msg_ptr - OSAL message 261 | * 262 | * @return none 263 | */ 264 | void osal_msg_enqueue(osal_msg_q_t *q_ptr, void *msg_ptr) 265 | { 266 | void *list; 267 | 268 | 269 | // Hold off interrupts 270 | HAL_ENTER_CRITICAL_SECTION(); 271 | 272 | OSAL_MSG_NEXT(msg_ptr) = NULL; 273 | // If first message in queue 274 | if(*q_ptr == NULL) 275 | { 276 | *q_ptr = msg_ptr; 277 | } 278 | else 279 | { 280 | // Find end of queue 281 | for(list = *q_ptr; OSAL_MSG_NEXT(list) != NULL; list = OSAL_MSG_NEXT(list)); 282 | 283 | // Add message to end of queue 284 | OSAL_MSG_NEXT(list) = msg_ptr; 285 | } 286 | 287 | // Re-enable interrupts 288 | HAL_EXIT_CRITICAL_SECTION(); 289 | } 290 | 291 | /********************************************************************* 292 | * @fn osal_msg_dequeue 293 | * 294 | * @brief 295 | * 296 | * This function dequeues an OSAL message from an OSAL queue. 297 | * 298 | * @param osal_msg_q_t *q_ptr - OSAL queue 299 | * 300 | * @return void * - pointer to OSAL message or NULL of queue is empty. 301 | */ 302 | void *osal_msg_dequeue(osal_msg_q_t *q_ptr) 303 | { 304 | void *msg_ptr = NULL; 305 | 306 | 307 | // Hold off interrupts 308 | HAL_ENTER_CRITICAL_SECTION(); 309 | 310 | if(*q_ptr != NULL) 311 | { 312 | // Dequeue message 313 | msg_ptr = *q_ptr; 314 | *q_ptr = OSAL_MSG_NEXT(msg_ptr); 315 | OSAL_MSG_NEXT(msg_ptr) = NULL; 316 | OSAL_MSG_ID(msg_ptr) = TASK_NO_TASK; 317 | } 318 | 319 | // Re-enable interrupts 320 | HAL_EXIT_CRITICAL_SECTION(); 321 | 322 | return msg_ptr; 323 | } 324 | 325 | /********************************************************************* 326 | * @fn osal_msg_push 327 | * 328 | * @brief 329 | * 330 | * This function pushes an OSAL message to the head of an OSAL 331 | * queue. 332 | * 333 | * @param osal_msg_q_t *q_ptr - OSAL queue 334 | * @param void *msg_ptr - OSAL message 335 | * 336 | * @return none 337 | */ 338 | void osal_msg_push(osal_msg_q_t *q_ptr, void *msg_ptr) 339 | { 340 | // Hold off interrupts 341 | HAL_ENTER_CRITICAL_SECTION(); 342 | 343 | // Push message to head of queue 344 | OSAL_MSG_NEXT(msg_ptr) = *q_ptr; 345 | *q_ptr = msg_ptr; 346 | 347 | // Re-enable interrupts 348 | HAL_EXIT_CRITICAL_SECTION(); 349 | } 350 | 351 | /********************************************************************* 352 | * @fn osal_msg_extract 353 | * 354 | * @brief 355 | * 356 | * This function extracts and removes an OSAL message from the 357 | * middle of an OSAL queue. 358 | * 359 | * @param osal_msg_q_t *q_ptr - OSAL queue 360 | * @param void *msg_ptr - OSAL message to be extracted 361 | * @param void *prev_ptr - OSAL message before msg_ptr in queue 362 | * 363 | * @return none 364 | */ 365 | void osal_msg_extract(osal_msg_q_t *q_ptr, void *msg_ptr, void *prev_ptr) 366 | { 367 | // Hold off interrupts 368 | HAL_ENTER_CRITICAL_SECTION(); 369 | 370 | if(msg_ptr == *q_ptr) 371 | { 372 | // remove from first 373 | *q_ptr = OSAL_MSG_NEXT(msg_ptr); 374 | } 375 | else 376 | { 377 | // remove from middle 378 | OSAL_MSG_NEXT(prev_ptr) = OSAL_MSG_NEXT(msg_ptr); 379 | } 380 | OSAL_MSG_NEXT(msg_ptr) = NULL; 381 | OSAL_MSG_ID(msg_ptr) = TASK_NO_TASK; 382 | 383 | // Re-enable interrupts 384 | HAL_EXIT_CRITICAL_SECTION(); 385 | } 386 | 387 | /********************************************************************* 388 | * @fn osal_msg_enqueue_max 389 | * 390 | * @brief 391 | * 392 | * This function enqueues an OSAL message into an OSAL queue if 393 | * the length of the queue is less than max. 394 | * 395 | * @param osal_msg_q_t *q_ptr - OSAL queue 396 | * @param void *msg_ptr - OSAL message 397 | * @param uint8 max - maximum length of queue 398 | * 399 | * @return TRUE if message was enqueued, FALSE otherwise 400 | */ 401 | uint8 osal_msg_enqueue_max(osal_msg_q_t *q_ptr, void *msg_ptr, uint8 max) 402 | { 403 | void *list; 404 | uint8 ret = FALSE; 405 | 406 | // Hold off interrupts 407 | HAL_ENTER_CRITICAL_SECTION(); 408 | 409 | // If first message in queue 410 | if(*q_ptr == NULL) 411 | { 412 | *q_ptr = msg_ptr; 413 | ret = TRUE; 414 | } 415 | else 416 | { 417 | // Find end of queue or max 418 | list = *q_ptr; 419 | max--; 420 | while((OSAL_MSG_NEXT(list) != NULL) && (max > 0)) 421 | { 422 | list = OSAL_MSG_NEXT(list); 423 | max--; 424 | } 425 | 426 | // Add message to end of queue if max not reached 427 | if(max != 0) 428 | { 429 | OSAL_MSG_NEXT(list) = msg_ptr; 430 | ret = TRUE; 431 | } 432 | } 433 | 434 | // Re-enable interrupts 435 | HAL_EXIT_CRITICAL_SECTION(); 436 | 437 | return ret; 438 | } 439 | -------------------------------------------------------------------------------- /osal/osal_msg.h: -------------------------------------------------------------------------------- 1 | #ifndef OSAL_MSG_H 2 | #define OSAL_MSG_H 3 | 4 | #include "osal.h" 5 | #include "type.h" 6 | 7 | #define OSAL_MSG_NEXT(msg_ptr) ((osal_msg_hdr_t *) (msg_ptr) - 1)->next 8 | #define OSAL_MSG_ID(msg_ptr) ((osal_msg_hdr_t *) (msg_ptr) - 1)->dest_id 9 | 10 | extern uint8 * osal_msg_allocate(uint16 len); 11 | extern uint8 osal_msg_deallocate(uint8 *msg_ptr); 12 | extern uint8 osal_msg_send(uint8 destination_task, uint8 *msg_ptr); 13 | extern uint8 *osal_msg_receive(uint8 task_id); 14 | extern osal_event_hdr_t *osal_msg_find(uint8 task_id, uint8 event); 15 | extern void osal_msg_enqueue(osal_msg_q_t *q_ptr, void *msg_ptr); 16 | extern uint8 osal_msg_enqueue_max(osal_msg_q_t *q_ptr, void *msg_ptr, uint8 max); 17 | extern void *osal_msg_dequeue(osal_msg_q_t *q_ptr); 18 | extern void osal_msg_push(osal_msg_q_t *q_ptr, void *msg_ptr); 19 | extern void osal_msg_extract(osal_msg_q_t *q_ptr, void *msg_ptr, void *prev_ptr); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /osal/osal_timer.c: -------------------------------------------------------------------------------- 1 | #include "osal_timer.h" 2 | #include "osal_memory.h" 3 | #include "osal_event.h" 4 | #include "type.h" 5 | 6 | typedef struct 7 | { 8 | void *next; 9 | uint16 timeout; //定时时间,每过一个系统时钟会自减 10 | uint16 event_flag; //定时事件,定时时间减完产生任务事件 11 | uint8 task_id; //响应的任务ID 12 | uint16 reloadTimeout; //重装定时时间 13 | } osalTimerRec_t; //任务定时器,链表结构 14 | 15 | /********************************************************************* 16 | * GLOBAL VARIABLES 17 | */ 18 | osalTimerRec_t *timerHead; //任务定时器链表头指针 19 | uint8 tmr_decr_time; //任务定时器更新时自减的数值单位 20 | uint8 timerActive; //标识硬件定时器是否运行 21 | 22 | /********************************************************************* 23 | * LOCAL VARIABLES 24 | */ 25 | static uint32 osal_systemClock; //记录系统时钟 26 | 27 | /********************************************************************* 28 | * LOCAL FUNCTION PROTOTYPES 29 | */ 30 | osalTimerRec_t *osalAddTimer(uint8 task_id, uint16 event_flag, uint16 timeout); 31 | osalTimerRec_t *osalFindTimer(uint8 task_id, uint16 event_flag); 32 | void osalDeleteTimer(osalTimerRec_t *rmTimer); 33 | void osal_timer_activate(uint8 turn_on); 34 | void osal_timer_hw_setup(uint8 turn_on); 35 | 36 | /********************************************************************* 37 | * FUNCTIONS 38 | *********************************************************************/ 39 | 40 | /********************************************************************* 41 | * @fn osalTimerInit 42 | * 43 | * @brief Initialization for the OSAL Timer System. 44 | * 45 | * @param none 46 | * 47 | * @return 48 | */ 49 | void osalTimerInit(void) 50 | { 51 | OSAL_TIMER_TICKINIT(); //初始化硬件定时器 52 | 53 | // Initialize the rollover modulo 54 | tmr_decr_time = TIMER_DECR_TIME; 55 | 56 | // Initialize the system timer 57 | osal_timer_activate(FALSE); 58 | timerActive = FALSE; 59 | 60 | osal_systemClock = 0; 61 | } 62 | 63 | /********************************************************************* 64 | * @fn osalAddTimer 65 | * 66 | * @brief Add a timer to the timer list. 67 | * Ints must be disabled. 68 | * 69 | * @param task_id 70 | * @param event_flag 71 | * @param timeout 72 | * 73 | * @return osalTimerRec_t * - pointer to newly created timer 74 | */ 75 | osalTimerRec_t * osalAddTimer(uint8 task_id, uint16 event_flag, uint16 timeout) 76 | { 77 | osalTimerRec_t *newTimer; 78 | osalTimerRec_t *srchTimer; 79 | 80 | // Look for an existing timer first 81 | newTimer = osalFindTimer(task_id, event_flag); 82 | if(newTimer) 83 | { 84 | // Timer is found - update it. 85 | newTimer->timeout = timeout; 86 | 87 | return (newTimer); 88 | } 89 | else 90 | { 91 | // New Timer 92 | newTimer = osal_mem_alloc(sizeof(osalTimerRec_t)); 93 | 94 | if(newTimer) 95 | { 96 | // Fill in new timer 97 | newTimer->task_id = task_id; 98 | newTimer->event_flag = event_flag; 99 | newTimer->timeout = timeout; 100 | newTimer->next = (void *)NULL; 101 | newTimer->reloadTimeout = 0; 102 | 103 | // Does the timer list already exist 104 | if(timerHead == NULL) 105 | { 106 | // Start task list 107 | timerHead = newTimer; 108 | } 109 | else 110 | { 111 | // Add it to the end of the timer list 112 | srchTimer = timerHead; 113 | 114 | // Stop at the last record 115 | while(srchTimer->next) 116 | srchTimer = srchTimer->next; 117 | 118 | // Add to the list 119 | srchTimer->next = newTimer; 120 | } 121 | return (newTimer); 122 | } 123 | else 124 | return ((osalTimerRec_t *)NULL); 125 | } 126 | } 127 | 128 | /********************************************************************* 129 | * @fn osalFindTimer 130 | * 131 | * @brief Find a timer in a timer list. 132 | * Ints must be disabled. 133 | * 134 | * @param task_id 135 | * @param event_flag 136 | * 137 | * @return osalTimerRec_t * 138 | */ 139 | osalTimerRec_t *osalFindTimer(uint8 task_id, uint16 event_flag) 140 | { 141 | osalTimerRec_t *srchTimer; 142 | 143 | // Head of the timer list 144 | srchTimer = timerHead; 145 | 146 | // Stop when found or at the end 147 | while(srchTimer) 148 | { 149 | if(srchTimer->event_flag == event_flag && 150 | srchTimer->task_id == task_id) 151 | break; 152 | 153 | // Not this one, check another 154 | srchTimer = srchTimer->next; 155 | } 156 | 157 | return (srchTimer); 158 | } 159 | 160 | /********************************************************************* 161 | * @fn osalDeleteTimer 162 | * 163 | * @brief Delete a timer from a timer list. 164 | * 165 | * @param table 166 | * @param rmTimer 167 | * 168 | * @return none 169 | */ 170 | void osalDeleteTimer(osalTimerRec_t *rmTimer) 171 | { 172 | // Does the timer list really exist 173 | if(rmTimer) 174 | { 175 | // Clear the event flag and osalTimerUpdate() will delete 176 | // the timer from the list. 177 | rmTimer->event_flag = 0; 178 | } 179 | } 180 | 181 | /********************************************************************* 182 | * @fn osal_timer_activate 183 | * 184 | * @brief 185 | * 186 | * Turns the hardware timer on or off 187 | * 188 | * @param uint8 turn_on - false - turn off, true - turn on 189 | * 190 | * @return none 191 | */ 192 | void osal_timer_activate(uint8 turn_on) 193 | { 194 | osal_timer_hw_setup(turn_on); 195 | timerActive = turn_on; 196 | } 197 | 198 | /********************************************************************* 199 | * @fn osal_timer_hw_setup 200 | * 201 | * @brief 202 | * 203 | * Setup the timer hardware. 204 | * 205 | * @param uint8 turn_on 206 | * 207 | * @return void 208 | */ 209 | void osal_timer_hw_setup(uint8 turn_on) 210 | { 211 | if(turn_on) 212 | { 213 | OSAL_TIMER_TICKSTART() ; 214 | } 215 | else 216 | { 217 | OSAL_TIMER_TICKSTOP(); 218 | } 219 | } 220 | 221 | /********************************************************************* 222 | * @fn osal_start_timerEx 223 | * 224 | * @brief 225 | * 226 | * This function is called to start a timer to expire in n mSecs. 227 | * When the timer expires, the calling task will get the specified event. 228 | * 229 | * @param uint8 taskID - task id to set timer for 230 | * @param uint16 event_id - event to be notified with 231 | * @param UNINT16 timeout_value - in milliseconds. 232 | * 233 | * @return SUCCESS, or NO_TIMER_AVAIL. 234 | */ 235 | uint8 osal_start_timerEx(uint8 taskID, uint16 event_id, uint16 timeout_value) 236 | { 237 | osalTimerRec_t *newTimer; 238 | 239 | HAL_ENTER_CRITICAL_SECTION(); // Hold off interrupts. 240 | 241 | // Add timer 242 | newTimer = osalAddTimer(taskID, event_id, timeout_value); 243 | 244 | if(newTimer) 245 | { 246 | // Does the hal timer need to be started? 247 | if(timerActive == FALSE) 248 | { 249 | osal_timer_activate(TRUE); 250 | } 251 | } 252 | 253 | HAL_EXIT_CRITICAL_SECTION(); // Re-enable interrupts. 254 | 255 | return ((newTimer != NULL) ? SUCCESS : NO_TIMER_AVAIL); 256 | } 257 | 258 | /********************************************************************* 259 | * @fn osal_start_reload_timer 260 | * 261 | * @brief 262 | * 263 | * This function is called to start a timer to expire in n mSecs. 264 | * When the timer expires, the calling task will get the specified event 265 | * and the timer will be reloaded with the timeout value. 266 | * 267 | * @param uint8 taskID - task id to set timer for 268 | * @param uint16 event_id - event to be notified with 269 | * @param UNINT16 timeout_value - in milliseconds. 270 | * 271 | * @return SUCCESS, or NO_TIMER_AVAIL. 272 | */ 273 | uint8 osal_start_reload_timer(uint8 taskID, uint16 event_id, uint16 timeout_value) 274 | { 275 | osalTimerRec_t *newTimer; 276 | 277 | HAL_ENTER_CRITICAL_SECTION(); // Hold off interrupts. 278 | 279 | // Add timer 280 | newTimer = osalAddTimer(taskID, event_id, timeout_value); 281 | if(newTimer) 282 | { 283 | // Load the reload timeout value 284 | newTimer->reloadTimeout = timeout_value; 285 | } 286 | 287 | if(newTimer) 288 | { 289 | // Does the hal timer need to be started? 290 | if(timerActive == FALSE) 291 | { 292 | osal_timer_activate(TRUE); 293 | } 294 | } 295 | 296 | HAL_EXIT_CRITICAL_SECTION(); // Re-enable interrupts. 297 | 298 | return ((newTimer != NULL) ? SUCCESS : NO_TIMER_AVAIL); 299 | } 300 | 301 | /********************************************************************* 302 | * @fn osal_stop_timerEx 303 | * 304 | * @brief 305 | * 306 | * This function is called to stop a timer that has already been started. 307 | * If ZSUCCESS, the function will cancel the timer and prevent the event 308 | * associated with the timer from being set for the calling task. 309 | * 310 | * @param uint8 task_id - task id of timer to stop 311 | * @param uint16 event_id - identifier of the timer that is to be stopped 312 | * 313 | * @return SUCCESS or INVALID_EVENT_ID 314 | */ 315 | uint8 osal_stop_timerEx(uint8 task_id, uint16 event_id) 316 | { 317 | osalTimerRec_t *foundTimer; 318 | 319 | HAL_ENTER_CRITICAL_SECTION(); // Hold off interrupts. 320 | 321 | // Find the timer to stop 322 | foundTimer = osalFindTimer(task_id, event_id); 323 | if(foundTimer) 324 | { 325 | osalDeleteTimer(foundTimer); 326 | } 327 | 328 | HAL_EXIT_CRITICAL_SECTION(); // Re-enable interrupts. 329 | 330 | return ((foundTimer != NULL) ? SUCCESS : INVALID_EVENT_ID); 331 | } 332 | 333 | /********************************************************************* 334 | * @fn osal_get_timeoutEx 335 | * 336 | * @brief 337 | * 338 | * @param uint8 task_id - task id of timer to check 339 | * @param uint16 event_id - identifier of timer to be checked 340 | * 341 | * @return Return the timer's tick count if found, zero otherwise. 342 | */ 343 | uint16 osal_get_timeoutEx(uint8 task_id, uint16 event_id) 344 | { 345 | uint16 rtrn = 0; 346 | osalTimerRec_t *tmr; 347 | 348 | HAL_ENTER_CRITICAL_SECTION(); // Hold off interrupts. 349 | 350 | tmr = osalFindTimer(task_id, event_id); 351 | 352 | if(tmr) 353 | { 354 | rtrn = tmr->timeout; 355 | } 356 | 357 | HAL_EXIT_CRITICAL_SECTION(); // Re-enable interrupts. 358 | 359 | return rtrn; 360 | } 361 | 362 | /********************************************************************* 363 | * @fn osal_timer_num_active 364 | * 365 | * @brief 366 | * 367 | * This function counts the number of active timers. 368 | * 369 | * @return uint8 - number of timers 370 | */ 371 | uint8 osal_timer_num_active(void) 372 | { 373 | uint8 num_timers = 0; 374 | osalTimerRec_t *srchTimer; 375 | 376 | HAL_ENTER_CRITICAL_SECTION(); // Hold off interrupts. 377 | 378 | // Head of the timer list 379 | srchTimer = timerHead; 380 | 381 | // Count timers in the list 382 | while(srchTimer != NULL) 383 | { 384 | num_timers++; 385 | srchTimer = srchTimer->next; 386 | } 387 | 388 | HAL_EXIT_CRITICAL_SECTION(); // Re-enable interrupts. 389 | 390 | return num_timers; 391 | } 392 | 393 | /********************************************************************* 394 | * @fn osalTimerUpdate 395 | * 396 | * @brief Update the timer structures for a timer tick. 397 | * 398 | * @param none 399 | * 400 | * @return none 401 | *********************************************************************/ 402 | void osalTimerUpdate(uint16 updateTime) 403 | { 404 | osalTimerRec_t *srchTimer; 405 | osalTimerRec_t *prevTimer; 406 | 407 | HAL_ENTER_CRITICAL_SECTION(); // Hold off interrupts. 408 | // Update the system time 409 | osal_systemClock += updateTime; 410 | HAL_EXIT_CRITICAL_SECTION(); // Re-enable interrupts. 411 | 412 | // Look for open timer slot 413 | if(timerHead != NULL) 414 | { 415 | // Add it to the end of the timer list 416 | srchTimer = timerHead; 417 | prevTimer = (void *)NULL; 418 | 419 | // Look for open timer slot 420 | while(srchTimer) 421 | { 422 | osalTimerRec_t *freeTimer = NULL; 423 | 424 | HAL_ENTER_CRITICAL_SECTION(); // Hold off interrupts. 425 | 426 | if(srchTimer->timeout <= updateTime) 427 | { 428 | srchTimer->timeout = 0; 429 | } 430 | else 431 | { 432 | srchTimer->timeout = srchTimer->timeout - updateTime; 433 | } 434 | 435 | // Check for reloading 436 | if((srchTimer->timeout == 0) && (srchTimer->reloadTimeout) && (srchTimer->event_flag)) 437 | { 438 | // Notify the task of a timeout 439 | osal_set_event(srchTimer->task_id, srchTimer->event_flag); 440 | 441 | // Reload the timer timeout value 442 | srchTimer->timeout = srchTimer->reloadTimeout; 443 | } 444 | 445 | // When timeout or delete (event_flag == 0) 446 | if(srchTimer->timeout == 0 || srchTimer->event_flag == 0) 447 | { 448 | // Take out of list 449 | if(prevTimer == NULL) 450 | timerHead = srchTimer->next; 451 | else 452 | prevTimer->next = srchTimer->next; 453 | 454 | // Setup to free memory 455 | freeTimer = srchTimer; 456 | 457 | // Next 458 | srchTimer = srchTimer->next; 459 | } 460 | else 461 | { 462 | // Get next 463 | prevTimer = srchTimer; 464 | srchTimer = srchTimer->next; 465 | } 466 | 467 | HAL_EXIT_CRITICAL_SECTION(); // Re-enable interrupts. 468 | 469 | if(freeTimer) 470 | { 471 | if(freeTimer->timeout == 0) 472 | { 473 | osal_set_event(freeTimer->task_id, freeTimer->event_flag); 474 | } 475 | osal_mem_free(freeTimer); 476 | } 477 | } 478 | } 479 | } 480 | 481 | /********************************************************************* 482 | * @fn osal_GetSystemClock() 483 | * 484 | * @brief Read the local system clock. 485 | * 486 | * @param none 487 | * 488 | * @return local clock in milliseconds 489 | */ 490 | uint32 osal_GetSystemClock(void) 491 | { 492 | return (osal_systemClock); 493 | } 494 | 495 | /********************************************************************* 496 | * @fn osal_update_timers 497 | * 498 | * @brief Update the timer structures for timer ticks. 499 | * 500 | * @param none 501 | * 502 | * @return none 503 | */ 504 | //在每次系统定时溢出时调用一次,更新计时器 505 | void osal_update_timers(void) 506 | { 507 | osalTimerUpdate(tmr_decr_time); 508 | } 509 | -------------------------------------------------------------------------------- /osal/osal_timer.h: -------------------------------------------------------------------------------- 1 | #ifndef OSAL_TIMER_H 2 | #define OSAL_TIMER_H 3 | 4 | #include "type.h" 5 | #include "timer.h" 6 | 7 | #define TIMER_DECR_TIME 1 //任务定时器更新时自减的数值单位 8 | 9 | extern void osalTimerInit(void); 10 | extern uint8 osal_start_timerEx(uint8 task_id, uint16 event_id, uint16 timeout_value); 11 | extern uint8 osal_start_reload_timer(uint8 taskID, uint16 event_id, uint16 timeout_value); 12 | extern uint8 osal_stop_timerEx(uint8 task_id, uint16 event_id); 13 | extern uint16 osal_get_timeoutEx(uint8 task_id, uint16 event_id); 14 | extern uint8 osal_timer_num_active(void); 15 | extern uint32 osal_GetSystemClock(void); 16 | extern void osal_update_timers(void); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /osal/type.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPE_H 2 | #define TYPE_H 3 | 4 | #define ZSUCCESS 1 5 | #define INVALID_TASK 2 6 | #define INVALID_MSG_POINTER 3 7 | #define INVALID_EVENT_ID 4 8 | #define NO_TIMER_AVAIL 5 9 | #define TASK_NO_TASK 6 10 | #define MSG_BUFFER_NOT_AVAIL 7 11 | 12 | typedef unsigned char BOOL; 13 | 14 | //芯片硬件字长 15 | typedef unsigned int halDataAlign_t; 16 | 17 | // Unsigned numbers 18 | typedef unsigned char uint8; 19 | typedef unsigned char byte; 20 | typedef unsigned short uint16; 21 | typedef unsigned short int16U; 22 | typedef unsigned int uint32; 23 | typedef unsigned int int32U; 24 | 25 | // Signed numbers 26 | typedef signed char int8; 27 | typedef signed short int16; 28 | typedef signed int int32; 29 | 30 | #ifndef FALSE 31 | #define FALSE 0 32 | #endif 33 | 34 | #ifndef ARRAY_NULL 35 | #define ARRAY_NULL '\0' 36 | #endif 37 | 38 | #ifndef TRUE 39 | #define TRUE 1 40 | #endif 41 | 42 | #ifndef OPEN 43 | #define OPEN 1 44 | #endif 45 | 46 | #ifndef CLOSE 47 | #define CLOSE 0 48 | #endif 49 | 50 | #ifndef NULL 51 | #define NULL ((void*) 0 ) 52 | #endif 53 | 54 | #ifndef HIGH 55 | #define HIGH 1 56 | #endif 57 | 58 | #ifndef LOW 59 | #define LOW 0 60 | #endif 61 | 62 | #ifndef SUCCESS 63 | #define SUCCESS 1 64 | #endif 65 | 66 | #ifndef ERROR 67 | #define ERROR 0 68 | #endif 69 | 70 | //#define CLI() __set_PRIMASK(1) // Disable Interrupts 71 | //#define SEI() __set_PRIMASK(0) // Enable Interrupts 72 | #define CLI() ; // Disable Interrupts 73 | #define SEI() ; // Enable Interrupts 74 | 75 | #define HAL_ENABLE_INTERRUPTS() SEI() // Enable Interrupts 76 | #define HAL_DISABLE_INTERRUPTS() CLI() // Disable Interrupts 77 | #define HAL_INTERRUPTS_ARE_ENABLED() SEI() // Enable Interrupts 78 | 79 | #define HAL_ENTER_CRITICAL_SECTION() CLI() 80 | #define HAL_EXIT_CRITICAL_SECTION() SEI() 81 | 82 | #endif 83 | --------------------------------------------------------------------------------