关注、星标公众,不错过精彩内容

转自:Mculover666

之前给大家分享过关于CMSIS的内容,比如:

Cortex-M微控制器软件接口标准CMSIS详细内容

CMSIS-DAP和J-Link、ST-Link是什么关系?

今天继续给大家分享由“Mculover666”整理的关于CMSIS的内容。

1. CMSIS-RTOS API

CMSIS-RTOS API是ARM公司为RTOS内核制定的一套通用接口协议,它提供了一套「标准的API接口」,可以移植到各种各样的RTOS上,使得上层的软件、中间件、库以及其他组件在不同的RTOS之上都可以正常工作。

这套API表现为两个文件:cmsis-os.h和cmsis-os.c,也就是说,不同的RTOS内核分别用自己的一套东西去适配.c文件中的接口,而用户只需要调用.h文件中给出的API编写应用。

本文会列举性的给出CMSIS-RTOS有哪些API和宏定义,并给出每类API的使用demo,学习者只需要了解这些东西,能看懂用CMSIS-RTOS API编写的应用程序即可~

在TencentOS-tiny中如下。

  • 基于TencentOS-tiny的CMSIS-RTOS API v1.02版本实现:

    • cmsis_os.h

    • cmsis_os.c

  • 基于TencentOS-tiny的CMSIS-RTOS API v2.1.3版本实现:

    • cmsis_os2.h

    • cmsis_os2.c

CMSIS-RTOS API的整体架构如下图:

2. CMSIS-RTOS API列表

下面列出了 CMSIS-RTOS API v1.02 版本提供的所有API。

CMSIS-RTOS 所有API使用的错误码(cmsis-os.h):

typedef enum {osOK                    =     0,       ///< function completed; no error or event occurred.osEventSignal           =  0x08,       ///< function completed; signal event occurred.osEventMessage          =  0x10,       ///< function completed; message event occurred.osEventMail             =  0x20,       ///< function completed; mail event occurred.osEventTimeout          =  0x40,       ///< function completed; timeout occurred.osErrorParameter        =  0x80,       ///< parameter error: a mandatory parameter was missing or specified an incorrect object.osErrorResource         =  0x81,       ///< resource not available: a specified resource was not available.osErrorTimeoutResource  =  0xC1,       ///< resource not available within given time: a specified resource was not available within the timeout period.osErrorISR              =  0x82,       ///< not allowed in ISR context: the function cannot be called from interrupt service routines.osErrorISRRecursive     =  0x83,       ///< function called multiple times from ISR with same object.osErrorPriority         =  0x84,       ///< system cannot determine priority or thread has illegal priority.osErrorNoMemory         =  0x85,       ///< system is out of memory: it was impossible to allocate or reserve memory for the operation.osErrorValue            =  0x86,       ///< value of a parameter is out of range.osErrorOS               =  0xFF,       ///< unspecified RTOS error: run-time error but no other error message fits.os_status_reserved      =  0x7FFFFFFF  ///< prevent from enum down-size compiler optimization.
} osStatus;

CMSIS-RTOS API一些可选项控制是否开启(cmsis-os.h):

#define osFeature_MainThread   1       ///< main thread      1=main can be thread, 0=not available
#define osFeature_Pool         1       ///< Memory Pools:    1=available, 0=not available
#define osFeature_MailQ        1       ///< Mail Queues:     1=available, 0=not available
#define osFeature_MessageQ     1       ///< Message Queues:  1=available, 0=not available
#define osFeature_Signals      0       ///< maximum number of Signal Flags available per thread
#define osFeature_Semaphore    30       ///< maximum count for \ref osSemaphoreCreate function
#define osFeature_Wait         0       ///< osWait function: 1=available, 0=not available
#define osFeature_SysTick      1       ///< osKernelSysTick functions: 1=available, 0=not available

2.1. 内核信息和控制

API 描述
osKernelInitialize 初始化RTOS内核
osKernelStart 启动RTOS内核
osKernelRunning Query if the RTOS kernel is running
osKernelSysTick (可选) Get RTOS kernel system timer counter
osKernelSysTickFrequency (可选) RTOS kernel system timer frequency in Hz
osKernelSysTickMicroSec (可选) Convert microseconds value to RTOS kernel system timer value
  • osKernelInitialize

osStatus osKernelInitialize(void);

返回值:status code

  • osKernelStart

osStatus osKernelStart(void);

