单片机裸机移植sqlite3
上一篇文章中提供了vfs支持,此处主要是sqlite3移植所需的线程,信号量支持,sqlite3源码在官方下载,需要很大的内存支持,移植基本原理就是实现sqlite3所需的linux api接口即可,可以通过宏定义去掉一些不用的功能,减少API依赖。ucos_iii_pthread.c/********************************************************
·
上一篇文章中提供了vfs支持,此处主要是sqlite3移植所需的线程,信号量支持,sqlite3源码在官方下载,需要很大的内存支持,移植基本原理就是实现sqlite3所需的linux api接口即可,可以通过宏定义去掉一些不用的功能,减少API依赖。
ucos_iii_pthread.c
/*************************************************************************************************************
* 文件名 : ucos_iii_pthread.c
* 功能 : ucos_iii虚拟的pthread相关接口
* 作者 : cp1300@139.com
* 创建时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 详细 : 用于实现sqlite3移植所需的信号量,线程操作相关接口
*************************************************************************************************************/
#include "system.h"
#include "ucos_iii_pthread.h"
#include <stdlib.h>
#include "errno-base.h"
#define MUTEXA_INIT_ID 0x12546f24 //用于标示互斥锁是否初始化了
//内存申请接口
static void* (*pthread_malloc)(size_t size) = malloc; //默认的内存申请接口
static void (*pthread_free)(void *ptr) = free; //默认的内存释放接口
/*************************************************************************************************************************
* 函数 : int pthread_mutexattr_init(pthread_mutexattr_t *mattr)
* 功能 : 初始化互斥锁属性
* 参数 : mattr:互斥锁属性对象
* 返回 : 0:成功;负数:返回错误码
* 依赖 : ucos iii
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 : pshared 属性的 缺省值为 PTHREAD_PROCESS_PRIVATE。 该值表示可以在进程内使用经过初始化的 互斥锁。
对于 互斥锁属性对象,必须首先通过调用 pthread_mutexattr_destroy(3C) 将其销毁,才能重新初始化该对象
不会申请内存
*************************************************************************************************************************/
int pthread_mutexattr_init(pthread_mutexattr_t *mattr)
{
if(mattr == NULL) return -EINVAL;
mattr->InitId = MUTEXA_INIT_ID;
return 0;
}
/*************************************************************************************************************************
* 函数 : int pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type)
* 功能 : 设置互斥锁属性类型
* 参数 : attr:互斥锁指针;type:设置的属性
* 返回 : 0:成功;负数:返回错误码
* 依赖 : ucos iii
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 : 此方法并没有被实现
PTHREAD_MUTEX_NORMAL 描述: 此类型的 互斥锁不会检测 死锁
PTHREAD_MUTEX_ERRORCHECK 描述: 此类型的 互斥锁可提供错误检查
PTHREAD_MUTEX_RECURSIVE 描述: 如果线程在不首先解除锁定 互斥锁的情况下尝试重新锁定该互斥锁,则可成功锁定该互斥锁
PTHREAD_MUTEX_DEFAULT 描述: 如果尝试以 递归方式锁定此类型的 互斥锁,则会产生不确定的行为
*************************************************************************************************************************/
int pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type)
{
if(attr == NULL || attr->InitId != MUTEXA_INIT_ID) return -EINVAL;
uart_printf("pthread_mutexattr_settype(xxx, %d);\r\n", type);
return 0;
}
/*************************************************************************************************************************
* 函数 : int pthread_mutexattr_destroy(pthread_mutexattr_t *mattr)
* 功能 : 销毁互斥锁属性对象
* 参数 : mattr:互斥锁属性对象
* 返回 : 0:成功;负数:返回错误码
* 依赖 : ucos iii
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 : 由于之前也没有涉及到内存申请,此处只去掉初始化ID即可
*************************************************************************************************************************/
int pthread_mutexattr_destroy(pthread_mutexattr_t *mattr)
{
if(mattr == NULL) return -EINVAL;
mattr->InitId = 0;
return 0;
}
/*************************************************************************************************************************
* 函数 : int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr)
* 功能 : 互斥锁初始化
* 参数 : mutex:互斥锁指针;attr:提前初始化的属性信息
* 返回 : 0:成功;负数:返回错误码
* 依赖 : ucos iii
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 : 不会申请内存,调用ucos接口初始化互斥锁
*************************************************************************************************************************/
int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t *attr)
{
OS_ERR err;
if(mutex == NULL || attr == NULL) return -EINVAL;
OSMutexCreate(&mutex->mutex, "Sqlite3", &err);
if(err == OS_ERR_NONE)
{
mutex->mattr = (pthread_mutexattr_t *)attr; //记录互斥锁属性
mutex->InitId = MUTEXA_INIT_ID;
return 0; //初始化成功了
}
else
{
DEBUG("Sqlite3初始化互斥锁失败,错误:%d\r\n", err);
return -1;
}
}
/*************************************************************************************************************************
* 函数 : int pthread_mutex_destroy(pthread_mutex_t *mutex)
* 功能 : 销毁一个互斥锁
* 参数 : mutex:互斥锁指针
* 返回 : 0:成功;负数:返回错误码
* 依赖 : ucos iii
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 : 调用ucos接口删除互斥锁
*************************************************************************************************************************/
int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
OS_ERR err;
if(mutex == NULL || mutex->InitId != MUTEXA_INIT_ID) return -EINVAL;
OSMutexDel(&mutex->mutex, OS_OPT_DEL_ALWAYS, &err);
if(err == OS_ERR_NONE)
{
mutex->mattr = NULL; //记录互斥锁属性清除
mutex->InitId = 0;
return 0; //初始化成功了
}
else
{
DEBUG("Sqlite3删除互斥锁失败,错误:%d\r\n", err);
return -1;
}
}
/*************************************************************************************************************************
* 函数 : int pthread_mutex_lock(pthread_mutex_t *mutex)
* 功能 : 申请互斥锁
* 参数 : mutex:互斥锁指针
* 返回 : 0:成功;负数:返回错误码
* 依赖 : ucos iii
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 : 调用ucos接口申请互斥锁
*************************************************************************************************************************/
int pthread_mutex_lock(pthread_mutex_t *mutex)
{
OS_ERR err;
CPU_TS ts;
if(mutex == NULL || mutex->InitId != MUTEXA_INIT_ID) return -EINVAL;
OSMutexPend(&mutex->mutex, 0, OS_OPT_PEND_BLOCKING, &ts, &err); //OS_OPT_PEND_BLOCKING阻塞等待
if(err == OS_ERR_NONE || err == OS_ERR_MUTEX_OWNER)
{
return 0;
}
else
{
DEBUG("Sqlite3申请互斥锁失败,错误:%d\r\n", err);
return -1;
}
}
/*************************************************************************************************************************
* 函数 : int pthread_mutex_trylock( pthread_mutex_t *mutex)
* 功能 : 非阻塞申请互斥锁
* 参数 : mutex:互斥锁指针
* 返回 : 0:成功;负数:返回错误码
* 依赖 : ucos iii
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 : 如果mutex参数所指定的互斥锁已经被锁定的话,调用pthread_mutex_trylock函数不会阻塞当前线程,而是立即返回一个值来描述互斥锁的状况
*************************************************************************************************************************/
int pthread_mutex_trylock( pthread_mutex_t *mutex)
{
OS_ERR err;
CPU_TS ts;
if(mutex == NULL || mutex->InitId != MUTEXA_INIT_ID) return -EINVAL;
OSMutexPend(&mutex->mutex, 0, OS_OPT_PEND_NON_BLOCKING, &ts, &err); //非阻塞,设置超时无意义
if(err == OS_ERR_NONE)
{
return 0; //信号量可用
}
else if(err == OS_ERR_PEND_WOULD_BLOCK) //当前信号量不可用
{
return -EBUSY;
}
else
{
DEBUG("Sqlite3申请互斥锁失败,错误:%d\r\n", err);
return -1;
}
}
/*************************************************************************************************************************
* 函数 : int pthread_mutex_unlock(pthread_mutex_t *mutex)
* 功能 : 互斥锁解锁
* 参数 : mutex:互斥锁指针
* 返回 : 0:成功;负数:返回错误码
* 依赖 : ucos iii
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 :
*************************************************************************************************************************/
int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
OS_ERR err;
if(mutex == NULL || mutex->InitId != MUTEXA_INIT_ID) return -EINVAL;
OSMutexPost(&mutex->mutex, OS_OPT_POST_NONE, &err); //释放信号量
if(err == OS_ERR_NONE || err == OS_ERR_MUTEX_NESTING)
{
return 0; //成功
}
else
{
DEBUG("Sqlite3释放互斥锁失败,错误:%d\r\n", err);
return -1;
}
}
#define PTHREAD_INIT_ID 0x55874187 //任务初始化id,标识任务是否被初始化了
//任务封装
void pthread_task(void *p_arg)
{
ucosiii_pthread_type *pThread = (ucosiii_pthread_type*)p_arg;
if((pThread != NULL) && (pThread->InitId == PTHREAD_INIT_ID))
{
pThread->pTaskReturnValue = pThread->p_task(pThread->p_arg); //执行任务函数,记录任务返回值
pThread->isExit = TRUE; //任务结束
}
}
/*************************************************************************************************************************
* 函数 : int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, void *(*start_rtn)(void*), void *arg)
* 功能 : 线程创建
* 参数 : tidp:线程指针;attr:线程属性;start_rtn:线程执行的函数;arg:线程执行函数的参数
* 返回 : 0:成功;负数:返回错误码
* 依赖 : ucos iii
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 :
*************************************************************************************************************************/
int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, void *(*start_rtn)(void*), void *arg)
{
static u32 cnt; //每次调用自增一次,用于产生不同的名称
ucosiii_pthread_type *pThread;
OS_ERR err;
if(start_rtn == NULL) return -EINVAL;
pThread = pthread_malloc(sizeof(ucosiii_pthread_type)); //申请内存
if(pThread == NULL)
{
DEBUG("Sqlite3创建线程失败,内存不足!\r\n");
return -ENOMEM;
}
sprintf(pThread->p_name, "Sqlite_%d", cnt++); //产生随机任务名称
pThread->p_task = start_rtn; //任务函数
pThread->p_arg = arg; //任务参数
pThread->prio = SQLITE_PTHREAD_PRIO; //任务优先级
pThread->pThis = pThread; //记录当前任务信息指针,并将任务指针当做任务参数传递到任务中
pThread->pTaskReturnValue = NULL; //任务返回值
pThread->isExit = FALSE; //任务未结束
pThread->InitId = 0; //任务初始化ID无效
OSTaskCreate(&pThread->TCB, //任务控制块
(CPU_CHAR *)pThread->p_name, //任务的名字
pthread_task, //任务函数
pThread, //传递参数
pThread->prio, //任务的优先级
pThread->p_stk_base, //任务堆栈基地址
SQLITE_PTHREAD_STK_SIZE-64, //任务堆栈深度限位,用到这个位置,任务不能再继续使用
SQLITE_PTHREAD_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY)0, //禁止任务消息队列
(OS_TICK)0, //默认时间片长度
(void *)0, //不需要补充用户存储区
(OS_OPT)OS_OPT_TASK_NONE, //没有任何选项
&err //返回的错误码
);
if(err == OS_ERR_NONE) //任务创建成功
{
*tidp = (u32)pThread; //返回任务的指针
pThread->InitId = PTHREAD_INIT_ID; //任务创建成功
DEBUG("SQLITE任务%s建立成功\r\n",pThread->p_name);
return 0;
}
else
{
pthread_free(pThread); //释放掉申请的内存
*tidp = NULL;
DEBUG("SQLITE任务%s建立失败,错误:%d\r\n",pThread->p_name, err);
return -1;
}
}
/*************************************************************************************************************************
* 函数 : int pthread_join(pthread_t thread, void **retval)
* 功能 : 等待一个线程的结束
* 参数 : tidp:线程指针;retval: 用户定义的指针,用来存储被等待线程的返回值
* 返回 : 0:成功;负数:返回错误码
* 依赖 : ucos iii
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 :
*************************************************************************************************************************/
int pthread_join(pthread_t thread, void **retval)
{
ucosiii_pthread_type *pThread = (ucosiii_pthread_type*)thread;
OS_ERR err;
if((pThread != NULL) && (pThread->InitId == PTHREAD_INIT_ID))
{
while(pThread->isExit == FALSE) //等待任务退出
{
Sleep(20);
}
//任务退出后就要销毁任务了,可是这个返回值是个指针,如果是现成中申请的内存,需要用户自己在返回数据使用完成后释放掉
*retval = pThread->pTaskReturnValue; //任务的返回值
//开始销毁任务,释放内存了
OSTaskDel(&pThread->TCB, &err);
if(err == OS_ERR_NONE) //任务删除成功
{
DEBUG("SQLITE任务%s删除成功\r\n",pThread->p_name);
//释放内存前,先清除掉一些重要数据,防止残存在内存中
pThread->p_task = NULL; //任务函数
pThread->p_arg = 0; //任务参数
pThread->prio = 255; //任务优先级
pThread->pThis = NULL; //记录当前任务信息指针,并将任务指针当做任务参数传递到任务中
pThread->pTaskReturnValue = NULL; //任务返回值
pThread->isExit = FALSE; //任务未结束
pThread->InitId = 0; //任务初始化ID无效
pthread_free(pThread); //释放内存
return 0;
}
else
{
DEBUG("SQLITE任务%s删除失败,错误:%d\r\n",pThread->p_name, err);
return -1;
}
}
else return -1;
}
/*************************************************************************************************************************
* 函数 : pid_t getpid(void)
* 功能 : 获取当前程序pid
* 参数 : 无
* 返回 : PID
* 依赖 :
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 :
*************************************************************************************************************************/
pid_t getpid(void)
{
uart_printf("getpid()\r\n");
return 0;
}
/*************************************************************************************************************************
* 函数 : void sleep(u32 seconds)
* 功能 : 线程延时(单位秒)
* 参数 : 无
* 返回 : 无
* 依赖 :
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 :
*************************************************************************************************************************/
void sleep(u32 seconds)
{
Sleep(seconds * 1000);
}
/*************************************************************************************************************************
* 函数 : void usleep(u64 usec)
* 功能 : 线程延时(单位us)
* 参数 : 无
* 返回 : 无
* 依赖 :
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 :
*************************************************************************************************************************/
void usleep(u64 usec)
{
Sleep(usec / 1000);
}
/*************************************************************************************************************************
* 函数 : int gettimeofday(struct timeval *tp, void *ignore)
* 功能 : 获取时间戳
* 参数 : tv:存放当前时间;ignore:忽略
* 返回 : 0:成功;负数:返回错误码
* 依赖 :
* 作者 : cp1300@139.com
* 时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 说明 :
*************************************************************************************************************************/
int gettimeofday(struct timeval *tp, void *ignore)
{
uart_printf("gettimeofday(,)\r\n");
return 0;
}
//ucos_iii_pthread.h
/*************************************************************************************************************
* 文件名 : ucos_iii_pthread.h
* 功能 : ucos_iii虚拟的pthread相关接口
* 作者 : cp1300@139.com
* 创建时间 : 2020-09-29
* 最后修改时间 : 2020-09-29
* 详细 : 用于实现sqlite3移植所需的信号量,线程操作相关接口
*************************************************************************************************************/
#ifndef _UCOS_III_PTHREAD_H_
#define _UCOS_III_PTHREAD_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "system.h"
#include "main.h"
#include "ff_vfs.h"
//SQLITE相关配置宏定义
#define SQLITE_MAX_MMAP_SIZE 0 //不使用mmap
#define SQLITE_OMIT_WAL 1 //WAL机制
#define SQLITE_OMIT_LOAD_EXTENSION 1 //不使用动态加载库
#define SQLITE_MALLOC(x) malloc(x)
#define SQLITE_FREE(x) free(x)
#define SQLITE_REALLOC(x,y) realloc((x),(y))
//互斥锁属性
typedef struct
{
u32 InitId;
}pthread_mutexattr_t;
//互斥锁控制
typedef struct
{
OS_MUTEX mutex;
u32 InitId; //自己定义的一个,用于标示是否初始化了
pthread_mutexattr_t *mattr; //互斥锁属性
} pthread_mutex_t;
//互斥锁类型设置
enum
{
PTHREAD_MUTEX_NORMAL = 0,
PTHREAD_MUTEX_RECURSIVE = 1,
PTHREAD_MUTEX_ERRORCHECK = 2,
PTHREAD_MUTEX_ERRORCHECK_NP = PTHREAD_MUTEX_ERRORCHECK,
PTHREAD_MUTEX_RECURSIVE_NP = PTHREAD_MUTEX_RECURSIVE,
PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
};
#define SQLITE_PTHREAD_PRIO SQLITE_TASK_PRIO //sqlite创建的线程优先级
#define SQLITE_PTHREAD_STK_SIZE (64*1024) //任务堆栈大小
//实际任务的信息
typedef struct
{
void *pThis; //指向当前的指针(将线程执行函数进行封装,便于当线程结束后执行删除线程操作,并获取线程的返回值)
void *pTaskReturnValue; //任务返回值
bool isExit; //任务是否退出了
OS_TCB TCB; //线程控制块
char p_name[24]; //线程名称
void* (*p_task)(void*); //线程函数-兼容linux
void *p_arg; //线程参数
OS_PRIO prio; //线程优先级
CPU_STK p_stk_base[SQLITE_PTHREAD_STK_SIZE];//任务堆栈
u32 InitId; //任务初始化id
}ucosiii_pthread_type;
//任务句柄,此处实际上是个指向任务块的指针
typedef unsigned int pthread_t; //存储的是ucosiii_pthread_type的指针
typedef int pid_t;
//任务所需的信息-此处用不上,保留为一个整形数据就行
typedef unsigned int pthread_attr_t;
typedef int ssize_t;
#define timespec timeval
struct timezone {
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of dst correction */
};
//互斥锁
int pthread_mutexattr_init(pthread_mutexattr_t *mattr); //初始化互斥锁属性
int pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type); //设置互斥锁属性类型
int pthread_mutexattr_destroy(pthread_mutexattr_t *mattr); //销毁互斥锁属性对象
int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t *attr); //互斥锁初始化
int pthread_mutex_destroy(pthread_mutex_t *mutex); //销毁一个互斥锁
int pthread_mutex_lock(pthread_mutex_t *mutex); //申请互斥锁
int pthread_mutex_trylock( pthread_mutex_t *mutex); //非阻塞申请互斥锁
int pthread_mutex_unlock(pthread_mutex_t *mutex); //互斥锁解锁
//线程相关
int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, void *(*start_rtn)(void*), void *arg); //线程创建
int pthread_join(pthread_t thread, void **retval); //等待一个线程的结束
pid_t getpid(void); //获取当前程序pid
void sleep(u32 seconds); //线程延时(单位秒)
void usleep(u64 usec); //线程延时(单位us)
int gettimeofday(struct timeval *tp, void *ignore); //获取时间戳
#ifdef __cplusplus
}
#endif
#endif //_UCOS_III_PTHREAD_H_
请先初始化ucos以及文件系统,然后就可以初始化sqlite3,并查询数据,测试代码如下:
{
sqlite3 *ppDb;
int sta;
const char *pSQL = "SELECT *FROM \"tab\" WHERE id=2;";
char *zErrMsg = 0;
sqlite3_initialize();
sta = sqlite3_open("test.db", &ppDb);
if(sta == SQLITE_OK)
{
uart_printf("SQLITE打开数据库成功\r\n");
//查询数据
sta = sqlite3_exec( ppDb, pSQL, callback, NULL, &zErrMsg );
if( sta != SQLITE_OK)
{
uart_printf("%s: %s\r\n",pSQL, sqlite3_errmsg(ppDb));
if(zErrMsg)
{
uart_printf("ErrMsg = %s \r\n", zErrMsg);
sqlite3_free(zErrMsg);
}
}
sqlite3_close(ppDb);
}
else
{
uart_printf("SQLITE打开数据库错误:%d\r\n", sta);
}
Sleep(10000000);
}
int callback(void* data, int ncols, char** values, char** headers)
{
int i;
int len =0;
int ll=0;
for(i=0; i < ncols; i++)
{
if(strlen(headers[i])>len)
len = strlen(headers[i]);
}
for(i=0; i < ncols; i++)
{
ll = len-strlen(headers[i]);
while(ll)
{
uart_printf(" ");
--ll;
}
uart_printf("%s: %s\r\n", headers[i], values[i]);
}
uart_printf("\r\n");
return 0;
}
测试结果
更多推荐
已为社区贡献5条内容
所有评论(0)