返回值:status code

  • osKernelRunning

int32_t osKernelRunning(void);

返回值:0表示RTOS未启动,1表示RTOS已经启动

  • osKernelSysTick

uint32_t osKernelSysTick(void);

返回值:RTOS内核系统当前的时间

2.2. 线程管理

##连接符的作用是连接两个字符串,合为一个字符串。

CMSIS-RTOS API 存放线程参数管理的结构体如下:

typedef struct os_thread_def {char           *name;       ///< Thread nameos_pthread      pthread;    ///< start address of thread functionosPriority      tpriority;  ///< initial thread priorityuint32_t        instances;  ///< maximum number of instances of that thread functionk_stack_t      *stackbase;  ///< base address of taskuint32_t        stacksize;  ///< stack size requirements in bytes; 0 is default stack sizek_timeslice_t   timeslice;  ///< timeslicek_task_t       *task;
} osThreadDef_t;

CMSIS-RTOS API 定义线程的宏如下:

#define osThreadDef(name, priority, instances, stacksz)  \k_task_t task_handler_##name; \k_stack_t task_stack_##name[(stacksz)]; \const osThreadDef_t os_thread_def_##name = \{ #name, (os_pthread)(name), (osPriority)(priority), (instances), \(&((task_stack_##name)[0])), (stacksz), ((k_timeslice_t)0u), (&(task_handler_##name)) }

宏定义中的 instances 表示基于此任务参数,创建出几个任务实例,比如instances为2,则会创建出两个任务。

CMSIS-RTOS API定义的获取线程参数结构体的宏如下:

#define osThread(name)  \&os_thread_def_##name

管理线程参数的API如下:

API 描述
osThreadCreate 创建线程并开始执行
osThreadTerminate 停止线程执行
osThreadYield 线程主动让出
osThreadGetID 获取当前正在运行线程的ID
osThreadSetPriority 改变线程优先级
osThreadGetPriority 获取线程优先级
  • osThreadCreate

osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument);

其中osThreadId被定义为k_task_t指针类型:

typedef k_task_t *osThreadId;

返回值:TencentOS-tiny中的任务控制块类型指针。

  • osThreadTerminate

osStatus osThreadTerminate(osThreadId thread_id);

返回值:osStatus

  • osThreadYield

osStatus osThreadYield(void);

返回值:osStatus

  • osThreadGetID

osThreadId osThreadGetId(void);
  • osThreadSetPriority

osStatus osThreadSetPriority(osThreadId thread_id, osPriority priority);
  • osThreadGetPriority

osPriority osThreadGetPriority(osThreadId thread_id);

使用时需要特别注意,在TencentOS-tiny中,调用CMSIS-RTOS API提供的优先级选项设置之后,实际设置的任务值是不同的。

CMSIS-RTOS API提供的线程优先级宏定义如下:

typedef enum {osPriorityIdle          = -3,          ///< priority: idle (lowest)osPriorityLow           = -2,          ///< priority: lowosPriorityBelowNormal   = -1,          ///< priority: below normalosPriorityNormal        =  0,          ///< priority: normal (default)osPriorityAboveNormal   = +1,          ///< priority: above normalosPriorityHigh          = +2,          ///< priority: highosPriorityRealtime      = +3,          ///< priority: realtime (highest)osPriorityError         =  0x84        ///< system cannot determine priority or thread has illegal priority
} osPriority;

在TecentOS-tiny中实现的时候进行了转化:

static k_prio_t priority_cmsis2knl(osPriority prio)
{if (prio == osPriorityError) {return K_TASK_PRIO_INVALID;}return (k_prio_t)(3 - prio);
}static osPriority priority_knl2cmsis(k_prio_t prio)
{return (osPriority)(3 - prio);
}

比如创建线程时设置为 osPriorityNormal=0,则「实际设置的任务优先级为3」

2.3. 通用等待函数

CMSIS-RTOS提供的等待函数API如下:

API 描述
osDelay 等待指定的时间
osWait(可选) 等待信号、消息、邮箱的某个事件
  • osDelay

osStatus osDelay(uint32_t millisec);

返回值:osStatus。

2.4. 软件定时器管理

CMSIS-RTOS API提供的存储定时器参数的结构体如下:

typedef struct os_timer_def {os_ptimer                 cb;   ///< start address of a timer functionk_timer_t                *timer;
} osTimerDef_t;

CMSIS-RTOS API提供的定义一个软件定时器的宏定义如下:

#define osTimerDef(name, function)  \k_timer_t timer_handler_##name; \const osTimerDef_t os_timer_def_##name = \{ (os_ptimer)(function), (&(timer_handler_##name)) }

CMSIS-RTOS API定义的获取软件定时器参数结构体的宏如下:

#define osTimer(name) \&os_timer_def_##name

CMSIS-RTOS API提供的软件定时器管理API如下:

API 描述
osTimerCreate 创建一个软件定时器
osTimerStart 启动软件定时器
osTimerStop 停止软件定时器
osTimerDelete 删除软件定时器
  • osTimerCreate

osTimerId osTimerCreate(const osTimerDef_t *timer_def, os_timer_type type, void *argument);

其中osTimerId被定义为k_timer_t指针类型:

typedef k_timer_t *osTimerId;

type参数为 os_timer_type 类型,表示软件定时器的类型为单次触发或者周期触发:

typedef enum  {osTimerOnce             =     0,       ///< one-shot timerosTimerPeriodic         =     1        ///< repeating timer
} os_timer_type;
  • osTimerStart

osStatus osTimerStart(osTimerId timer_id, uint32_t millisec);

返回值:osStatus。

  • osTimerStop

osStatus osTimerStop(osTimerId timer_id)

返回值:osStatus。

  • osTimerDelete

osStatus osTimerDelete(osTimerId timer_id);

返回值:osStatus。

2.5. 信号量管理

CMSIS-RTOS API提供的存储信号量参数的结构体如下:

typedef struct os_semaphore_def {uint32_t                    dummy;  ///< dummy value.k_sem_t                    *sem;
} osSemaphoreDef_t;

CMSIS-RTOS API提供的定义一个信号量的宏定义如下:

#define osSemaphoreDef(name)  \k_sem_t sem_handler_##name; \const osSemaphoreDef_t os_semaphore_def_##name = { 0, (&(sem_handler_##name)) }

CMSIS-RTOS API定义的获取信号量参数结构体的宏如下:

#define osSemaphore(name)  \&os_semaphore_def_##name

CMSIS-RTOS API提供的信号量管理API如下:

API 描述
osSemaphoreCreate 创建一个信号量
osSemaphoreWait 等待信号量
osSemaphoreRelease 释放信号量
osSemaphoreDelete 删除信号量
  • osSemaphoreCreate

osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, int32_t count);

其中 osSemaphoreId 被定义为k_sem_t指针类型:

typedef k_sem_t *osSemaphoreId;
  • osSemaphoreWait

int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec);

返回值:int32_t ,正常返回当前count数,失败返回-1。

如果需要阻塞延时,参数应该设置为CMSIS-RTOS API提供的宏定义 osWaitForever :

#define osWaitForever     0xFFFFFFFF     ///< wait forever timeout value
  • osSemaphoreRelease

osStatus osSemaphoreRelease(osSemaphoreId semaphore_id);

返回值:osStatus。

  • osSemaphoreDelete

osStatus osSemaphoreDelete(osSemaphoreId semaphore_id);

返回值:osStatus。

2.6. 互斥锁管理

CMSIS-RTOS API提供的存储互斥锁参数的结构体如下:

typedef struct os_mutex_def {uint32_t                    dummy;  ///< dummy value.k_mutex_t                  *mutex;
} osMutexDef_t;

CMSIS-RTOS API提供的定义一个互斥锁的宏定义如下:

#define osMutexDef(name)  \k_mutex_t mutex_handler_##name; \const osMutexDef_t os_mutex_def_##name = { 0, (&(mutex_handler_##name)) }

CMSIS-RTOS API定义的获取互斥锁参数结构体的宏如下:

#define osMutex(name)  \&os_mutex_def_##name

CMSIS-RTOS API提供的互斥锁管理API如下:

API 描述
osMutexCreate 创建一个互斥锁
osMutexWait 等待获取互斥锁
osMutexRelease 释放互斥锁
osMutexDelete 删除互斥锁
  • osMutexCreate

osMutexId osMutexCreate(const osMutexDef_t *mutex_def);

其中 osMutexId 被定义为k_mutex_t指针类型:

typedef k_mutex_t *osMutexId;
  • osMutexWait

osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec);

返回值:osStatus 。

如果需要阻塞延时,参数应该设置为CMSIS-RTOS API提供的宏定义 osWaitForever :

#define osWaitForever     0xFFFFFFFF     ///< wait forever timeout value
  • osMutexRelease

osStatus osMutexRelease(osMutexId mutex_id);

返回值:osStatus。

  • osMutexDelete

osStatus osMutexDelete(osMutexId mutex_id);

返回值:osStatus。

2.7. 静态内存池管理

CMSIS-RTOS API提供的存储静态内存池参数的结构体如下:

typedef struct os_pool_def {uint32_t                    pool_sz;    ///< number of items (elements) in the pooluint32_t                    item_sz;    ///< size of an itemvoid                       *pool;       ///< pointer to memory for poolk_mmblk_pool_t             *mmblk_pool; ///< memory blk pool handler
} osPoolDef_t;

CMSIS-RTOS API提供的定义一个互斥锁的宏定义如下:

#define osPoolDef(name, no, type)   \k_mmblk_pool_t mmblk_pool_handler_##name; \uint8_t mmblk_pool_buf_##name[(no) * sizeof(type)]; \const osPoolDef_t os_pool_def_##name = \{ (no), sizeof(type), (&((mmblk_pool_buf_##name)[0])), (&(mmblk_pool_handler_##name)) }

CMSIS-RTOS API定义的获取互斥锁参数结构体的宏如下:

#define osPool(name) \&os_pool_def_##name

CMSIS-RTOS API提供的互斥锁管理API如下:

API 描述
osPoolCreate 创建一块固定大小的静态内存池
osPoolAlloc 申请分配内存
osPoolCAlloc 申请分配一块内存并全部初始化为0
osPoolFree 申请回收内存
  • osPoolCreate

osPoolId osPoolCreate(const osPoolDef_t *pool_def);

其中 osPoolId 被定义为 k_mmblk_pool_t 指针类型:

typedef k_mmblk_pool_t *osPoolId;
  • osPoolAlloc

void *osPoolAlloc(osPoolId pool_id);
  • osPoolCAlloc

void *osPoolCAlloc(osPoolId pool_id);
  • osPoolFree

osStatus osPoolFree(osPoolId pool_id, void *block);

返回值:osStatus。

2.8. 消息队列管理

CMSIS-RTOS API提供的存储消息队列参数的结构体如下:

typedef struct os_messageQ_def {uint32_t                    queue_sz;   ///< number of elements in the queueuint32_t                    item_sz;    ///< size of an itemvoid                       *pool;       ///< memory array for messagesk_msg_q_t                  *queue;      ///< queue handler
} osMessageQDef_t;

CMSIS-RTOS API提供的定义一个消息队列的宏定义如下:

#define osMessageQDef(name, queue_sz, type)   \k_msg_q_t msg_q_handler_##name; \const osMessageQDef_t os_messageQ_def_##name = \{ (queue_sz), sizeof(type), NULL, (&(msg_q_handler_##name)) }

CMSIS-RTOS API定义的获取消息队列参数结构体的宏如下:

#define osMessageQ(name) \&os_messageQ_def_##name

CMSIS-RTOS API提供的消息队列管理API如下:

API 描述
osMessageCreate 初始化一个消息队列
osMessagePut 向消息队列中加入数据
osMessageGet 从消息队列中取出数据
  • osMessageCreate

osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, osThreadId thread_id);

其中 osMessageQId 被定义为 k_msg_q_t 指针类型:

typedef k_msg_q_t *osMessageQId;
  • osMessagePut

osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec);

返回值:osStatus 。

因为TencentOS-tiny中消息队列实现机制的不同,此API中的 millisec 参数未用到。

  • osMessageGet

osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec);

返回值:osEvent ,其中包含了事件信息和错误码,以及消息队列收到的值。

如果需要阻塞延时,参数应该设置为CMSIS-RTOS API提供的宏定义 osWaitForever :

#define osWaitForever     0xFFFFFFFF     ///< wait forever timeout value

3. 使用示例

3.1. 任务创建示例

#include <cmsis_os.h>void task1_entry(void *arg)
{while(1){printf("task1 is running...\r\n");osDelay(1000);}
}
osThreadDef(task1_entry, osPriorityNormal, 1, 512);void task2_entry(void *arg)
{while(1){printf("task2 is running...\r\n");osDelay(1000);}
}
osThreadDef(task2_entry, osPriorityNormal, 1, 512);void application_entry(void *arg)
{osThreadCreate(osThread(task1_entry), NULL);osThreadCreate(osThread(task2_entry), NULL);return;
}

任务运行结果如下:

task1 is running...
task2 is running...
task1 is running...
task2 is running...
task1 is running...
task2 is running...

3.2. 软件定时器使用示例

#include <cmsis_os.h>void timer1_cb(void *arg)
{printf("timer1 is timeout!\r\n");
}void timer2_cb(void *arg)
{printf("timer2 is timeout!\r\n");
}osTimerDef(timer1, timer1_cb);
osTimerDef(timer2, timer2_cb);void application_entry(void *arg)
{osTimerId timer1;osTimerId timer2;timer1 = osTimerCreate(osTimer(timer1), osTimerOnce, NULL);timer2 = osTimerCreate(osTimer(timer2), osTimerPeriodic, NULL);osTimerStart(timer1, 5000);osTimerStart(timer2, 1000);return;
}

运行结果如下:

timer2 is timeout!
timer2 is timeout!
timer2 is timeout!
timer2 is timeout!
timer1 is timeout!
timer2 is timeout!
timer2 is timeout!
timer2 is timeout!
timer2 is timeout!

3.3. 信号量使用示例

#include <cmsis_os.h>osSemaphoreId sync_sem_id;
osSemaphoreDef(sync_sem);void task1_entry(void *arg)
{while(1){printf("task1 is waiting sem forever...\r\n");osSemaphoreWait(sync_sem_id, osWaitForever);printf("task1 get sem!\r\n");}
}
osThreadDef(task1_entry, osPriorityNormal, 1, 512);void task2_entry(void *arg)
{while(1){printf("task2 will release a sem...\r\n");osSemaphoreRelease(sync_sem_id);osDelay(1000);}
}
osThreadDef(task2_entry, osPriorityNormal, 1, 512);void application_entry(void *arg)
{sync_sem_id = osSemaphoreCreate(osSemaphore(sync_sem), 0);osThreadCreate(osThread(task1_entry), NULL);osThreadCreate(osThread(task2_entry), NULL);return;
}

运行结果为:

task1 is waiting sem forever...
task1 get sem!
task1 is waiting sem forever...
task2 will release a sem...
task1 get sem!
task1 is waiting sem forever...
task2 will release a sem...
task1 get sem!
task1 is waiting sem forever...
task2 will release a sem...
task1 get sem!
task1 is waiting sem forever...
task2 will release a sem...
task1 get sem!
task1 is waiting sem forever...

3.4. 互斥锁使用示例

#include <cmsis_os.h>osMutexId sync_mutex_id;
osMutexDef(sync_mutex);void task1_entry(void *arg)
{while(1){osMutexWait(sync_mutex_id, osWaitForever);printf("task1 get mutex,doing sth...\r\n");HAL_Delay(1000);    //死循环占用CPUprintf("task1 finish do sth!\r\n");osMutexRelease(sync_mutex_id);osDelay(1000);}
}
osThreadDef(task1_entry, osPriorityHigh, 1, 512);void task2_entry(void *arg)
{while(1){osMutexWait(sync_mutex_id, osWaitForever);printf("task2 get mutex,doing sth...\r\n");HAL_Delay(2000);    //死循环占用CPUprintf("task2 finish do sth!\r\n");osMutexRelease(sync_mutex_id);osDelay(1000);}
}
osThreadDef(task2_entry, osPriorityNormal, 1, 512);void application_entry(void *arg)
{sync_mutex_id = osMutexCreate(osMutex(sync_mutex));osThreadCreate(osThread(task1_entry), NULL);osThreadCreate(osThread(task2_entry), NULL);return;
}

运行结果为:

task1 get mutex,doing sth...
task1 finish do sth!
task2 get mutex,doing sth...
task2 finish do sth!
task1 get mutex,doing sth...
task1 finish do sth!
task1 get mutex,doing sth...
task1 finish do sth!
task2 get mutex,doing sth...

3.5. 动态内存使用示例

#include <cmsis_os.h>typedef struct blk_st {int   id;char* payload;
} blk_t;#define MMBLK_BLK_NUM 10osPoolDef (MemPool, MMBLK_BLK_NUM, blk_t);
osPoolId mem_pool_id;void task1_entry(void *arg)
{   blk_t *ptr = NULL;osStatus err;/* 打印出一个块的大小 */printf("block size is %d bytes\r\n", sizeof(blk_t));/* 申请一个块 */ptr = osPoolAlloc(mem_pool_id);if (ptr == NULL) {printf("a mmblk alloc fail\r\n");return;}else {printf("a mmblk alloc success\r\n");}/* 使用该块 */ptr->id = 1;ptr->payload = "hello";printf("mmblk id:%d payload:%s\r\n", ptr->id, ptr->payload);/* 使用完毕之后释放 */err = osPoolFree(mem_pool_id, ptr);if (err != osOK) {printf("a mmblk free fail, err = %d\r\n", err);return;}else {printf("a mmblk free success\r\n");}while (1) {tos_task_delay(1000);}
}#define STK_SIZE_TASK1      1024
osThreadDef(task1_entry, osPriorityNormal, 1, STK_SIZE_TASK1);void application_entry(void *arg)
{//初始化静态内存池mem_pool_id = osPoolCreate(osPool(MemPool));if (mem_pool_id == NULL) {printf("mmblk pool create fail\r\n");return;}else {printf("mmblk pool create success\r\n");}//创建任务osThreadCreate(osThread(task1_entry), NULL);return;
}

运行结果为:

mmblk pool create success
block size is 8 bytes
a mmblk alloc success
mmblk id:1 payload:hello
a mmblk free success

3.6. 消息队列使用示例

#include <cmsis_os.h>#define STK_SIZE_TASK_RECEIVER      512
#define STK_SIZE_TASK_SENDER        512#define MESSAGE_MAX     10osMessageQId msg_q_id;
osMessageQDef(msg_q,MESSAGE_MAX,uint32_t);void task_receiver_entry(void *arg)
{osEvent event;osStatus ret;uint32_t value;while (1){event = osMessageGet(msg_q_id, osWaitForever);ret = event.status;if (ret == osOK){value = event.value.v;printf("receiver: msg incoming[%s]\r\n", (char*)value);}}
}
osThreadDef(task_receiver_entry, osPriorityNormal, 1, STK_SIZE_TASK_RECEIVER);void task_sender_entry(void *arg)
{char *msg_prio_0 = "msg 0";char *msg_prio_1 = "msg 1";char *msg_prio_2 = "msg 2";printf("sender: post a messgae:[%s]\r\n", msg_prio_2);osMessagePut(msg_q_id,(uint32_t)msg_prio_2,0);printf("sender: post a messgae:[%s]\r\n", msg_prio_1);osMessagePut(msg_q_id,(uint32_t)msg_prio_1,0);printf("sender: post a messgae:[%s]\r\n", msg_prio_0);osMessagePut(msg_q_id,(uint32_t)msg_prio_0,0);}
osThreadDef(task_sender_entry, osPriorityNormal, 1, STK_SIZE_TASK_SENDER);void application_entry(void *arg)
{msg_q_id = osMessageCreate(osMessageQ(msg_q),NULL);osThreadCreate(osThread(task_receiver_entry), NULL);osThreadCreate(osThread(task_sender_entry), NULL);return;
}

运行结果为:

sender: post a messgae:[msg 2]
sender: post a messgae:[msg 1]
sender: post a messgae:[msg 0]
receiver: msg incoming[msg 2]
receiver: msg incoming[msg 1]
receiver: msg incoming[msg 0]

推荐阅读:

文本或代码中 \n 和 \r 的区别

几个类似 VS Code的开源编辑器工具

STM32中CRC计算单元,及CRC校验的应用

关注微信公众号『strongerHuang』,后台回复“1024”查看更多内容,回复“加群”按规则加入技术交流群。

长按前往图中包含的公众号关注

CMSIS RTOS API,内核通用API接口相关推荐

  1. 新浪微博商业数据API、通用API

    新浪微博商业数据API.通用API,整理好备用. /*** <p>* Title WeiboBusinessDataApiConstants* </p>* <p>* ...

  2. RTOS内功修炼记(八)——CMSIS RTOS API,内核通用API接口

    1. CMSIS-RTOS API CMSIS-RTOS API是ARM公司为RTOS内核制定的一套通用接口协议,它提供了一套标准的API接口,可以移植到各种各样的RTOS上,使得上层的软件.中间件. ...

  3. 常用快递单号物流查询接口通用API(JAVA快递鸟对接)

    快递查询接口通用API是给发货电商用来实现查询快递物流轨迹功能的,接口对接前要先到快递鸟网站申请接口秘钥和APIKEY 快递API的应用场景与用途 最常见的应用场景如下: (1)电商网站:例如B2C. ...

  4. 帝国cms万能通用api二次开发核心包使用说明

    简介 帝国cms万能通用api二次开发核心包是一款可以用地对帝国cms进行二次开发,可进行开发微信小程序.百度小程序.支付宝小程序.轻应用.苹果ios安卓android.其他营销插件的二次开发核心包. ...

  5. Linux内核scatterlist API介绍 DMA SG搬移

    Linux内核scatterlist API介绍 1. 前言 我们在那些需要和用户空间交互大量数据的子系统(例如MMC[1].Video.Audio等)中,经常看到scatterlist的影子.对我们 ...

  6. 主线剧情07.3-Linux驱动编程-内核态API总结备查

    驱动程序 中的 设备相关 和 常用内核态 API 总结备查 多处网搜和引用,做了良好的整理,侵删. 本文对应的驱动源代码在 github/gitee 仓库里:并且 在 Github 上的原版文章日后可 ...

  7. feathers mysql_Feathers 数据库和通用API

    Feathers数据库适配器是一些模块,它们使用通用API进行初始化和设置并提供通用查询语法,从而为特定数据库提供实现标准CRUD功能的服务. 重要: 服务允许实现对任何数据库的访问,此处列出的数据库 ...

  8. 腾讯微博API时间线相关接口返回的微博信息中head值使用问题

    腾讯微博API时间线相关接口返回的微博信息中head值表示作者头像url,这个链接直接访问并不能使用,需要再附加一个参数指定图片的大小(100.50),比如:[head]/100.

  9. 1.18.2.Table APISQL(概念与通用API、两种计划器(Planner)的主要区别、创建 TableEnvironment、临时表、永久表、创建表、虚拟表、Connector 等)

    1.18.2.概念与通用API 1.18.2.1.两种计划器(Planner)的主要区别: 1.18.2.2.Table API和SQL程序的结构 1.18.2.3.创建 TableEnvironme ...

  10. Golang面向API编程-interface(接口)

    Golang面向API编程-interface(接口) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Golang并不是一种典型的面向对象编程(Object Oriented Pr ...

最新文章

  1. docker安装nginx实例
  2. 一次真实的蓝屏分析 ntkrnlmp.exe
  3. IDEA 2020.3版本中的lombok失效问题
  4. 数据库原理与应用(SQL Server)笔记 第六章 数据完整性
  5. Java部分A+B正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA。例如:给定A = 3862767,DA = 6,则A的“6部分”PA是66,因为A中有2个6。现给定A、DA
  6. Bitmap Font生成
  7. 农行运营合规管理心得体会_“乘风破浪”的农行合规达人秀来啦
  8. php 数组重新打乱_PHP 将数组打乱 shuffle 函数
  9. “编程太差,那你别搞开发了!”基础差的程序员,你不知道有多难!!
  10. 英语总结系列(三):如何维持激情
  11. 数字信号处理matlab实验心得,数字信号处理学习心得体会3篇
  12. [Mac]图像处理JPEG工具箱jpegtbx_1.4的MATLAB编译及使用
  13. 缠中说禅电子书_缠中说禅108课PDF电子书
  14. 学前教育计算机课程设置,计算机网络背景下学前教育专业课程设置分析
  15. python12306学生票抢票脚本下载_Python 12306抢火车票脚本 Python京东抢手机脚本
  16. 反转链表(Java)
  17. 震惊!程序员一夜赚1W,没想到他就做了这个......
  18. UG/NX 二次开发(C#)自动出2D零件图思路
  19. 打通前后端全栈开发node+vue+mongodb进阶
  20. 浔阳江头夜送客,枫叶荻花秋瑟瑟——python标准输入、标准输出和注释

热门文章

  1. 北通G3游戏手柄开箱体验,原来手游高手都是这么成就的
  2. 相爱相杀:移动联通IT支撑回忆录(九)
  3. 阅读HashMap(1.6)源码所做的一些记录
  4. 计算机的桌面图标类型,软件图标的格式 电脑桌面图标是什么格式的文件啊
  5. Share Disk、Share Memory和Share Nothing的区别
  6. 基于MATLAB的车牌识别实现
  7. 进销存软件网络版连接不上,如何设置IP地址
  8. C# 图片直接打印方法
  9. RQNOJ 34 紧急援救 解题报告
  10. CodeBlock的安装、配置和运行