update prepare_for_master latest commit(5a10e4153c) to 2023_open_source_contest

it is OK
This commit is contained in:
IACU 2023-11-01 16:29:47 +08:00
commit e03b3b390a
217 changed files with 237742 additions and 2565 deletions

6
.gitmodules vendored
View File

@ -24,11 +24,11 @@
url = https://www.gitlink.org.cn/chunyexixiaoyu/kendryte-sdk-source.git
[submodule "APP_Framework/lib/lorawan/lora_radio_driver"]
path = APP_Framework/lib/lorawan/lora_radio_driver
url = https://gitlink.org.cn/IACU/lora_radio_driver.git
url = https://gitlink.org.cn/xuos/lora_radio_driver
[submodule "APP_Framework/lib/lorawan/lorawan_devicenode"]
path = APP_Framework/lib/lorawan/lorawan_devicenode
url = https://gitlink.org.cn/IACU/lorawan_devicenode.git
url = https://gitlink.org.cn/xuos/lorawan_devicenode.git
branch = master
[submodule "APP_Framework/lib/lorawan/lorawan_gateway_single_channel"]
path = APP_Framework/lib/lorawan/lorawan_gateway_single_channel
url = https://gitlink.org.cn/IACU/lorawan_gateway_single_channel.git
url = https://gitlink.org.cn/xuos/lorawan_gateway_single_channel.git

View File

@ -46,7 +46,12 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
endif
ifeq ($(CONFIG_USER_TEST_I2C),y)
SRC_FILES += test_i2c.c
ifeq ($(CONFIG_BOARD_EDU_RISCV64_EVB),y)
SRC_FILES += test_i2c_riscv.c
endif
ifeq ($(CONFIG_BOARD_EDU_ARM32_EVB),y)
SRC_FILES += test_i2c_arm.c
endif
endif
ifeq ($(CONFIG_USER_TEST_UART),y)
@ -66,7 +71,12 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
endif
ifeq ($(CONFIG_USER_TEST_RS485),y)
SRC_FILES += test_rs485.c
ifeq ($(CONFIG_BOARD_EDU_RISCV64_EVB),y)
SRC_FILES += test_rs485_riscv.c
endif
ifeq ($(CONFIG_BOARD_EDU_ARM32_EVB),y)
SRC_FILES += test_rs485_arm.c
endif
endif
ifeq ($(CONFIG_USER_TEST_HWTIMER),y)

View File

@ -22,7 +22,7 @@
#include <transform.h>
#ifdef ADD_XIZI_FEATURES
#define BSP_LED_PIN 134
#define BSP_LED_PIN 29
#define NULL_PARAMETER 0
static uint16_t pin_fd=0;
@ -37,7 +37,7 @@ void LedFlip(void *parameter)
void TestHwTimer(void)
{
x_ticks_t period = 100000;
x_ticks_t period = 1;
pin_fd = PrivOpen(HWTIMER_PIN_DEV_DRIVER, O_RDWR);
if(pin_fd<0) {

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: test_i2c.c
* @brief: a application of i2c function
* @version: 1.1
* @author: AIIT XUOS Lab
* @date: 2022/12/17
*/
#include <stdio.h>
#include <string.h>
#include <transform.h>
#include <sleep.h>
#ifdef ADD_XIZI_FEATURES
#define I2C_SLAVE_ADDRESS (0x44U)
void TestI2C(void)
{
// config IIC pin(SCL:34.SDA:35) in menuconfig
int iic_fd = PrivOpen(I2C_DEV_DRIVER, O_RDWR);
if (iic_fd < 0)
{
printf("open iic_fd fd error:%d\n", iic_fd);
return;
}
printf("IIC open successful!\n");
// init iic
uint16 iic_address = I2C_SLAVE_ADDRESS;
struct PrivIoctlCfg ioctl_cfg;
ioctl_cfg.ioctl_driver_type = I2C_TYPE;
ioctl_cfg.args = (void *)&iic_address;
if (0 != PrivIoctl(iic_fd, OPE_INT, &ioctl_cfg))
{
printf("ioctl iic fd error %d\n", iic_fd);
PrivClose(iic_fd);
return;
}
printf("IIC configure successful!\n");
// I2C read and write
uint8_t data[32];
while (1)
{
PrivWrite(iic_fd, NONE, 0);
msleep(40);
PrivRead(iic_fd, data, 4);
float result = ((data[2] << 8 | data[3]) >> 2) * 165.0 /( (1 << 14) - 1) - 40.0;
int temperature = result*10;
printf("Temperature : %d.%d ℃\n", temperature/10, temperature%10);
result = ((data[0] << 8 | data[1] ) & 0x3fff) * 100.0 / ( (1 << 14) - 1);
int humidity = result*10;
printf("Humidity : %d.%d %%RH\n", humidity/10, humidity%10);
printf("HS300X origin data1:0x%2x%2x%2x%2x\n", data[0],data[1],data[2],data[3]);
msleep(1000);
}
PrivClose(iic_fd);
return;
}
PRIV_SHELL_CMD_FUNCTION(TestI2C, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR);
#endif

View File

@ -0,0 +1,108 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: test_rs485.c
* @brief: a application of rs485 function
* @version: 1.1
* @author: AIIT XUOS Lab
* @date: 2022/12/17
*/
#include <stdio.h>
#include <string.h>
#include <transform.h>
#ifdef ADD_XIZI_FEATURES
#define BSP_485_DIR_PIN 24
void Test485(void)
{
int pin_fd = PrivOpen(RS485_PIN_DEV_DRIVER, O_RDWR);
if (pin_fd < 0)
{
printf("open pin fd error:%d\n", pin_fd);
return;
}
int uart_fd = PrivOpen(RS485_UART_DEV_DRIVER, O_RDWR);
if (uart_fd < 0)
{
printf("open pin fd error:%d\n", uart_fd);
return;
}
printf("uart and pin fopen success\n");
//config led pin in board
struct PinParam pin_parameter;
memset(&pin_parameter, 0, sizeof(struct PinParam));
pin_parameter.cmd = GPIO_CONFIG_MODE;
pin_parameter.pin = BSP_485_DIR_PIN;
pin_parameter.mode = GPIO_CFG_OUTPUT;
struct PrivIoctlCfg ioctl_cfg;
ioctl_cfg.ioctl_driver_type = PIN_TYPE;
ioctl_cfg.args = (void *)&pin_parameter;
if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg)) {
printf("ioctl pin fd error %d\n", pin_fd);
PrivClose(pin_fd);
return;
}
struct SerialDataCfg uart_cfg;
memset(&uart_cfg, 0, sizeof(struct SerialDataCfg));
uart_cfg.serial_baud_rate = BAUD_RATE_115200;
uart_cfg.serial_data_bits = DATA_BITS_8;
uart_cfg.serial_stop_bits = STOP_BITS_1;
uart_cfg.serial_parity_mode = PARITY_NONE;
uart_cfg.serial_bit_order = BIT_ORDER_LSB;
uart_cfg.serial_invert_mode = NRZ_NORMAL;
uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ;
uart_cfg.serial_timeout = 1000;
uart_cfg.is_ext_uart = 0;
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
ioctl_cfg.args = (void *)&uart_cfg;
if (0 != PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg))
{
printf("ioctl uart fd error %d\n", uart_fd);
PrivClose(uart_fd);
return;
}
struct PinStat pin_dir;
pin_dir.pin = BSP_485_DIR_PIN;
while (1)
{
pin_dir.val = GPIO_HIGH;
PrivWrite(pin_fd,&pin_dir,0);
PrivWrite(uart_fd,"Hello world!\n",sizeof("Hello world!\n"));
printf("Send: Hello world!\n");
PrivTaskDelay(1000);
pin_dir.val = GPIO_LOW;
PrivWrite(pin_fd,&pin_dir,0);
char recv_buff[100];
memset(recv_buff,0,sizeof(recv_buff));
PrivRead(uart_fd,recv_buff,20);
printf("Recv: %s\n",recv_buff);
PrivTaskDelay(1000);
}
PrivClose(pin_fd);
PrivClose(uart_fd);
return;
}
PRIV_SHELL_CMD_FUNCTION(Test485, a RS485 test sample, PRIV_SHELL_CMD_MAIN_ATTR);
#endif

View File

@ -324,7 +324,7 @@ void TestSocket(int argc, char* argv[])
return;
} else {
memset(iperf_param.host, 0, sizeof(iperf_param.host));
strncpy(iperf_param.host, ip_ptr, strlen(ip_ptr));
strncpy(iperf_param.host, ip_ptr, sizeof(iperf_param.host));
}
iperf_mode->mode = IPERF_MODE_CLIENT;
}
@ -335,10 +335,22 @@ void TestSocket(int argc, char* argv[])
if (mode == IPERF_MODE_SERVER) {
printf("[%s] Running iperf server at port %d.\n", __func__, iperf_param.port);
PrivTaskCreate(&thd, NULL, TestIperfServer, (void*)&iperf_param);
#ifdef ADD_XIZI_FEATURES
char task_name[] = "test_iperf_server";
pthread_args_t args;
args.pthread_name = task_name;
args.arg = (void *)&iperf_param;
PrivTaskCreate(&thd, NULL, TestIperfServer, (void*)&args);
#endif
} else if (mode == IPERF_MODE_CLIENT) {
printf("[%s] Running iperf client to server at %s:%d.\n", __func__, iperf_param.host, iperf_param.port);
PrivTaskCreate(&thd, NULL, TestIperfClient, (void*)&iperf_param);
#ifdef ADD_XIZI_FEATURES
char task_name[] = "test_iperf_client";
pthread_args_t args;
args.pthread_name = task_name;
args.arg = (void *)&iperf_param;
PrivTaskCreate(&thd, NULL, TestIperfClient, (void*)&args);
#endif
}
PrivTaskStartup(&thd);

View File

@ -1,5 +1,5 @@
#include <cstdio>
#include <transform.h>
// #include <transform.h>
#include <stdio.h>
#include "tensorflow/lite/micro/all_ops_resolver.h"

View File

@ -26,3 +26,4 @@ void mnist_app(void);
int tfmnist(void) {
mnist_app();
}
PRIV_SHELL_CMD_FUNCTION(tfmnist, a tenorflow_lite_for_microcontroller sample, PRIV_SHELL_CMD_FUNC_ATTR);

View File

@ -24,23 +24,10 @@
#include "lv_demo_calendar.h"
#include <transform.h>
// extern void lv_example_chart_2(void);
// extern void lv_example_img_1(void);
// extern void lv_example_img_2(void);
// extern void lv_example_img_3(void);
// extern void lv_example_img_4(void);
// extern void lv_example_line_1(void);
// extern void lv_example_aoteman(void);
extern void lv_example_show(void);
void* lvgl_thread(void *parameter)
{
/* display demo; you may replace with your LVGL application at here */
lv_demo_calendar();
// lv_example_img_1();
// lv_example_chart_2();
// lv_example_table_1();
// lv_example_line_1();
// lv_example_aoteman();
/* handle the tasks of LVGL */
lv_example_show();
while(1)
{
lv_task_handler();
@ -48,12 +35,12 @@ void* lvgl_thread(void *parameter)
}
}
pthread_t lvgl_task;
static pthread_t lvgl_task;
static int lvgl_demo_init(void)
{
pthread_attr_t attr;
attr.schedparam.sched_priority = 25;
attr.stacksize = 4096;
attr.stacksize = 8192;
PrivTaskCreate(&lvgl_task, &attr, lvgl_thread, NULL);

View File

@ -52,7 +52,7 @@ int lv_port_init(void)
#endif
#ifndef PKG_USING_LVGL_INDEV_DEVICE
lv_port_indev_init();
// lv_port_indev_init();
#endif
return 0;

View File

@ -17,12 +17,21 @@
extern int FrameworkInit();
extern void ApplicationOtaTaskInit(void);
#ifdef OTA_BY_PLATFORM
extern int OtaTask(void);
#endif
int main(void)
{
printf("Hello, world! \n");
FrameworkInit();
printf("Hello, world! \n");
FrameworkInit();
#ifdef APPLICATION_OTA
ApplicationOtaTaskInit();
ApplicationOtaTaskInit();
#endif
#ifdef OTA_BY_PLATFORM
OtaTask();
#endif
return 0;
}

View File

@ -28,10 +28,14 @@ void TvocTb600bTvoc10(void)
{
struct SensorQuantity *tvoc = SensorQuantityFind(SENSOR_QUANTITY_TB600B_TVOC, SENSOR_QUANTITY_TVOC);
SensorQuantityOpen(tvoc);
int32_t result = 0;
result = SensorQuantityReadValue(tvoc);
for(int i = 0; i < 10;i++)
{
PrivTaskDelay(1000);
SensorQuantityReadValue(tvoc);
}
printf("tvoc concentration is : %dppb\n", result);
SensorQuantityClose(tvoc);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),tvoc, TvocTb600bTvoc10, read data from tvoc sensor);

View File

@ -39,7 +39,7 @@ void* ttf_thread(void *parameter)
}
}
pthread_t lvgl_task;
static pthread_t lvgl_task;
static int ttf_demo_init(void)
{
pthread_attr_t attr;

View File

@ -23,7 +23,7 @@ if ADD_XIZI_FEATURES
config ADAPTER_EC200T_DRIVER
string "EC200T device uart driver path"
default "/dev/usart2_dev2"
default "/dev/uart8_dev8"
depends on !ADAPTER_EC200T_DRIVER_EXTUART
if ADAPTER_EC200T_DRIVER_EXTUART

View File

@ -163,8 +163,12 @@ static int Ec200tIoctl(struct Adapter *adapter, int cmd, void *args)
serial_cfg.serial_parity_mode = PARITY_NONE;
serial_cfg.serial_bit_order = STOP_BITS_1;
serial_cfg.serial_invert_mode = NRZ_NORMAL;
#ifdef TOOL_USING_OTA
serial_cfg.serial_timeout = OTA_RX_TIMEOUT;
#else
//serial receive timeout 10s
serial_cfg.serial_timeout = 10000;
serial_cfg.serial_timeout = 100000;
#endif
serial_cfg.is_ext_uart = 0;
#ifdef ADAPTER_EC200T_DRIVER_EXT_PORT
serial_cfg.is_ext_uart = 1;

View File

@ -6,7 +6,7 @@ menuconfig SUPPORT_CONNECTION_FRAMEWORK
if SUPPORT_CONNECTION_FRAMEWORK
config CONNECTION_FRAMEWORK_DEBUG
bool "Using connection framework debug log function"
default y
default n
menuconfig CONNECTION_INDUSTRIAL_NETWORK
bool "Using industrial network"

View File

@ -124,7 +124,9 @@ int ParseATReply(char *str, const char *format, ...)
void ATSprintf(int fd, const char *format, va_list params)
{
last_cmd_len = vsnprintf(send_buf, sizeof(send_buf), format, params);
#ifdef CONNECTION_FRAMEWORK_DEBUG
printf("AT send %s len %u\n",send_buf, last_cmd_len);
#endif
PrivWrite(fd, send_buf, last_cmd_len);
}
@ -264,29 +266,34 @@ int AtSetReplyCharNum(ATAgentType agent, unsigned int num)
int EntmSend(ATAgentType agent, const char *data, int len)
{
char send_buf[128];
if(len > 128){
printf("send length %d more then max 128 Bytes.\n",len);
if(len > 256){
printf("send length %d more then max 256 Bytes.\n",len);
return -1;
}
char *send_buff = (char *)PrivMalloc(256);
PrivMutexObtain(&agent->lock);
memset(send_buf, 0, 128);
memset(send_buff, 0, 256);
agent->receive_mode = ENTM_MODE;
memcpy(send_buf, data, len);
// memcpy(send_buf + len, "!@", 2);
memcpy(send_buff, data, len);
PrivWrite(agent->fd, send_buf, len);
PrivWrite(agent->fd, send_buff, len);
PrivMutexAbandon(&agent->lock);
printf("entm send %s length %d\n",send_buf, len);
#ifdef CONNECTION_FRAMEWORK_DEBUG
printf("entm send length %d\n", len);
#endif
PrivFree(send_buff);
return 0;
}
int EntmRecv(ATAgentType agent, char *rev_buffer, int buffer_len, int timeout_s)
{
struct timespec abstime;
uint32 real_recv_len = 0;
abstime.tv_sec = timeout_s;
if(buffer_len > ENTM_RECV_MAX){
@ -299,21 +306,25 @@ int EntmRecv(ATAgentType agent, char *rev_buffer, int buffer_len, int timeout_s)
PrivMutexAbandon(&agent->lock);
//PrivTaskDelay(1000);
if (PrivSemaphoreObtainWait(&agent->entm_rx_notice, &abstime)) {
#ifdef CONNECTION_FRAMEWORK_DEBUG
printf("wait sem[%d] timeout\n",agent->entm_rx_notice);
#endif
agent->entm_recv_len = 0;
return -1;
}
PrivMutexObtain(&agent->lock);
#ifdef CONNECTION_FRAMEWORK_DEBUG
printf("EntmRecv once len %d.\n", agent->entm_recv_len);
#endif
memcpy(rev_buffer, agent->entm_recv_buf, agent->entm_recv_len);
memset(agent->entm_recv_buf, 0, ENTM_RECV_MAX);
real_recv_len = agent->entm_recv_len;
agent->entm_recv_len = 0;
agent->read_len = 0;
PrivMutexAbandon(&agent->lock);
return buffer_len;
return real_recv_len;
}
static int GetCompleteATReply(ATAgentType agent)
@ -321,21 +332,22 @@ static int GetCompleteATReply(ATAgentType agent)
uint32_t read_len = 0;
char ch = 0, last_ch = 0;
bool is_full = false;
int res;
PrivMutexObtain(&agent->lock);
memset(agent->maintain_buffer, 0x00, agent->maintain_max);
agent->maintain_len = 0;
memset(agent->entm_recv_buf, 0x00, 256);
memset(agent->entm_recv_buf, 0x00, ENTM_RECV_MAX);
agent->entm_recv_len = 0;
PrivMutexAbandon(&agent->lock);
while (1) {
PrivRead(agent->fd, &ch, 1);
res = PrivRead(agent->fd, &ch, 1);
#ifdef CONNECTION_FRAMEWORK_DEBUG
if(ch != 0) {
if((res == 1) && (ch != 0)) {
printf(" %c (0x%x)\n", ch, ch);
}
#endif
@ -343,14 +355,28 @@ static int GetCompleteATReply(ATAgentType agent)
PrivMutexObtain(&agent->lock);
if (agent->receive_mode == ENTM_MODE) {
if (agent->entm_recv_len < ENTM_RECV_MAX) {
agent->entm_recv_buf[agent->entm_recv_len] = ch;
agent->entm_recv_len++;
if(agent->entm_recv_len < agent->read_len) {
#ifdef TOOL_USING_MQTT
if((res == 1) && (agent->entm_recv_len < agent->read_len))
{
agent->entm_recv_buf[agent->entm_recv_len] = ch;
agent->entm_recv_len++;
PrivMutexAbandon(&agent->lock);
continue;
} else {
}
#else
agent->entm_recv_buf[agent->entm_recv_len] = ch;
agent->entm_recv_len++;
if(agent->entm_recv_len < agent->read_len)
{
PrivMutexAbandon(&agent->lock);
continue;
}
#endif
else
{
#ifdef CONNECTION_FRAMEWORK_DEBUG
printf("ENTM_MODE recv %d Bytes done.\n",agent->entm_recv_len);
#endif
agent->receive_mode = DEFAULT_MODE;
PrivSemaphoreAbandon(&agent->entm_rx_notice);
}
@ -523,13 +549,19 @@ static int ATAgentInit(ATAgentType agent)
attr.priority = 18;
attr.stacksize = 8192;
PrivTaskCreate(&agent->at_handler, &attr, ATAgentReceiveProcess, agent);
#else
pthread_attr_t attr;
attr.schedparam.sched_priority = 25;
attr.stacksize = 4096;
#endif
PrivTaskCreate(&agent->at_handler, &attr, ATAgentReceiveProcess, agent);
char task_name[] = "at_agent";
pthread_args_t args;
args.pthread_name = task_name;
args.arg = (void *)agent;
PrivTaskCreate(&agent->at_handler, &attr, ATAgentReceiveProcess, (void *)&args);
#endif
return result;

View File

@ -28,6 +28,12 @@
#define REPLY_TIME_OUT 10
#ifdef TOOL_USING_OTA
#define ENTM_RECV_MAX OTA_RX_BUFFERSIZE
#else
#define ENTM_RECV_MAX 256
#endif
enum ReceiveMode
{
DEFAULT_MODE = 0,
@ -70,7 +76,6 @@ struct ATAgent
#endif
pthread_t at_handler;
#define ENTM_RECV_MAX 256
char entm_recv_buf[ENTM_RECV_MAX];
uint32 entm_recv_len;
enum ReceiveMode receive_mode;

View File

@ -129,6 +129,9 @@ uint8_t lora_recv_data[ADAPTER_LORA_TRANSFER_DATA_LENGTH];
struct LoraDataFormat client_recv_data_format[ADAPTER_LORA_CLIENT_NUM];
static sem_t gateway_recv_data_sem;
static sem_t gateway_send_cmd_sem;
static sem_t client_recv_cmd_sem;
static sem_t client_send_data_sem;
struct LoraDataFormat gateway_recv_data_format;
static int recv_error_cnt = 0;
@ -315,6 +318,8 @@ static int LoraGatewaySendCmd(struct Adapter *adapter, uint8_t client_id, uint16
return -1;
}
PrivSemaphoreAbandon(&gateway_send_cmd_sem);
return 0;
}
@ -410,6 +415,7 @@ static int LoraClientSendData(struct Adapter *adapter, void *send_buf, int lengt
return -1;
}
PrivSemaphoreAbandon(&client_send_data_sem);
return 0;
}
@ -462,7 +468,7 @@ static int LoraClientDataAnalyze(struct Adapter *adapter, void *send_buf, int le
struct timespec abstime;
abstime.tv_sec = DEFAULT_SEM_TIMEOUT;
ret = PrivSemaphoreObtainWait(&adapter->sem, &abstime);
ret = PrivSemaphoreObtainWait(&client_recv_cmd_sem, NULL);
if (0 == ret) {
//only handle this client_id information from gateway
if ((client_recv_data_format[client_id - 1].client_id == adapter->net_role_id) &&
@ -653,9 +659,15 @@ static int LoraReceiveDataCheck(struct Adapter *adapter, uint8_t *recv_data, uin
static void *LoraReceiveTask(void *parameter)
{
int ret = 0;
struct timespec abstime;
abstime.tv_sec = DEFAULT_SEM_TIMEOUT;
struct Adapter *lora_adapter = (struct Adapter *)parameter;
while (1) {
#ifdef AS_LORA_GATEWAY_ROLE
PrivSemaphoreObtainWait(&gateway_send_cmd_sem, NULL);
#endif
memset(lora_recv_data, 0, ADAPTER_LORA_TRANSFER_DATA_LENGTH);
ret = AdapterDeviceRecv(lora_adapter, lora_recv_data, ADAPTER_LORA_TRANSFER_DATA_LENGTH);
@ -675,8 +687,10 @@ static void *LoraReceiveTask(void *parameter)
if (ret < 0) {
continue;
}
PrivSemaphoreAbandon(&lora_adapter->sem);
#ifdef AS_LORA_CLIENT_ROLE
PrivSemaphoreAbandon(&client_recv_cmd_sem);
PrivSemaphoreObtainWait(&client_send_data_sem, &abstime);
#endif
}
return 0;
@ -834,8 +848,10 @@ static int AdapterLoraRegister(struct Adapter *adapter)
ret = AdapterDeviceRegister(adapter);
if (ret < 0) {
printf("Adapter4G register error\n");
#ifdef AS_LORA_GATEWAY_ROLE
if (lora_gateway)
PrivFree(lora_gateway);
#endif
if (lora_client)
PrivFree(lora_client);
@ -904,9 +920,13 @@ int AdapterLoraInit(void)
adapter->done = product_info->model_done;
#endif
PrivSemaphoreCreate(&adapter->sem, 0, 0);
#ifdef AS_LORA_GATEWAY_ROLE
PrivSemaphoreCreate(&gateway_recv_data_sem, 0, 0);
PrivSemaphoreCreate(&gateway_send_cmd_sem, 0, 0);
#else//AS_LORA_CLIENT_ROLE
PrivSemaphoreCreate(&client_recv_cmd_sem, 0, 0);
PrivSemaphoreCreate(&client_send_data_sem, 0, 0);
#endif
PrivMutexCreate(&adapter->lock, 0);
@ -934,22 +954,32 @@ int AdapterLoraTest(void)
pthread_attr_t lora_gateway_attr = PTHREAD_ATTR_INITIALIZER;
lora_gateway_attr.priority = 20;
lora_gateway_attr.stacksize = 2048;
PrivTaskCreate(&lora_recv_data_task, &lora_gateway_attr, &LoraReceiveTask, (void *)adapter);
#else
pthread_attr_t lora_gateway_attr;
lora_gateway_attr.schedparam.sched_priority = 20;
lora_gateway_attr.stacksize = 2048;
char task_name_1[] = "adapter_lora_recv";
pthread_args_t args;
args.pthread_name = task_name_1;
args.arg = (void *)adapter;
PrivTaskCreate(&lora_recv_data_task, &lora_gateway_attr, &LoraReceiveTask, (void *)&args);
#endif
PrivTaskCreate(&lora_recv_data_task, &lora_gateway_attr, &LoraReceiveTask, (void *)adapter);
PrivTaskStartup(&lora_recv_data_task);
#ifdef ADD_NUTTX_FEATURES
lora_gateway_attr.priority = 19;
lora_gateway_attr.priority = 20;
PrivTaskCreate(&lora_gateway_task, &lora_gateway_attr, &LoraGatewayTask, (void *)adapter);
#else
lora_gateway_attr.schedparam.sched_priority = 19;
lora_gateway_attr.schedparam.sched_priority = 20;
char task_name_2[] = "adapter_lora_gateway";
args.pthread_name = task_name_2;
args.arg = (void *)adapter;
PrivTaskCreate(&lora_recv_data_task, &lora_gateway_attr, &LoraReceiveTask, (void *)&args);
#endif
PrivTaskCreate(&lora_gateway_task, &lora_gateway_attr, &LoraGatewayTask, (void *)adapter);
PrivTaskStartup(&lora_gateway_task);
#else //AS_LORA_CLIENT_ROLE
@ -957,22 +987,34 @@ int AdapterLoraTest(void)
pthread_attr_t lora_client_attr = PTHREAD_ATTR_INITIALIZER;
lora_client_attr.priority = 20;
lora_client_attr.stacksize = 2048;
PrivTaskCreate(&lora_recv_data_task, &lora_client_attr, &LoraReceiveTask, (void *)adapter);
#else
pthread_attr_t lora_client_attr;
lora_client_attr.schedparam.sched_priority = 20;
lora_client_attr.stacksize = 2048;
char task_name_1[] = "adapter_lora_recv";
pthread_args_t args;
args.pthread_name = task_name_1;
args.arg = (void *)adapter;
PrivTaskCreate(&lora_recv_data_task, &lora_client_attr, &LoraReceiveTask, (void *)&args);
#endif
PrivTaskCreate(&lora_recv_data_task, &lora_client_attr, &LoraReceiveTask, (void *)adapter);
PrivTaskStartup(&lora_recv_data_task);
#ifdef ADD_NUTTX_FEATURES
lora_client_attr.priority = 19;
lora_client_attr.priority = 20;
PrivTaskCreate(&lora_client_data_task, &lora_client_attr, &LoraClientDataTask, (void *)adapter);
#else
lora_client_attr.schedparam.sched_priority = 19;
lora_client_attr.schedparam.sched_priority = 20;
char task_name_2[] = "adapter_lora_client";
args.pthread_name = task_name_2;
args.arg = (void *)adapter;
PrivTaskCreate(&lora_client_data_task, &lora_client_attr, &LoraClientDataTask, (void *)&args);
#endif
//create lora client task
PrivTaskCreate(&lora_client_data_task, &lora_client_attr, &LoraClientDataTask, (void *)adapter);
PrivTaskStartup(&lora_client_data_task);
#endif

View File

@ -67,7 +67,7 @@ typedef enum
struct ControlDevice
{
char *dev_name;
char dev_name[20];
int status;
//to do

View File

@ -322,7 +322,12 @@ int ControlProtocolOpenDef(struct ControlProtocol *control_protocol)
attr.schedparam.sched_priority = 19;
attr.stacksize = 2048;
PrivTaskCreate(&recv_plc_data_task, &attr, &ReceivePlcDataTask, control_protocol);
char task_name[] = "control_recv_data";
pthread_args_t args;
args.pthread_name = task_name;
args.arg = (void *)control_protocol;
PrivTaskCreate(&recv_plc_data_task, &attr, &ReceivePlcDataTask, (void *)&args);
PrivTaskStartup(&recv_plc_data_task);
}

View File

@ -76,7 +76,7 @@ void Uart485Init(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8
ioctl_cfg.args = &pin_param;
PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg);
uart_fd = open(CONTROL_FRAMEWORK_UART_DEV, O_RDWR);
uart_fd = PrivOpen(CONTROL_FRAMEWORK_UART_DEV, O_RDWR);
if (uart_fd < 0) {
printf("open fd error %d\n", uart_fd);
return;
@ -190,3 +190,33 @@ int SerialRead(uint8_t *read_data, int length)
return data_size;
#endif
}
int ControlFileDataStore(uint8 *data, int data_length)
{
int data_file_fd = -1;
struct stat data_file_status;
int i = 0;
//Step1 : open data file from SD card or other store device
data_file_fd = PrivOpen(FILE_NAME, O_RDONLY);
if (data_file_fd < 0) {
printf("Open data file %s failed\n", FILE_NAME);
PrivClose(data_file_fd);
return -1;
}
if (0 != fstat(data_file_fd, &data_file_status)) {
printf("Get data file information failed!\n");
PrivClose(data_file_fd);
return -1;
}
lseek(data_file_fd, data_file_status.st_size, SEEK_SET);
//Step2 : write data to file in SD card or other store device
FatfsPrintf(GetFileDescriptor(data_file_fd), data, data_length);
//Step3 : close data file from SD card or other store device
PrivClose(data_file_fd);
return 0;
}

View File

@ -48,6 +48,9 @@ extern "C" {
#endif
#endif
#define FILE_NAME "plc_data.csv"
extern void FatfsPrintf(struct FileDescriptor *fdp, const void *src, size_t len);
/*Control Framework Socket Init*/
void SocketInit(char *ip, char *mask, char *gw);
@ -60,6 +63,9 @@ void SerialWrite(uint8_t *write_data, int length);
/*Control Framework Serial Read*/
int SerialRead(uint8_t *read_data, int length);
/*Control Framework Store data in SD Card*/
int ControlFileDataStore(uint8 *data, int data_length);
#ifdef __cplusplus
}
#endif

View File

@ -26,6 +26,7 @@ extern int AdapterEthercatInit(void);
extern int AdapterZigbeeInit(void);
extern int AdapterLoraInit(void);
extern int Bmp180AltitudeInit(void);
extern int D124VoiceInit(void);
extern int Hs300xTemperatureInit(void);
extern int Hs300xHumidityInit(void);
@ -83,6 +84,10 @@ static struct InitDesc framework[] =
static struct InitDesc sensor_desc[] =
{
#ifdef SENSOR_DEVICE_BMP180
{ "bmp180_altitude", Bmp180AltitudeInit},
#endif
#ifdef SENSOR_DEVICE_D124
{ "d124_voice", D124VoiceInit },
#endif

View File

@ -9,7 +9,7 @@ config KPU_DEV_DRIVER
config CAMERA_DEV_DRIVER
string "Set camera dev path for kpu"
default "/dev/ov2640"
default "/dev/camera_dev"
config KPU_LCD_DEV_DRIVER
string "Set lcd dev path for kpu"

View File

@ -69,12 +69,28 @@ static int SensorDeviceRead(struct SensorDevice *sdev, size_t len)
return 0;
}
/**
* @description: Write sensor device
* @param sdev - sensor device pointer
* @param buf - the buffer of write data
* @param len - the length of the write data
* @return success: 0 , failure: -1
*/
static int SensorDeviceWrite(struct SensorDevice *sdev, const void *buf, size_t len)
{
//Read i2c device data from i2c device address
if (PrivWrite(sdev->fd, buf, len) < 0)
return -1;
return 0;
}
static struct SensorDone done =
{
SensorDeviceOpen,
NULL,
SensorDeviceRead,
NULL,
SensorDeviceWrite,
NULL,
};
@ -109,7 +125,8 @@ static int32_t ReadHumidity(struct SensorQuantity *quant)
float result = 0.0;
if (quant->sdev->done->read != NULL) {
if (quant->sdev->status == SENSOR_DEVICE_PASSIVE) {
quant->sdev->done->read(quant->sdev, 4);
quant->sdev->done->write(quant->sdev, NONE, 0);
PrivTaskDelay(50);
quant->sdev->done->read(quant->sdev, 4); /* It takes two reads to get the data right */
result = ((quant->sdev->buffer[0] << 8 | quant->sdev->buffer[1] ) & 0x3fff) * 100.0 / ( (1 << 14) - 1);

View File

@ -80,7 +80,12 @@ static int SensorDeviceOpen(struct SensorDevice *sdev)
result = PrivIoctl(sdev->fd, OPE_INT, &cfg);
PrivTaskCreate(&active_task_id, NULL, &ReadTask, sdev);
char task_name[] = "ps5308_recv_data";
pthread_args_t args;
args.pthread_name = task_name;
args.arg = (void *)sdev;
PrivTaskCreate(&active_task_id, NULL, &ReadTask, (void *)&args);
PrivTaskStartup(&active_task_id);
return result;

View File

@ -68,12 +68,28 @@ static int SensorDeviceRead(struct SensorDevice *sdev, size_t len)
return 0;
}
/**
* @description: Write sensor device
* @param sdev - sensor device pointer
* @param buf - the buffer of write data
* @param len - the length of the write data
* @return success: 0 , failure: -1
*/
static int SensorDeviceWrite(struct SensorDevice *sdev, const void *buf, size_t len)
{
//Read i2c device data from i2c device address
if (PrivWrite(sdev->fd, buf, len) < 0)
return -1;
return 0;
}
static struct SensorDone done =
{
SensorDeviceOpen,
NULL,
SensorDeviceRead,
NULL,
SensorDeviceWrite,
NULL,
};
@ -108,7 +124,7 @@ static int32_t ReadTemperature(struct SensorQuantity *quant)
float result;
if (quant->sdev->done->read != NULL) {
if (quant->sdev->status == SENSOR_DEVICE_PASSIVE) {
quant->sdev->done->read(quant->sdev, 4);
quant->sdev->done->write(quant->sdev, NONE, 0);
PrivTaskDelay(50);
quant->sdev->done->read(quant->sdev, 4); /* It takes two reads to get the data right */
result = ((quant->sdev->buffer[2] << 8 | quant->sdev->buffer[3]) >> 2) * 165.0 /( (1 << 14) - 1) - 40.0;

View File

@ -116,7 +116,12 @@ static int SensorDeviceOpen(struct SensorDevice *sdev)
attr.schedparam.sched_priority = 20;
attr.stacksize = 2048;
PrivTaskCreate(&active_task_id, &attr, &ReadTask, sdev);
char task_name[] = "d124_recv_data";
pthread_args_t args;
args.pthread_name = task_name;
args.arg = (void *)sdev;
PrivTaskCreate(&active_task_id, &attr, &ReadTask, (void *)&args);
PrivTaskStartup(&active_task_id);
return result;

View File

@ -163,6 +163,37 @@ int PrivTimerModify(timer_t timerid, int flags, const struct itimerspec *restric
/*********************fs**************************/
#ifdef FS_VFS
/************************Files Posix Transform***********************/
int PrivLseek(int fd, off_t offset, int whence)
{
return lseek(fd, offset, whence);
}
int PrivFsync(int fd)
{
return fsync(fd);
}
int PrivFstat(int fd, struct stat *buf)
{
return fstat(fd, buf);
}
int PrivStat(const char *path, struct stat *buf)
{
return stat(path, buf);
}
int PrivUnlink(const char *path)
{
return unlink(path);
}
char *PrivGetcwd(char *buf, size_t size)
{
return getcwd(buf, size);
}
/************************Driver Posix Transform***********************/
int PrivOpen(const char *path, int flags, ...)
{
@ -206,7 +237,7 @@ static int PrivLcdIoctl(int fd, int cmd, void *args)
int PrivIoctl(int fd, int cmd, void *args)
{
int ret;
int ret = -ERROR;
struct PrivIoctlCfg *ioctl_cfg = (struct PrivIoctlCfg *)args;
switch (ioctl_cfg->ioctl_driver_type)
{

View File

@ -43,6 +43,9 @@ extern "C" {
#define NAME_NUM_MAX 32
#define LINKLIST_FLAG_FIFO 0x00
#define LINKLIST_FLAG_PRIO 0x01
#ifndef EVENT_AND
#define EVENT_AND (1 << 0)
#endif
@ -169,6 +172,8 @@ struct SerialDataCfg
uint16_t serial_buffer_size;
int32 serial_timeout;
int (*dev_recv_callback) (void *dev, size_t length);
uint8_t is_ext_uart;
uint8_t ext_uart_no;
enum ExtSerialPortConfigure port_configure;
@ -425,6 +430,13 @@ int PrivTaskDelay(int32_t ms);
int PrivUserTaskSearch(void);
uint32_t PrivGetTickTime();
/*********************Files**************************/
int PrivLseek(int fd, off_t offset, int whence);
int PrivFsync(int fd);
int PrivFstat(int fd, struct stat *buf);
int PrivStat(const char *path, struct stat *buf);
int PrivUnlink(const char *path);
char *PrivGetcwd(char *buf, size_t size);
/*********************driver*************************/
int PrivOpen(const char *path, int flags, ...);

View File

@ -72,6 +72,11 @@ extern "C" {
typedef int pid_t;
// typedef int pthread_mutex_t ;
typedef struct pthread_args
{
void *arg;
const char *pthread_name;
}pthread_args_t;
/* scheduling algorithms */
#define SCHED_OTHER 0

View File

@ -29,28 +29,40 @@
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg)
{
int ret ;
int pid ;
int ret;
int pid;
char task_name[32] = {0};
static int utask_id = 0;
UtaskType task ;
UtaskType task;
pthread_args_t *pthread_args = (pthread_args_t *)arg;
if (NULL == attr) {
task.prio = KTASK_PRIORITY_MAX / 2;
task.stack_size = 4096 ;
task.stack_size = 4096;
} else {
task.prio = attr->schedparam.sched_priority ;
task.stack_size = attr->stacksize ;
task.prio = attr->schedparam.sched_priority;
task.stack_size = attr->stacksize;
}
task.func_entry = start_routine;
if (NULL == pthread_args) {
task.func_param = NULL;
snprintf(task_name, sizeof(task_name) - 1, "utask%02d", utask_id++);
} else {
task.func_param = pthread_args->arg;
if (NULL == pthread_args->pthread_name) {
snprintf(task_name, sizeof(task_name) - 1, "utask%02d", utask_id++);
} else {
snprintf(task_name, sizeof(task_name) - 1, pthread_args->pthread_name);
}
}
task.func_entry = start_routine ;
task.func_param = arg;
snprintf(task_name, sizeof(task_name) - 1, "utask%02d",utask_id++);
memcpy(task.name , task_name, sizeof(task_name) - 1);
pid = UserTaskCreate(task);
if (pid < 0)
return -1 ;
return -1;
ret = UserTaskStartup(pid);
*thread = (pthread_t)(long)pid;

View File

@ -25,8 +25,11 @@
#include "include/semaphore.h"
#include "include/pthread.h"
static sem_t timer_sem;
static pthread_t timer_task;
#define TIMER_NUM 20
static sem_t timer_sem[TIMER_NUM];
static pthread_t timer_task[TIMER_NUM];
static char timer_idx[TIMER_NUM];
struct timer_func {
union sigval value;
@ -34,16 +37,17 @@ struct timer_func {
void (* user_timer_function)(union sigval val);
};
struct timer_func g_timer_func;
struct timer_func g_timer_func[TIMER_NUM];
static void *timer_callback(void *args)
{
struct sigevent *evp = (struct sigevent *)args;
clockid_t clockid = *((clockid_t *)args);
while (1) {
if (g_timer_func.user_timer_function != NULL) {
if (0 == sem_timedwait(&timer_sem, NULL)) {
g_timer_func.user_timer_function(g_timer_func.value);
if (g_timer_func[clockid].user_timer_function != NULL) {
if (0 == sem_timedwait(&(timer_sem[clockid]), NULL)) {
g_timer_func[clockid].value.sival_ptr = &clockid;
g_timer_func[clockid].user_timer_function(g_timer_func[clockid].value);
}
}
}
@ -66,32 +70,39 @@ int timer_create(clockid_t clockid, struct sigevent * evp, timer_t * timerid)
}
memset(timer_name, 0, sizeof(timer_name));
snprintf(timer_name, sizeof(timer_name), "timer_%d", clockid);
snprintf(timer_name, sizeof(timer_name), "timer_%ld", clockid);
sem_init(&timer_sem, 0, 0);
sem_init(&(timer_sem[clockid]), 0, 0);
g_timer_func.value = evp->sigev_value;
g_timer_func.user_timer_function = evp->sigev_notify_function;
g_timer_func.timer_flags = *(int *)(evp->sigev_notify_attributes);
g_timer_func[clockid].value = evp->sigev_value;
g_timer_func[clockid].user_timer_function = evp->sigev_notify_function;
g_timer_func[clockid].timer_flags = *(int *)(evp->sigev_notify_attributes);
pthread_attr_t attr;
attr.schedparam.sched_priority = 22;
attr.stacksize = 2048;
pthread_create(&timer_task, &attr, &timer_callback, (void *)evp);
pthread_args_t args;
args.pthread_name = timer_name;
args.arg = &clockid;
timer_id = UserTimerCreate(timer_name, NULL, (void *)&timer_sem, 1000, g_timer_func.timer_flags);
pthread_create(&(timer_task[clockid]), &attr, &timer_callback, (void *)&args);
timer_id = UserTimerCreate(timer_name, NULL, (void *)&(timer_sem[clockid]), clockid, g_timer_func[clockid].timer_flags);
*timerid = timer_id;
return timer_id;
}
int timer_delete(timer_t timerid)
{
pthread_kill(timer_task, 0);
sem_t sem;
int timer_id = timerid;
pthread_kill(timer_task[timer_id], 0);
UserTimerQuitRun(timerid);
sem_destroy(&timer_sem);
sem = timer_sem[timer_id];
sem_destroy(&sem);
return 0;
}

View File

@ -14,4 +14,6 @@ menu "app lib"
source "$APP_DIR/lib/lvgl/Kconfig"
source "$APP_DIR/lib/embedded_database/Kconfig"
source "$APP_DIR/lib/lorawan/Kconfig"
source "$APP_DIR/lib/mqtt/Kconfig"
source "$APP_DIR/lib/SQLite/Kconfig"
endmenu

View File

@ -18,4 +18,12 @@ ifeq ($(CONFIG_LIB_USING_LORAWAN),y)
SRC_DIR += lorawan
endif
ifeq ($(CONFIG_TOOL_USING_MQTT),y)
SRC_DIR += mqtt
endif
ifeq ($(CONFIG_LIB_USING_SQLITE),y)
SRC_DIR += SQLite
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,21 @@
menu "lib using SQLite"
menuconfig LIB_USING_SQLITE
bool "Using SQLite lib"
default n
if LIB_USING_SQLITE
config LIB_SQLITE_EXAMPLE
bool "Enable SQLite example"
default y
config LIB_SQLITE_SQL_MAX_LEN
int "Set SQL statements max length"
default 1024
config LIB_SQLITE_DB_NAME_MAX_LEN
int "Set SQL database filename fullpath max length"
default 64
endif
endmenu

View File

@ -0,0 +1,10 @@
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
SRC_FILES := sqlite3.c dbhelper.c
SRC_DIR := xizi_port
ifeq ($(CONFIG_LIB_SQLITE_EXAMPLE),y)
SRC_FILES += student_dao.c
endif
include $(KERNEL_ROOT)/compiler.mk
endif

View File

@ -0,0 +1,400 @@
# SQLite for RT-Thread
## 简介
SQLite 是一个小型,快速,独立的高可靠性全功能 SQL 数据库引擎。SQLite 是全世界部署最广泛的 SQL 数据库引擎。它内置在几乎所有的移动电话、大多数计算机以及部分嵌入式设备中,并被捆绑在人们每天使用的无数其他应用程序中。
## 文件说明
| 名称 | 说明 |
| ------------------------ | ---------------------------------------------------------------- |
| sqlite3.c | sqlite3源文件 |
| sqlite3.h | sqlite3头文件 |
| sqlite_config_rtthread.h | sqlite3在rt-thread上的配置文件 |
| rtthread_io_methods.c | rt-thread为sqlite提供的底层文件IO接口 |
| rtthread_mutex.c | rt-thread为sqlite提供的互斥量操作接口 |
| rtthread_vfs.c | rt-thread为sqlite提供的VFS(虚拟文件系统)接口 |
| xizi_io_methods.c | xizi为sqlite提供的底层文件IO接口 |
| xizi_mutex.c | xizi为sqlite提供的互斥量操作接口 |
| xizi_vfs.c | xizi为sqlite提供的VFS(虚拟文件系统)接口 |
| dbhelper.c | sqlite3操作接口封装简化应用 |
| dbhelper.h | dbhelper头文件向外部声明封装后的接口供用户调用 |
| student_dao.c | 简单的DAO层例程简单展示了对dbhelper的使用方法 |
| student_dao.h | 数据访问对象对外接口声明,线程可通过调用这些接口完成对该表的操作 |
## RT-Thread获取
在ENV中配置如下
```c
RT-Thread online packages --->
system packages --->
--- SQLite: a self-contained, high-reliability, embedded, full-featured, public-domain, SQL database engine.
(1024) SQL statements max length
[*] Enable example
```
配置项说明:
| 名称 | 说明 |
| ------------------------- | --------------------------------------------------- |
| SQL statements max length | SQL语句最大长度请根据实际业务需求设置。 |
| Enable example | 选择是否使能DAO层例程例程是模拟了学生成绩录入查询 |
## 依赖
- RT-Thread 3.X+
- DFS组件
## XiZi获取
在menuconfig中配置如下
```c
LIB_USING_SQLITE --->
[*] Enable SQLite example
(1024) Set SQL statements max length
(64) Set SQL database filename fullpath max length
```
配置项说明:
| 名称 | 说明 |
| -----------------------------| --------------------------------------------------- |
| Enable example | 选择是否使能DAO层例程例程是模拟了学生成绩录入查询 |
| SQL statements max length | SQL语句最大长度请根据实际业务需求设置。 |
| filename fullpath max length | SQL数据库文件名最大长度请根据实际业务需求设置。 |
## 依赖
- XiZi_IIoT
- shell线程栈不少于32KB
- TF卡驱动支持并挂载FATFS文件系统
## dbhelp接口说明
dbhelp是对sqlite3操作接口的封装目的是使用户更加简单地操作sqlite。
### 数据库文件完整路径
数据库文件的默认存放完整路径是"/rt.db"或"xiuos.db"用户可根据实际需求在dbhelper.h中修改。
```c
#define DB_NAME "/rt.db" 、"xiuos.db"
```
### 初始化
dbhelp初始化其中包含了sqlite的初始化及互斥量创建。用户无需再对数据库及锁初始化。
```c
int db_helper_init(void);
```
| 参数 | 说明 |
| --------- | ---------- |
| void | |
| 返回 | |
| RT_EOK | 初始化成功 |
| -RT_ERROR | 初始化失败 |
### 数据库创建
```c
int db_create_database(const char *sqlstr);
```
| 参数 | 说明 |
| ------ | --------------- |
| sqlstr | 创建表的SQL语句 |
| 返回 | |
| 0 | 成功 |
| 非0 | 失败 |
输入形参sqlstr应当是一条创建表的SQL语句
```c
const char *sql = "CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);";
return db_create_database(sql);
```
### 可进行数据绑定的非查询操作
用于非查询的操作可通过回调进行数据绑定db_nonquery_operator中开启了事务功能支持操作失败后回滚。
```c
int db_nonquery_operator(const char *sqlstr, int (*bind)(sqlite3_stmt *, int index, void *arg), void *param);
```
| 参数 | 说明 |
| ------ | ------------------------------------------------------------ |
| sqlstr | 非查询类SQL语句如果有多个SQL语句要执行请用;将SQL语句分开 |
| bind | 数据绑定回调 |
| param | 在内部将赋值给bind的输入参数void *arg |
| 返回 | |
| 0 | 成功 |
| 非0 | 失败 |
注:该接口请勿用于查询类操作。
bind需要用户实现
| 参数 | 说明 |
| ---------------------- | -------------------------------------------------------------------- |
| stmt | sqlite3_stmt预备语句对象 |
| index | 如果有多条SQL语句要执行index表示第index条SQL语句注意index从1开始 |
| arg | 即db_nonquery_operator的四三个形参void *param |
| 返回 | |
| SQLITE_OK或SQLITE_DONE | 成功 |
| 其他 | 失败(如果用户提供的bind返回失败db_nonquery_operator将执行回滚操作) |
普通SQL语句在执行时是需要解析、编译、执行的而sqlite3_stmt结构是已经通过sqlite3_prepare函数对sql语句解析和编译了的而在SQL语句中在要绑定数据的位置放置?作为占位符即可通过数据绑定接口sqlite3_bind_*(此处*为通配符取值为intdoubletext等详情请见sqlite文档)。这种在批量操作时由于绕开了解释编译的过程直接在sqlite3_stmt的基础上对绑定值进行修改因而会使整体操作效率势大大提升。具体应用请见[student_dao.c](./student_dao.c)
### 带可变参数的非查询操作
```c
int db_nonquery_by_varpara(const char *sql, const char *fmt, ...);
```
| 参数 | 说明 |
| ---- | ----------------------------------------------------------------- |
| sql | 非查询类SQL语句 |
| fmt | 格式符配合后面的可变参数使用用法类似printf只支持%d,%f,%s,%x |
| ... | 可变形参 |
| 返回 | |
| 0 | 成功 |
| 非0 | 失败 |
注:该接口请勿用于查询类操作。
例:
```c
int student_del(int id)
{
return db_nonquery_by_varpara("delete from student where id=?;", "%d", id);
}
```
SQL语句"delete from student where id=?;"中,“?”为占位符id将会按照%d的格式被绑定到通过对前述SQL语句解释编译后的sqlite3_stmt中。
### 开启事务的非查询操作
db_nonquery_transaction开启了事务功能支持操作失败后回滚。
```c
int db_nonquery_transaction(int (*exec_sqls)(sqlite3 *db, void *arg), void *arg);
```
| 参数 | 说明 |
| --------- | ---------------------------------------------- |
| exec_sqls | SQL执行回调 |
| arg | 内部赋值给exec_sqls的void *arg形参作为输入参数 |
| 返回 | |
| 0 | 成功 |
| 非0 | 失败 |
exec_sqls
| 参数 | 说明 |
| ---------------------- | ---------------------------------------------------------------------------- |
| db | 数据库描述符 |
| arg | 来自于db_nonquery_transaction的形参void *arg |
| 返回 | |
| SQLITE_OK或SQLITE_DONE | 成功 |
| 其他 | 失败(如果用户提供的exec_sqls返回失败db_nonquery_transaction将执行回滚操作) |
注:该接口请勿用于查询类操作。
db_nonquery_transaction的自由度比较大内部开启事务后就开始执行exec_sqls用户可在exec_sqls通过调用SQLite的接口进行相关的数据库操作。执行完exec_sqls后提交事务。如果有失败情况会回滚。
### 带变参的查询操作
用户可通过sql语句及变参进行查询操作
```c
int db_query_by_varpara(const char *sql, int (*create)(sqlite3_stmt *stmt, void *arg), void *arg, const char *fmt, ...);
```
| 参数 | 说明 |
| ---------------------- | ----------------------------------------------------------------- |
| sql | SQL语句 |
| create | 创建用来接收查询结果的数据对象 |
| arg | 将赋值给create的void *arg作为输入参数 |
| fmt | 格式符配合后面的可变参数使用用法类似printf只支持%d,%f,%s,%x |
| ... | 变参 |
| 返回creat!=NULL | |
| 返回create的返回值 | |
| 返回create==NULL时 | |
| 0 | |
create回调
| 参数 | 说明 |
| --------------------------------- | ---------------------------------------------------- |
| stmt | sqlite3_stmt预备语句对象 |
| arg | 接收来由db_query_by_varpara的void *arg传递进来的形参 |
| 返回 | |
| 返回值将被db_query_by_varpara返回 | |
用户可通过调用在通过调用db_stmt_get_intdb_stmt_get_text等接口配合sqlite3_step获取查询结果回调接收不定数量的条目时请注意内存用量或在查询前先通过db_query_count_result确定条符合条件的条目数量。
### 获取符合条件的结果数量
调用此接口返回结果条目数量注意如的SQL语句应为SELECT COUNT为前缀的查询数量的语句。接口中只会获取第一行第一列。
```c
int db_query_count_result(const char *sql);
```
| 参数 | 说明 |
| ------ | ----------------------------------------------------------------- |
| sql | SQL语句仅限查询数量语句select count(*) from sqlite_master |
| 返回 | |
| 非负值 | 符合条件的条目的数量 |
| 负数 | 查询失败 |
例如,查询数据库中表的数量:
```c
nums = db_query_count_result("select count(*) from sqlite_master where type = 'table';");
```
### 在查询结果中获取blob型数据
在查询时获取blob类型数据blob类型在SQLite 中指二进制大对象,完全根据其输入值存储。
```c
int db_stmt_get_blob(sqlite3_stmt *stmt, int index, unsigned char *out)
```
| 参数 | 说明 |
| ------ | ---------------------------------------------- |
| stmt | sqlite3_stmt预备语句对象 |
| index | 数据索引 |
| out | 输出参数,获取到的数据将存入该指针指向的地址中 |
| 返回 | |
| 非负值 | 获取的数据长度 |
| 负数 | 查询失败 | |
### 在查询结果中获取text型数据
在查询时获取文本类型数据text类型值是一个文本字符串。
```c
int db_stmt_get_text(sqlite3_stmt *stmt, int index, char *out)
```
| 参数 | 说明 |
| ------ | ---------------------------------------------- |
| stmt | sqlite3_stmt预备语句对象 |
| index | 数据索引 |
| out | 输出参数,获取到的数据将存入该指针指向的地址中 |
| 返回 | |
| 非负值 | 获取的数据长度 |
| 负数 | 查询失败 |
### 在查询结果中获取int型数据
在查询时获取整型数据
```c
int db_stmt_get_int(sqlite3_stmt *stmt, int index);
```
| 参数 | 说明 |
| --------- | ------------------------ |
| stmt | sqlite3_stmt预备语句对象 |
| index | 数据索引 |
| 返回 | |
| int型变量 | 查询结果 |
### 在查询结果中获取double型数据
在查询时获取双精度数据
```c
double db_stmt_get_double(sqlite3_stmt *stmt, int index)
```
| 参数 | 说明 |
| ------------ | ------------------------ |
| stmt | sqlite3_stmt预备语句对象 |
| index | 数据索引 |
| 返回 | |
| double型变量 | 查询结果 |
### 通过表面查询表是否存在
可通过输入表名称来确定该表是否存在。
```c
int db_table_is_exist(const char *tbl_name)
```
| 参数 | 说明 |
| -------- | -------- |
| tbl_name | 表名称 |
| 返回 | |
| 正值 | 已存在 |
| 0 | 不存在 |
| 负值 | 查询错误 |
### 设置数据库文件名
该文件名应为绝对路径,请使用.db作为扩展名。在对单数据库的使用场景中可用来设置数据库名称。多线程多数据库请使用int db_connect(char *name)和int db_connect(char *name)。
```c
int db_set_name(char *name)
```
| 参数 | 说明 |
| ------ | ---------------------- |
| name | 文件名(完整绝对路径) |
| 返回 | |
| RT_EOK | 设置成功 |
| <0 | 设置失败 |
### 读取当前数据库文件名
```c
const char *db_get_name(void)
```
| 参数 | 说明 |
| ------ | -------- |
| 返回 | |
| 字符串 | 设置成功 |
| <0 | 设置失败 |
### 连接数据库
该文件名应为绝对路径,请使用.db作为扩展名该方法将会设置要打开的数据库文件名并加锁操作完毕后请调用 int db_disconnect(char *name) 解锁,以便以其他线程操作。适用于多线程操作多数据库场景。如果是多线程,单数据库场景请使用 int db_set_name(char *name) 来修改数据库名称或直接操作数据库(即使用默认数据库名称)。
```c
int db_connect(char *name)
```
| 参数 | 说明 |
| ------ | ---------------------- |
| name | 文件名(完整绝对路径) |
| 返回 | |
| RT_EOK | 设置成功 |
| <0 | 设置失败 |
### 断开数据库连接
断开数据库连接,数据库名称将恢复为默认,并释放互斥量。
```c
int db_connect(char *name)
```
| 参数 | 说明 |
| ------ | ---------------------- |
| name | 文件名(完整绝对路径) |
| 返回 | |
| RT_EOK | 设置成功 |
| <0 | 设置失败 |
## DAO层实例
这是一个学生成绩录入查询的DAO(Data Access Object)层示例可在menuconfig中配置使能。通过此例程可更加详细的了解dbhelper的使用方法。例程配置使能后可通过命令行实现对student表的操作具体命令如下
说明:以下命令中被[]包裹的为必填参数,<>包裹的为非必填参数
### stu add \<num\>
增加\<num\>个学生信息。学生名称和成绩为一定范围内的生成的随机值。如果仅输入```stu add```则默认插入一条学生信息。
### stu del <id>
删除主键为\<id\>的学生成绩信息,如果仅输入```stu del```则删除全部学生信息。例如:
```
stu del 1
```
删除主键为1的学生成绩信息。
### stu update [id] [name] [score]
将主键为[id]的学生的姓名及分数分别修改为[name]和[score]。例如:
```
stu update 1 lizhen9880 100
```
表示将主键为1的条目中学生姓名修改为lizhen9880分数修改为100。
### stu \<id\>
根据id查询学生成绩并打印id为该表自增主键具备唯一性。根据主键查询速度是非常快的。
仅输入 ```stu``` 会查询出所有学生名称成绩并打印,例:
```
stu 3
```
将查询出主键为3的学生成绩信息并打印。
### stu score [ls] [hs] \<-d|-a\>
查询并打印分数在[ls]到[hs]之间的学生成绩单。<br/>
[ls]: 最低分 <br/>
[hs]: 最高分 <br/>
\<-d|-a\>: -d 降序;-a 升序;默认升序
例如:
```
stu score 60 100 -d
```
按照```降序```打印出成绩及格学生的成绩单。
```
stu score 60 100
```
按照```升序```打印出成绩及格学生的成绩单。
## 注意事项
- SQLite资源占用RAM:250KB+,ROM:310KB+,所以需要有较充足的硬件资源。
- 根据应用场景创建合理的表结构,会提高操作效率。
- 根据应用场合理使用SQL语句如查询条件插入方式等。
- 如涉及到多表操作或联表查询最好使用PowerDesigner等工具合理设计表。
## 相关链接
Env工具获取[https://www.rt-thread.org/page/download.html](https://www.rt-thread.org/page/download.html)
Env工具使用[https://www.rt-thread.org/document/site/zh/5chapters/01-chapter_env_manual/#env](https://www.rt-thread.org/document/site/zh/5chapters/01-chapter_env_manual/#env)
SQLite官方文档[https://www.sqlite.org/docs.html](https://www.sqlite.org/docs.html)
## Q&F
联系人: RT-Thread官方 | [lizhen9880](https://github.com/lizhen9880)<br/>
邮箱:[package_team@rt-thread.com](package_team@rt-thread.com) | [lizhen9880@126.com](lizhen9880@126.com)

View File

@ -0,0 +1,12 @@
from building import *
cwd = GetCurrentDir()
src = ['sqlite3.c']
src += ['dbhelper.c']
if GetDepend('PKG_SQLITE_DAO_EXAMPLE'):
src += Glob('student_dao.c')
CPPPATH = [cwd]
group = DefineGroup('sqlite', src, depend = ['RT_USING_DFS', 'PKG_USING_SQLITE'], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,770 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-06 lizhen9880 first version
*/
/**
* @file dbhelper.c
* @brief support SQLite api function for applications in XiUOS
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023-10-25
*/
/*************************************************
File name: dbhelper.c
Description: support SQLite api function for applications in XiUOS
Others:
History:
1. Date: 2023-10-25
Author: AIIT XUOS Lab
Modification:
1add XiUOS function.
*************************************************/
#include <stdio.h>
#include <string.h>
#include <transform.h>
#ifdef ADD_XIZI_FEATURES
#include <sqlite_config_xiuos.h>
#endif
#ifdef ADD_RTTHREAD_FEATURES
#include <rtthread.h>
#endif
#include <ctype.h>
#include "dbhelper.h"
#define DBG_ENABLE
#define DBG_SECTION_NAME "app.dbhelper"
#define DBG_LEVEL DBG_INFO
#define DBG_COLOR
#ifdef ADD_RTTHREAD_FEATURES
#include <rtdbg.h>
#endif
#if PKG_SQLITE_DB_NAME_MAX_LEN < 8
#error "the database name length is too short"
#endif
#ifdef ADD_RTTHREAD_FEATURES
#define DEFAULT_DB_NAME "/rt.db"
#endif
#ifdef ADD_XIZI_FEATURES
#define DEFAULT_DB_NAME "xiuos.db"
#endif
#ifdef ADD_RTTHREAD_FEATURES
static rt_mutex_t db_mutex_lock = RT_NULL;
#endif
#ifdef ADD_XIZI_FEATURES
static pthread_mutex_t db_mutex_lock;
#endif
static char db_name[PKG_SQLITE_DB_NAME_MAX_LEN + 1] = DEFAULT_DB_NAME;
/**
* This function will initialize SQLite3 create a mutex as a lock.
*/
#ifdef ADD_RTTHREAD_FEATURES
int db_helper_init(void)
{
sqlite3_initialize();
if (db_mutex_lock == RT_NULL)
{
db_mutex_lock = rt_mutex_create("dbmtx", RT_IPC_FLAG_FIFO);
}
if (db_mutex_lock == RT_NULL)
{
LOG_E("rt_mutex_create dbmtx failed!\n");
return -RT_ERROR;
}
return RT_EOK;
}
INIT_APP_EXPORT(db_helper_init);
#endif
#ifdef ADD_XIZI_FEATURES
int db_helper_init(void)
{
int ret = 0;
sqlite3_initialize();
ret = PrivMutexCreate(&db_mutex_lock, 0);
if (ret < 0)
{
printf("mutex_create dbmtx failed!\n");
return -1;
}
return 0;
}
PRIV_SHELL_CMD_FUNCTION(db_helper_init, initialize SQLite3 and create a mutex, PRIV_SHELL_CMD_FUNC_ATTR);
#endif
/**
* This function will create a database.
*
* @param sqlstr should be a SQL CREATE TABLE statements.
* @return the result of sql execution.
*/
int db_create_database(const char *sqlstr)
{
return db_nonquery_operator(sqlstr, 0, 0);
}
static int db_bind_by_var(sqlite3_stmt *stmt, const char *fmt, va_list args)
{
int len, npara = 1;
int ret = SQLITE_OK;
if (fmt == NULL)
{
return ret;
}
for (; *fmt; ++fmt)
{
if (*fmt != '%')
{
continue;
}
++fmt;
/* get length */
len = 0;
while (isdigit(*fmt))
{
len = len * 10 + (*fmt - '0');
++fmt;
}
switch (*fmt)
{
case 'd':
ret = sqlite3_bind_int(stmt, npara, va_arg(args, int));
break;
case 'f':
ret = sqlite3_bind_double(stmt, npara, va_arg(args, double));
break;
case 's':
{
char *str = va_arg(args, char *);
ret = sqlite3_bind_text(stmt, npara, str, strlen(str), NULL);
}
break;
case 'x':
{
char *pdata;
pdata = va_arg(args, char *);
ret = sqlite3_bind_blob(stmt, npara, pdata, len, NULL);
}
break;
default:
ret = SQLITE_ERROR;
break;
}
++npara;
if (ret)
return ret;
}
return ret;
}
/**
* This function will be used for the SELECT operating.The additional arguments
* following format are formatted and inserted in the resulting string replacing
* their respective specifiers.
*
* @param sql the SQL statements.
* @param create the callback function supported by user.
* create@param stmt the SQL statement after preparing.
* create@param arg the input parameter from 'db_query_by_varpara' arg.
* create@return rule:SQLITE_OK:success,others:fail
* @param arg the parameter for the callback "create".
* @param fmt the args format.such as %s string,%d int.
* @param ... the additional arguments
* @return =SQLITE_OK:success, others:fail.
*/
int db_query_by_varpara(const char *sql, int (*create)(sqlite3_stmt *stmt, void *arg), void *arg, const char *fmt, ...)
{
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
if (sql == NULL)
{
return SQLITE_ERROR;
}
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_take(db_mutex_lock, RT_WAITING_FOREVER);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexObtain(&db_mutex_lock);
#endif
int rc = sqlite3_open(db_name, &db);
if (rc != SQLITE_OK)
{
printf("open database failed,rc=%d", rc);
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
return rc;
}
rc = sqlite3_prepare(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
printf("database prepare fail,rc=%d", rc);
goto __db_exec_fail;
}
if (fmt)
{
va_list args;
va_start(args, fmt);
rc = db_bind_by_var(stmt, fmt, args);
va_end(args);
if (rc)
{
printf("database bind fail,rc=%d", rc);
goto __db_exec_fail;
}
}
if (create)
{
rc = (*create)(stmt, arg);
}
else
{
rc = (sqlite3_step(stmt), 0);
}
sqlite3_finalize(stmt);
goto __db_exec_ok;
__db_exec_fail:
printf("db operator failed,rc=%d", rc);
__db_exec_ok:
sqlite3_close(db);
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
return rc;
}
/**
* This function will be used for the operating that is not SELECT.It support executing multiple
* SQL statements.
*
* @param sqlstr the SQL statements strings.if there are more than one
* statements in the sqlstr to execute,separate them by a semicolon(;).
* @param bind the callback function supported by user.bind data and call the sqlite3_step function.
* bind@param stmt the SQL statement after preparing.
* bind@param index the index of SQL statements strings.
* bind@param param the parameter from 'db_nonquery_operator' arg.
* bind@return SQLITE_OK or SQLITE_DONE:success,others:fail
* @param param the parameter for the callback "bind".
* @return =SQLITE_OK:success, others:fail.
*/
int db_nonquery_operator(const char *sqlstr, int (*bind)(sqlite3_stmt *stmt, int index, void *param), void *param)
{
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
int index = 0, offset = 0, n = 0;
if (sqlstr == NULL)
{
return SQLITE_ERROR;
}
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_take(db_mutex_lock, RT_WAITING_FOREVER);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexObtain(&db_mutex_lock);
#endif
int rc = sqlite3_open(db_name, &db);
if (rc != SQLITE_OK)
{
printf("open database failed,rc=%d", rc);
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
return rc;
}
rc = sqlite3_exec(db, "begin transaction", 0, 0, NULL);
if (rc != SQLITE_OK)
{
printf("begin transaction:ret=%d", rc);
goto __db_begin_fail;
}
char sql[DB_SQL_MAX_LEN];
while (sqlstr[index] != 0)
{
offset = 0;
do
{
if (offset >= DB_SQL_MAX_LEN)
{
printf("sql is too long,(%d)", offset);
rc = SQLITE_ERROR;
goto __db_exec_fail;
}
if ((sqlstr[index] != ';') && (sqlstr[index] != 0))
{
sql[offset++] = sqlstr[index++];
}
else
{
sql[offset] = '\0';
if (sqlstr[index] == ';')
{
index++;
}
n++;
break;
}
} while (1);
rc = sqlite3_prepare(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
printf("prepare error,rc=%d", rc);
goto __db_exec_fail;
}
if (bind)
{
rc = (*bind)(stmt, n, param);
}
else
{
rc = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
if ((rc != SQLITE_OK) && (rc != SQLITE_DONE))
{
printf("bind failed");
goto __db_exec_fail;
}
}
rc = sqlite3_exec(db, "commit transaction", 0, 0, NULL);
if (rc)
{
printf("commit transaction:%d", rc);
goto __db_exec_fail;
}
goto __db_exec_ok;
__db_exec_fail:
if (sqlite3_exec(db, "rollback transaction", 0, 0, NULL))
{
printf("rollback transaction error");
}
__db_begin_fail:
printf("db operator failed,rc=%d", rc);
__db_exec_ok:
sqlite3_close(db);
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
return rc;
}
/**
* This function will be used for the operating that is not SELECT.The additional
* arguments following format are formatted and inserted in the resulting string
* replacing their respective specifiers.
*
* @param sql the SQL statement.
* @param fmt the args format.such as %s string,%d int.
* @param ... the additional arguments
* @return =SQLITE_OK:success, others:fail.
*/
int db_nonquery_by_varpara(const char *sql, const char *fmt, ...)
{
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
if (sql == NULL)
{
return SQLITE_ERROR;
}
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_take(db_mutex_lock, RT_WAITING_FOREVER);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexObtain(&db_mutex_lock);
#endif
int rc = sqlite3_open(db_name, &db);
if (rc != SQLITE_OK)
{
printf("open database failed,rc=%d\n", rc);
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
return rc;
}
printf("sql:%s", sql);
rc = sqlite3_prepare(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
printf("prepare error,rc=%d", rc);
goto __db_exec_fail;
}
if (fmt)
{
va_list args;
va_start(args, fmt);
rc = db_bind_by_var(stmt, fmt, args);
va_end(args);
if (rc)
{
goto __db_exec_fail;
}
}
rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
if ((rc != SQLITE_OK) && (rc != SQLITE_DONE))
{
printf("bind error,rc=%d", rc);
goto __db_exec_fail;
}
rc = SQLITE_OK;
goto __db_exec_ok;
__db_exec_fail:
printf("db operator failed,rc=%d", rc);
__db_exec_ok:
sqlite3_close(db);
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
return rc;
}
/**
* This function will be used for the transaction that is not SELECT.
*
* @param exec_sqls the callback function of executing SQL statements.
* exec_sqls@param db the database connection handle
* exec_sqls@param arg the input parameter from 'db_nonquery_transaction' function parameter 'arg'.
* exec_sqls@return =SQLITE_OK or =SQLITE_DONE:success,others:fail
* @param arg the parameter for the callback "exec_sqls".
* @return =SQLITE_OK:success, others:fail.
*/
int db_nonquery_transaction(int (*exec_sqls)(sqlite3 *db, void *arg), void *arg)
{
sqlite3 *db = NULL;
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_take(db_mutex_lock, RT_WAITING_FOREVER);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexObtain(&db_mutex_lock);
#endif
int rc = sqlite3_open(db_name, &db);
if (rc != SQLITE_OK)
{
printf("open database failed,rc=%d", rc);
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
return rc;
}
rc = sqlite3_exec(db, "begin transaction", 0, 0, NULL);
if (rc != SQLITE_OK)
{
printf("begin transaction:%d", rc);
goto __db_begin_fail;
}
if (exec_sqls)
{
rc = (*exec_sqls)(db, arg);
}
else
{
rc = SQLITE_ERROR;
}
if ((rc != SQLITE_OK) && (rc != SQLITE_DONE))
{
printf("prepare error,rc=%d", rc);
goto __db_exec_fail;
}
rc = sqlite3_exec(db, "commit transaction", 0, 0, NULL);
if (rc)
{
printf("commit transaction:%d", rc);
goto __db_exec_fail;
}
goto __db_exec_ok;
__db_exec_fail:
if (sqlite3_exec(db, "rollback transaction", 0, 0, NULL))
{
printf("rollback transaction:error");
}
__db_begin_fail:
printf("db operator failed,rc=%d", rc);
__db_exec_ok:
sqlite3_close(db);
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
return rc;
}
static int db_get_count(sqlite3_stmt *stmt, void *arg)
{
int ret, *count = arg;
ret = sqlite3_step(stmt);
if (ret != SQLITE_ROW)
{
return SQLITE_EMPTY;
}
*count = db_stmt_get_int(stmt, 0);
return SQLITE_OK;
}
/**
* This function will return the number of records returned by a select query.
* This function only gets the 1st row of the 1st column.
*
* @param sql the SQL statement SELECT COUNT() FROM .
* @return >=0:the count ,<0: fail.
*/
int db_query_count_result(const char *sql)
{
int ret, count = 0;
ret = db_query_by_varpara(sql, db_get_count, &count, NULL);
if (ret == SQLITE_OK)
{
return count;
}
return -1;
}
/**
* This function will get the blob from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @param out the output buffer.the result will put in this buffer.
* @return >=0:the result length ,<0: fail.
*/
int db_stmt_get_blob(sqlite3_stmt *stmt, int index, unsigned char *out)
{
const char *pdata = sqlite3_column_blob(stmt, index);
int len = sqlite3_column_bytes(stmt, index);
if (pdata)
{
memcpy(out, pdata, len);
return len;
}
return -1;
}
/**
* This function will get the text from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @param out the output buffer.the result will put in this buffer.
* @return >=0:the result length ,<0: fail.
*/
int db_stmt_get_text(sqlite3_stmt *stmt, int index, char *out)
{
const unsigned char *pdata = sqlite3_column_text(stmt, index);
if (pdata)
{
int len = strlen((char *)pdata);
strncpy(out, (char *)pdata, len);
return len;
}
return -1;
}
/**
* This function will get a integer from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @return the result.
*/
int db_stmt_get_int(sqlite3_stmt *stmt, int index)
{
return sqlite3_column_int(stmt, index);
}
/**
* This function will get a double precision value from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @return the result.
*/
double db_stmt_get_double(sqlite3_stmt *stmt, int index)
{
return sqlite3_column_double(stmt, index);
}
/**
* This function will check a table exist or not by table name.
*
* @param tbl_name the table name.
* @return >0:existed; ==0:not existed; <0:ERROR
*/
int db_table_is_exist(const char *tbl_name)
{
char sqlstr[DB_SQL_MAX_LEN];
int cnt = 0;
if (tbl_name == NULL)
{
return -1;
}
snprintf(sqlstr, DB_SQL_MAX_LEN, "select count(*) from sqlite_master where type = 'table' and name = '%s';", tbl_name);
cnt = db_query_count_result(sqlstr);
if (cnt > 0)
{
return cnt;
}
return -1;
}
/**
* This function will connect DB
*
* @param name the DB filename.
* @return 0:success
* -1:the input name is too long
*/
int db_connect(char *name)
{
int32_t len = 0;
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_take(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexObtain(&db_mutex_lock);
#endif
len = strnlen(name, PKG_SQLITE_DB_NAME_MAX_LEN + 1);
if (len >= PKG_SQLITE_DB_NAME_MAX_LEN + 1)
{
printf("the database name '(%s)' lengh is too long(max:%d).", name, PKG_SQLITE_DB_NAME_MAX_LEN);
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
return -1;
}
strncpy(db_name, name, len);
db_name[len] = '\0';
return 0;
}
/**
* This function will disconnect DB
*
* @param name the DB filename.
* @return 0:success
* -1:the input name is too long
*/
int db_disconnect(char *name)
{
int32_t len = 0;
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
strncpy(db_name, DEFAULT_DB_NAME, strlen(DEFAULT_DB_NAME));
db_name[len] = '\0';
return 0;
}
/**
* This function will connect DB
*
* @param name the DB filename.
* @return 0:success
* -1:the input name is too long
*/
int db_set_name(char *name)
{
int32_t len = 0;
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_take(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexObtain(&db_mutex_lock);
#endif
len = strnlen(name, PKG_SQLITE_DB_NAME_MAX_LEN + 1);
if (len >= PKG_SQLITE_DB_NAME_MAX_LEN + 1)
{
printf("the database name '(%s)' lengh is too long(max:%d).", name, PKG_SQLITE_DB_NAME_MAX_LEN);
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
return -1;
}
strncpy(db_name, name, len);
db_name[len] = '\0';
#ifdef ADD_RTTHREAD_FEATURES
rt_mutex_release(db_mutex_lock);
#endif
#ifdef ADD_XIZI_FEATURES
PrivMutexAbandon(&db_mutex_lock);
#endif
return 0;
}
/**
* This function will get the current DB filename
*
* @return the current DB filename
*
*/
char *db_get_name(void)
{
static char name[PKG_SQLITE_DB_NAME_MAX_LEN + 1];
size_t len = strlen(db_name);
strncpy(name, db_name, len);
name[len] = '\0';
return name;
}

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-06 lizhen9880 first version
*/
#ifndef __DBHELPER_H__
#define __DBHELPER_H__
#include <sqlite3.h>
#ifdef ADD_RTTHREAD_FEATURES
#include <rtthread.h>
#endif
#define DB_SQL_MAX_LEN PKG_SQLITE_SQL_MAX_LEN
int db_helper_init(void);
int db_create_database(const char *sqlstr);
/**
* This function will be used for the operating that is not SELECT.It support executing multiple
* SQL statements.
*
* @param sqlstr the SQL statements strings.if there are more than one
* statements in the sqlstr to execute,separate them by a semicolon(;).
* @param bind the callback function supported by user.bind data and call the sqlite3_step function.
* @param param the parameter for the callback "bind".
* @return success or fail.
*/
int db_nonquery_operator(const char *sqlstr, int (*bind)(sqlite3_stmt *, int index, void *arg), void *param);
/**
* This function will be used for the operating that is not SELECT.The additional
* arguments following format are formatted and inserted in the resulting string
* replacing their respective specifiers.
*
* @param sql the SQL statement.
* @param fmt the args format.such as %s string,%d int.
* @param ... the additional arguments
* @return success or fail.
*/
int db_nonquery_by_varpara(const char *sql, const char *fmt, ...);
/**
* This function will be used for the transaction that is not SELECT.
*
* @param exec_sqls the callback function of executing SQL statements.
* @param arg the parameter for the callback "exec_sqls".
* @return success or fail.
*/
int db_nonquery_transaction(int (*exec_sqls)(sqlite3 *db, void *arg), void *arg);
/**
* This function will be used for the SELECT operating.The additional arguments
* following format are formatted and inserted in the resulting string replacing
* their respective specifiers.
*
* @param sql the SQL statements.
* @param create the callback function supported by user.
* @param arg the parameter for the callback "create".
* @param fmt the args format.such as %s string,%d int.
* @param ... the additional arguments
* @return success or fail.
*/
int db_query_by_varpara(const char *sql, int (*create)(sqlite3_stmt *stmt, void *arg), void *arg, const char *fmt, ...);
/**
* This function will return the number of records returned by a select query.
* This function only gets the 1st row of the 1st column.
*
* @param sql the SQL statement SELECT COUNT() FROM .
* @return the count or fail.
*/
int db_query_count_result(const char *sql);
/**
* This function will get the blob from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @param out the output buffer.the result will put in this buffer.
* @return the result length or fail.
*/
int db_stmt_get_blob(sqlite3_stmt *stmt, int index, unsigned char *out);
/**
* This function will get the text from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @param out the output buffer.the result will put in this buffer.
* @return the result length or fail.
*/
int db_stmt_get_text(sqlite3_stmt *stmt, int index, char *out);
/**
* This function will get a integer from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @return the result.
*/
int db_stmt_get_int(sqlite3_stmt *stmt, int index);
/**
* This function will get a double precision value from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @return the result.
*/
double db_stmt_get_double(sqlite3_stmt *stmt, int index);
/**
* This function will check a table exist or not by table name.
*
* @param tbl_name the table name.
* @return >0:existed; ==0:not existed; <0:ERROR
*/
int db_table_is_exist(const char *tbl_name);
/**
* This function will connect DB
*
* @param name the DB filename.
* @return RT_EOK:success
* -RT_ERROR:the input name is too long
*/
int db_connect(char *name);
/**
* This function will disconnect DB
*
* @param name the DB filename.
* @return RT_EOK:success
* -RT_ERROR:the input name is too long
*/
int db_disconnect(char *name);
/**
* This function will connect DB
*
* @param name the DB filename.
* @return 0:success
* -1:the input name is too long
*/
int db_set_name(char *name);
/**
* This function will get the current DB filename
*
* @return the current DB filename
*
*/
char *db_get_name(void);
#endif

View File

@ -0,0 +1,467 @@
static int _rtthread_io_read(sqlite3_file *file_id, void *pbuf, int cnt, sqlite3_int64 offset)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
sqlite3_int64 new_offset;
int r_cnt;
assert(file_id);
assert(offset >= 0);
assert(cnt > 0);
new_offset = lseek(file->fd, offset, SEEK_SET);
if (new_offset != offset)
{
return SQLITE_IOERR_READ;
}
do {
r_cnt = read(file->fd, pbuf, cnt);
if (r_cnt == cnt)
{
break;
}
if (r_cnt < 0)
{
if (errno != EINTR)
{
return SQLITE_IOERR_READ;
}
r_cnt = 1;
continue;
}
else if (r_cnt > 0)
{
cnt -= r_cnt;
pbuf = (void*)(r_cnt + (char*)pbuf);
}
} while (r_cnt > 0);
if (r_cnt != cnt)
{
memset(&((char*)pbuf)[r_cnt], 0, cnt - r_cnt);
return SQLITE_IOERR_SHORT_READ;
}
return SQLITE_OK;
}
static int _rtthread_io_write(sqlite3_file* file_id, const void *pbuf, int cnt, sqlite3_int64 offset)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
sqlite3_int64 new_offset;
int w_cnt;
assert(file_id);
assert(cnt > 0);
new_offset = lseek(file->fd, offset, SEEK_SET);
if (new_offset != offset)
{
return SQLITE_IOERR_WRITE;
}
do {
w_cnt = write(file->fd, pbuf, cnt);
if (w_cnt == cnt)
{
break;
}
if (w_cnt < 0)
{
if (errno != EINTR)
{
return SQLITE_IOERR_WRITE;
}
w_cnt = 1;
continue;
}
else if (w_cnt > 0)
{
cnt -= w_cnt;
pbuf = (void*)(w_cnt + (char*)pbuf);
}
} while (w_cnt > 0);
if (w_cnt != cnt)
{
return SQLITE_FULL;
}
return SQLITE_OK;
}
static int _rtthread_io_truncate(sqlite3_file* file_id, sqlite3_int64 size)
{
return SQLITE_IOERR_TRUNCATE;
}
static int _rtthread_io_sync(sqlite3_file* file_id, int flags)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
assert((flags & 0x0F) == SQLITE_SYNC_NORMAL
|| (flags & 0x0F) == SQLITE_SYNC_FULL);
fsync(file->fd);
return SQLITE_OK;
}
static int _rtthread_io_file_size(sqlite3_file* file_id, sqlite3_int64 *psize)
{
int rc;
struct stat buf;
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
assert(file_id);
rc = fstat(file->fd, &buf);
if (rc != 0)
{
return SQLITE_IOERR_FSTAT;
}
*psize = buf.st_size;
/* When opening a zero-size database, the findInodeInfo() procedure
** writes a single byte into that file in order to work around a bug
** in the OS-X msdos filesystem. In order to avoid problems with upper
** layers, we need to report this file size as zero even though it is
** really 1. Ticket #3260.
*/
if (*psize == 1) *psize = 0;
return SQLITE_OK;
}
/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, set *pResOut
** to a non-zero value otherwise *pResOut is set to zero. The return value
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int _rtthread_io_check_reserved_lock(sqlite3_file *file_id, int *pResOut)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
rt_sem_t psem = &file->sem;
int reserved = 0;
/* Check if a thread in this process holds such a lock */
if (file->eFileLock > SHARED_LOCK)
{
reserved = 1;
}
/* Otherwise see if some other process holds it. */
if (!reserved)
{
if (rt_sem_trytake(psem) != RT_EOK)
{
/* someone else has the lock when we are in NO_LOCK */
reserved = (file->eFileLock < SHARED_LOCK);
}
else
{
/* we could have it if we want it */
rt_sem_release(psem);
}
}
*pResOut = reserved;
return SQLITE_OK;
}
/*
** Lock the file with the lock specified by parameter eFileLock - one
** of the following:
**
** (1) SHARED_LOCK
** (2) RESERVED_LOCK
** (3) PENDING_LOCK
** (4) EXCLUSIVE_LOCK
**
** Sometimes when requesting one lock state, additional lock states
** are inserted in between. The locking might fail on one of the later
** transitions leaving the lock state different from what it started but
** still short of its goal. The following chart shows the allowed
** transitions and the inserted intermediate states:
**
** UNLOCKED -> SHARED
** SHARED -> RESERVED
** SHARED -> (PENDING) -> EXCLUSIVE
** RESERVED -> (PENDING) -> EXCLUSIVE
** PENDING -> EXCLUSIVE
**
** Semaphore locks only really support EXCLUSIVE locks. We track intermediate
** lock states in the sqlite3_file structure, but all locks SHARED or
** above are really EXCLUSIVE locks and exclude all other processes from
** access the file.
**
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
static int _rtthread_io_lock(sqlite3_file *file_id, int eFileLock)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
rt_sem_t psem = &file->sem;
int rc = SQLITE_OK;
/* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
if (file->eFileLock > NO_LOCK)
{
file->eFileLock = eFileLock;
rc = SQLITE_OK;
goto sem_end_lock;
}
/* lock semaphore now but bail out when already locked. */
if (rt_sem_trytake(psem) != RT_EOK)
{
rc = SQLITE_BUSY;
goto sem_end_lock;
}
/* got it, set the type and return ok */
file->eFileLock = eFileLock;
sem_end_lock:
return rc;
}
/*
** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
*/
static int _rtthread_io_unlock(sqlite3_file *file_id, int eFileLock)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
rt_sem_t psem = &file->sem;
assert(eFileLock <= SHARED_LOCK);
/* no-op if possible */
if (file->eFileLock == eFileLock)
{
return SQLITE_OK;
}
/* shared can just be set because we always have an exclusive */
if (eFileLock == SHARED_LOCK)
{
file->eFileLock = SHARED_LOCK;
return SQLITE_OK;
}
/* no, really unlock. */
rt_sem_release(psem);
file->eFileLock = NO_LOCK;
return SQLITE_OK;
}
static int _rtthread_io_close(sqlite3_file *file_id)
{
int rc = 0;
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
if (file->fd >= 0)
{
_rtthread_io_unlock(file_id, NO_LOCK);
rt_sem_detach(&file->sem);
rc = close(file->fd);
file->fd = -1;
}
return rc;
}
static int _rtthread_fcntl_size_hint(sqlite3_file *file_id, i64 nByte)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
if (file->szChunk > 0)
{
i64 nSize; /* Required file size */
struct stat buf; /* Used to hold return values of fstat() */
if (fstat(file->fd, &buf))
{
return SQLITE_IOERR_FSTAT;
}
nSize = ((nByte + file->szChunk - 1) / file->szChunk) * file->szChunk;
if (nSize > (i64)buf.st_size)
{
/* If the OS does not have posix_fallocate(), fake it. Write a
** single byte to the last byte in each block that falls entirely
** within the extended region. Then, if required, a single byte
** at offset (nSize-1), to set the size of the file correctly.
** This is a similar technique to that used by glibc on systems
** that do not have a real fallocate() call.
*/
int nBlk = 512; /* File-system block size */
int nWrite = 0; /* Number of bytes written by seekAndWrite */
i64 iWrite; /* Next offset to write to */
iWrite = (buf.st_size / nBlk) * nBlk + nBlk - 1;
assert(iWrite >= buf.st_size);
assert(((iWrite + 1) % nBlk) == 0);
for (/*no-op*/; iWrite < nSize + nBlk - 1; iWrite += nBlk)
{
if (iWrite >= nSize)
{
iWrite = nSize - 1;
}
nWrite = _rtthread_io_write(file_id, "", 1, iWrite);
if (nWrite != 1)
{
return SQLITE_IOERR_WRITE;
}
}
}
}
return SQLITE_OK;
}
/*
** Information and control of an open file handle.
*/
static int _rtthread_io_file_ctrl(sqlite3_file *file_id, int op, void *pArg)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
switch( op )
{
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = file->eFileLock;
return SQLITE_OK;
}
case SQLITE_LAST_ERRNO: {
*(int*)pArg = 0;
return SQLITE_OK;
}
case SQLITE_FCNTL_CHUNK_SIZE: {
file->szChunk = *(int *)pArg;
return SQLITE_OK;
}
case SQLITE_FCNTL_SIZE_HINT: {
int rc;
rc = _rtthread_fcntl_size_hint(file_id, *(i64 *)pArg);
return rc;
}
case SQLITE_FCNTL_PERSIST_WAL: {
return SQLITE_OK;
}
case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
return SQLITE_OK;
}
case SQLITE_FCNTL_VFSNAME: {
*(char**)pArg = sqlite3_mprintf("%s", file->pvfs->zName);
return SQLITE_OK;
}
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = sqlite3_malloc(file->pvfs->mxPathname );
if( zTFile )
{
_rtthread_get_temp_name(file->pvfs->mxPathname, zTFile);
*(char**)pArg = zTFile;
}
return SQLITE_OK;
}
}
return SQLITE_NOTFOUND;
}
static int _rtthread_io_sector_size(sqlite3_file *file_id)
{
return SQLITE_DEFAULT_SECTOR_SIZE;
}
static int _rtthread_io_device_characteristics(sqlite3_file *file_id)
{
return 0;
}
/*
** If possible, return a pointer to a mapping of file fd starting at offset
** iOff. The mapping must be valid for at least nAmt bytes.
**
** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
** Finally, if an error does occur, return an SQLite error code. The final
** value of *pp is undefined in this case.
**
** If this function does return a pointer, the caller must eventually
** release the reference by calling unixUnfetch().
*/
static int _rtthread_io_fetch(sqlite3_file *file_id, i64 iOff, int nAmt, void **pp)
{
*pp = 0;
return SQLITE_OK;
}
/*
** If the third argument is non-NULL, then this function releases a
** reference obtained by an earlier call to unixFetch(). The second
** argument passed to this function must be the same as the corresponding
** argument that was passed to the unixFetch() invocation.
**
** Or, if the third argument is NULL, then this function is being called
** to inform the VFS layer that, according to POSIX, any existing mapping
** may now be invalid and should be unmapped.
*/
static int _rtthread_io_unfetch(sqlite3_file *fd, i64 iOff, void *p)
{
return SQLITE_OK;
}
static const sqlite3_io_methods _rtthread_io_method = {
3,
_rtthread_io_close,
_rtthread_io_read,
_rtthread_io_write,
_rtthread_io_truncate,
_rtthread_io_sync,
_rtthread_io_file_size,
_rtthread_io_lock,
_rtthread_io_unlock,
_rtthread_io_check_reserved_lock,
_rtthread_io_file_ctrl,
_rtthread_io_sector_size,
_rtthread_io_device_characteristics,
0,
0,
0,
0,
_rtthread_io_fetch,
_rtthread_io_unfetch
};

View File

@ -0,0 +1,228 @@
#if defined(SQLITE_MUTEX_RTTHREAD)
/*
* rt-thread mutex
*/
struct sqlite3_mutex {
struct rt_mutex mutex; /* Mutex controlling the lock */
int id; /* Mutex type */
};
SQLITE_PRIVATE void sqlite3MemoryBarrier(void)
{
}
/*
** Initialize and deinitialize the mutex subsystem.
The argument to sqlite3_mutex_alloc() must one of these integer constants:
SQLITE_MUTEX_FAST
SQLITE_MUTEX_RECURSIVE
SQLITE_MUTEX_STATIC_MASTER
SQLITE_MUTEX_STATIC_MEM
SQLITE_MUTEX_STATIC_OPEN
SQLITE_MUTEX_STATIC_PRNG
SQLITE_MUTEX_STATIC_LRU
SQLITE_MUTEX_STATIC_PMEM
SQLITE_MUTEX_STATIC_APP1
SQLITE_MUTEX_STATIC_APP2
SQLITE_MUTEX_STATIC_APP3
SQLITE_MUTEX_STATIC_VFS1
SQLITE_MUTEX_STATIC_VFS2
SQLITE_MUTEX_STATIC_VFS3
The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
cause sqlite3_mutex_alloc() to create a new mutex. The new mutex is recursive
when SQLITE_MUTEX_RECURSIVE is used but not necessarily so when SQLITE_MUTEX_FAST
is used. The mutex implementation does not need to make a distinction between
SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does not want to.
SQLite will only request a recursive mutex in cases where it really needs one.
If a faster non-recursive mutex implementation is available on the host platform,
the mutex subsystem might return such a mutex in response to SQLITE_MUTEX_FAST.
The other allowed parameters to sqlite3_mutex_alloc()
(anything other than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return
a pointer to a static preexisting mutex. Nine static mutexes are used by the
current version of SQLite. Future versions of SQLite may add additional static
mutexes. Static mutexes are for internal use by SQLite only. Applications that
use SQLite mutexes should use only the dynamic mutexes returned by SQLITE_MUTEX_FAST
or SQLITE_MUTEX_RECURSIVE.
Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST or SQLITE_MUTEX_RECURSIVE)
is used then sqlite3_mutex_alloc() returns a different mutex on every call.
For the static mutex types, the same mutex is returned on every call that has the same type number.
*/
static sqlite3_mutex _static_mutex[12];
static int _rtthread_mtx_init(void)
{
int i;
rt_err_t err;
for (i = 0; i < sizeof(_static_mutex) / sizeof(_static_mutex[0]); i++)
{
err = rt_mutex_init(&_static_mutex[i].mutex, "sqlmtx", RT_IPC_FLAG_PRIO);
if (err != RT_EOK)
{
return SQLITE_ERROR;
}
}
return SQLITE_OK;
}
static int _rtthread_mtx_end(void)
{
int i;
rt_err_t err;
for (i = 0; i < sizeof(_static_mutex) / sizeof(_static_mutex[0]); i++)
{
err = rt_mutex_detach(&_static_mutex[i].mutex);
_static_mutex[i].mutex.owner = 0;
_static_mutex[i].mutex.hold = 0;
if (err != RT_EOK)
{
return SQLITE_ERROR;
}
}
return SQLITE_OK;
}
static sqlite3_mutex * _rtthread_mtx_alloc(int id)
{
sqlite3_mutex *p = NULL;
switch (id)
{
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE:
p = sqlite3Malloc(sizeof(sqlite3_mutex));
if (p != NULL)
{
rt_mutex_init(&p->mutex, "sqlmtx", RT_IPC_FLAG_PRIO);
p->id = id;
}
break;
default:
assert(id - 2 >= 0);
assert(id - 2 < ArraySize(_static_mutex) );
p = &_static_mutex[id - 2];
p->id = id;
break;
}
return p;
}
static void _rtthread_mtx_free(sqlite3_mutex * p)
{
assert(p != 0);
rt_mutex_detach(&p->mutex);
switch (p->id)
{
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE:
sqlite3_free(p);
break;
default:
break;
}
}
static void _rtthread_mtx_enter(sqlite3_mutex *p)
{
assert(p != 0);
rt_mutex_take(&p->mutex, RT_WAITING_FOREVER);
}
static int _rtthread_mtx_try(sqlite3_mutex *p)
{
assert(p != 0);
if (rt_mutex_take(&p->mutex, RT_WAITING_NO) != RT_EOK)
{
return SQLITE_BUSY;
}
return SQLITE_OK;
}
static void _rtthread_mtx_leave(sqlite3_mutex *p)
{
assert(p != 0);
rt_mutex_release(&p->mutex);
}
#ifdef SQLITE_DEBUG
/*
If the argument to sqlite3_mutex_held() is a NULL pointer then the routine
should return 1. This seems counter-intuitive since clearly the mutex cannot
be held if it does not exist. But the reason the mutex does not exist is
because the build is not using mutexes. And we do not want the assert()
containing the call to sqlite3_mutex_held() to fail, so a non-zero return
is the appropriate thing to do. The sqlite3_mutex_notheld() interface should
also return 1 when given a NULL pointer.
*/
static int _rtthread_mtx_held(sqlite3_mutex *p)
{
if (p != 0)
{
if ((rt_thread_self() == p->mutex.owner) && (p->mutex.hold > 0))
{
return 1;
}
return 0;
}
return 1;
}
static int _rtthread_mtx_noheld(sqlite3_mutex *p)
{
if (_rtthread_mtx_held(p))
{
return 0;
}
return 1;
}
#endif /* SQLITE_DEBUG */
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void)
{
static const sqlite3_mutex_methods sMutex = {
_rtthread_mtx_init,
_rtthread_mtx_end,
_rtthread_mtx_alloc,
_rtthread_mtx_free,
_rtthread_mtx_enter,
_rtthread_mtx_try,
_rtthread_mtx_leave,
#ifdef SQLITE_DEBUG
_rtthread_mtx_held,
_rtthread_mtx_noheld
#else
0,
0
#endif
};
return &sMutex;
}
#endif /* SQLITE_MUTEX_RTTHREAD */

View File

@ -0,0 +1,654 @@
#ifdef SQLITE_OS_RTTHREAD
#ifndef SQLITE_OMIT_LOAD_EXTENSION
#error "rt-thread not support load extension, compile with SQLITE_OMIT_LOAD_EXTENSION."
#endif
#define RTTHREAD_MAX_PATHNAME 256
#include <dfs_posix.h>
/*
** Define various macros that are missing from some systems.
*/
#ifndef O_LARGEFILE
# define O_LARGEFILE 0
#endif
#ifdef SQLITE_DISABLE_LFS
# undef O_LARGEFILE
# define O_LARGEFILE 0
#endif
#ifndef O_NOFOLLOW
# define O_NOFOLLOW 0
#endif
#ifndef O_BINARY
# define O_BINARY 0
#endif
#ifndef RT_USING_NEWLIB
#ifndef EINTR
#define EINTR 4 /* Interrupted system call */
#endif
#ifndef ENOLCK
#define ENOLCK 46 /* No record locks available */
#endif
#ifndef EACCES
#define EACCES 13 /* Permission denied */
#endif
#ifndef EPERM
#define EPERM 1 /* Operation not permitted */
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT 145 /* Connection timed out */
#endif
#ifndef ENOTCONN
#define ENOTCONN 134 /* Transport endpoint is not connected */
#endif
#if defined(__GNUC__) || defined(__ADSPBLACKFIN__)
int _gettimeofday(struct timeval *tp, void *ignore) __attribute__((weak));
int _gettimeofday(struct timeval *tp, void *ignore)
#elif defined(__CC_ARM)
__weak int _gettimeofday(struct timeval *tp, void *ignore)
#elif defined(__IAR_SYSTEMS_ICC__)
#if __VER__ > 540
__weak
#endif
int _gettimeofday(struct timeval *tp, void *ignore)
#else
int _gettimeofday(struct timeval *tp, void *ignore)
#endif
{
return 0;
}
#endif /* RT_USING_NEWLIB */
static int _Access(const char *pathname, int mode)
{
int fd;
fd = open(pathname, O_RDONLY, mode);
if (fd >= 0)
{
close(fd);
return 0;
}
return -1;
}
#define _RTTHREAD_LOG_ERROR(a,b,c) _rtthread_log_error_at_line(a,b,c,__LINE__)
static int _rtthread_log_error_at_line(
int errcode, /* SQLite error code */
const char *zFunc, /* Name of OS function that failed */
const char *zPath, /* File path associated with error */
int iLine /* Source line number where error occurred */
)
{
char *zErr; /* Message from strerror() or equivalent */
int iErrno = errno; /* Saved syscall error number */
/* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
** the strerror() function to obtain the human-readable error message
** equivalent to errno. Otherwise, use strerror_r().
*/
#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
char aErr[80];
memset(aErr, 0, sizeof(aErr));
zErr = aErr;
/* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
** assume that the system provides the GNU version of strerror_r() that
** returns a pointer to a buffer containing the error message. That pointer
** may point to aErr[], or it may point to some static storage somewhere.
** Otherwise, assume that the system provides the POSIX version of
** strerror_r(), which always writes an error message into aErr[].
**
** If the code incorrectly assumes that it is the POSIX version that is
** available, the error message will often be an empty string. Not a
** huge problem. Incorrectly concluding that the GNU version is available
** could lead to a segfault though.
*/
#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
zErr =
#endif
strerror_r(iErrno, aErr, sizeof(aErr)-1);
#elif SQLITE_THREADSAFE
/* This is a threadsafe build, but strerror_r() is not available. */
zErr = "";
#else
/* Non-threadsafe build, use strerror(). */
zErr = strerror(iErrno);
#endif
if( zPath==0 )
zPath = "";
sqlite3_log(errcode, "os_rtthread.c:%d: (%d) %s(%s) - %s",
iLine, iErrno, zFunc, zPath, zErr);
return errcode;
}
typedef struct
{
sqlite3_io_methods const *pMethod;
sqlite3_vfs *pvfs;
int fd;
int eFileLock;
int szChunk;
struct rt_semaphore sem;
} RTTHREAD_SQLITE_FILE_T;
static const char* _rtthread_temp_file_dir(void)
{
const char *azDirs[] = {
0,
"/sql",
"/sql/tmp"
"/tmp",
0 /* List terminator */
};
unsigned int i;
struct stat buf;
const char *zDir = 0;
azDirs[0] = sqlite3_temp_directory;
for (i = 0; i < sizeof(azDirs) / sizeof(azDirs[0]); zDir = azDirs[i++])
{
if( zDir == 0 ) continue;
if( stat(zDir, &buf) ) continue;
if( !S_ISDIR(buf.st_mode) ) continue;
break;
}
return zDir;
}
/*
** Create a temporary file name in zBuf. zBuf must be allocated
** by the calling process and must be big enough to hold at least
** pVfs->mxPathname bytes.
*/
static int _rtthread_get_temp_name(int nBuf, char *zBuf)
{
const unsigned char zChars[] = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
unsigned int i, j;
const char *zDir;
zDir = _rtthread_temp_file_dir();
if (zDir == 0)
{
zDir = ".";
}
/* Check that the output buffer is large enough for the temporary file
** name. If it is not, return SQLITE_ERROR.
*/
if ((strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf)
{
return SQLITE_ERROR;
}
do {
sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
j = (int)strlen(zBuf);
sqlite3_randomness(15, &zBuf[j]);
for (i = 0; i < 15; i++, j++)
{
zBuf[j] = (char)zChars[((unsigned char)zBuf[j]) % (sizeof(zChars) - 1)];
}
zBuf[j] = 0;
zBuf[j + 1] = 0;
} while (_Access(zBuf, 0) == 0);
return SQLITE_OK;
}
#include "rtthread_io_methods.c"
/*
** Invoke open(). Do so multiple times, until it either succeeds or
** fails for some reason other than EINTR.
**
** If the file creation mode "m" is 0 then set it to the default for
** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
** 0644) as modified by the system umask. If m is not 0, then
** make the file creation mode be exactly m ignoring the umask.
**
** The m parameter will be non-zero only when creating -wal, -journal,
** and -shm files. We want those files to have *exactly* the same
** permissions as their original database, unadulterated by the umask.
** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
** transaction crashes and leaves behind hot journals, then any
** process that is able to write to the database will also be able to
** recover the hot journals.
*/
static int _rtthread_fs_open(const char *file_path, int f, mode_t m)
{
int fd = -1;
while (fd < 0)
{
#if defined(O_CLOEXEC)
fd = open(file_path, f | O_CLOEXEC, m);
#else
fd = open(file_path, f, m);
#endif
if (fd < 0)
{
if (errno == EINTR)
continue;
break;
}
}
return fd;
}
static int _rtthread_vfs_open(sqlite3_vfs *pvfs, const char *file_path, sqlite3_file *file_id, int flags, int *pOutFlags)
{
RTTHREAD_SQLITE_FILE_T *p;
int fd;
int eType = flags & 0xFFFFFF00; /* Type of file to open */
int rc = SQLITE_OK; /* Function Return Code */
int openFlags = 0;
mode_t openMode = 0;
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
int isCreate = (flags & SQLITE_OPEN_CREATE);
int isReadonly = (flags & SQLITE_OPEN_READONLY);
int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
/* If argument zPath is a NULL pointer, this function is required to open
** a temporary file. Use this buffer to store the file name in.
*/
char zTmpname[RTTHREAD_MAX_PATHNAME + 2];
p = (RTTHREAD_SQLITE_FILE_T*)file_id;
/* Check the following statements are true:
**
** (a) Exactly one of the READWRITE and READONLY flags must be set, and
** (b) if CREATE is set, then READWRITE must also be set, and
** (c) if EXCLUSIVE is set, then CREATE must also be set.
** (d) if DELETEONCLOSE is set, then CREATE must also be set.
*/
assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
assert(isCreate==0 || isReadWrite);
assert(isExclusive==0 || isCreate);
assert(isDelete==0 || isCreate);
/* The main DB, main journal, WAL file and master journal are never
** automatically deleted. Nor are they ever temporary files. */
assert( (!isDelete && file_path) || eType!=SQLITE_OPEN_MAIN_DB );
assert( (!isDelete && file_path) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
assert( (!isDelete && file_path) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
assert( (!isDelete && file_path) || eType!=SQLITE_OPEN_WAL );
/* Assert that the upper layer has set one of the "file-type" flags. */
assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
/* Database filenames are double-zero terminated if they are not
** URIs with parameters. Hence, they can always be passed into
** sqlite3_uri_parameter(). */
assert((eType != SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) || file_path[strlen(file_path) + 1] == 0);
memset(p, 0, sizeof(RTTHREAD_SQLITE_FILE_T));
if (!file_path)
{
rc = _rtthread_get_temp_name(RTTHREAD_MAX_PATHNAME + 2, zTmpname);
if (rc != SQLITE_OK )
{
return rc;
}
file_path = zTmpname;
/* Generated temporary filenames are always double-zero terminated
** for use by sqlite3_uri_parameter(). */
assert(file_path[strlen(file_path) + 1] == 0);
}
/* Determine the value of the flags parameter passed to POSIX function
** open(). These must be calculated even if open() is not called, as
** they may be stored as part of the file handle and used by the
** 'conch file' locking functions later on. */
if (isReadonly) openFlags |= O_RDONLY;
if (isReadWrite) openFlags |= O_RDWR;
if (isCreate) openFlags |= O_CREAT;
if (isExclusive) openFlags |= (O_EXCL | O_NOFOLLOW);
openFlags |= (O_LARGEFILE | O_BINARY);
fd = _rtthread_fs_open(file_path, openFlags, openMode);
if (fd < 0 && (errno != -EISDIR) && isReadWrite && !isExclusive)
{
/* Failed to open the file for read/write access. Try read-only. */
flags &= ~(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
openFlags &= ~(O_RDWR | O_CREAT);
flags |= SQLITE_OPEN_READONLY;
openFlags |= O_RDONLY;
isReadonly = 1;
fd = _rtthread_fs_open(file_path, openFlags, openMode);
}
if (fd < 0)
{
rc = _RTTHREAD_LOG_ERROR(SQLITE_CANTOPEN_BKPT, "open", file_path);
return rc;
}
if (pOutFlags)
{
*pOutFlags = flags;
}
if (isDelete)
{
unlink(file_path);
}
p->fd = fd;
p->pMethod = &_rtthread_io_method;
p->eFileLock = NO_LOCK;
p->szChunk = 0;
p->pvfs = pvfs;
rt_sem_init(&p->sem, "vfssem", 1, RT_IPC_FLAG_PRIO);
return rc;
}
int _rtthread_vfs_delete(sqlite3_vfs* pvfs, const char *file_path, int syncDir)
{
int rc = SQLITE_OK;
if (unlink(file_path) == (-1))
{
if (errno == -ENOENT)
{
rc = SQLITE_IOERR_DELETE_NOENT;
}
else
{
rc = _RTTHREAD_LOG_ERROR(SQLITE_IOERR_DELETE, "unlink", file_path);
}
return rc;
}
// sync dir: open dir -> fsync -> close
if ((syncDir & 1) != 0)
{
int ii;
int fd = -1;
char zDirname[RTTHREAD_MAX_PATHNAME + 1];
sqlite3_snprintf(RTTHREAD_MAX_PATHNAME, zDirname, "%s", file_path);
for (ii=(int)strlen(zDirname); ii > 1 && zDirname[ii] != '/'; ii--);
if (ii > 0)
{
zDirname[ii] = '\0';
fd = _rtthread_fs_open(zDirname, O_RDONLY | O_BINARY, 0);
}
if (fd >= 0)
{
if (fsync(fd))
{
rc = _RTTHREAD_LOG_ERROR(SQLITE_IOERR_DIR_FSYNC, "fsync", file_path);
}
close(fd);
}
rc = SQLITE_OK;
}
return rc;
}
static int _rtthread_vfs_access(sqlite3_vfs* pvfs, const char *file_path, int flags, int *pResOut)
{
int amode = 0;
#ifndef F_OK
# define F_OK 0
#endif
#ifndef R_OK
# define R_OK 4
#endif
#ifndef W_OK
# define W_OK 2
#endif
switch (flags)
{
case SQLITE_ACCESS_EXISTS:
amode = F_OK;
break;
case SQLITE_ACCESS_READWRITE:
amode = W_OK | R_OK;
break;
case SQLITE_ACCESS_READ:
amode = R_OK;
break;
default:
_RTTHREAD_LOG_ERROR(flags, "access", file_path);
return -1;
}
*pResOut = (_Access(file_path, amode) == 0);
if (flags == SQLITE_ACCESS_EXISTS && *pResOut)
{
struct stat buf;
if (0 == stat(file_path, &buf) && (buf.st_size == 0))
{
*pResOut = 0;
}
}
return SQLITE_OK;
}
static int _rtthread_vfs_fullpathname(sqlite3_vfs* pvfs, const char *file_path, int nOut, char *zOut)
{
assert(pvfs->mxPathname == RTTHREAD_MAX_PATHNAME);
zOut[nOut - 1] = '\0';
if (file_path[0] == '/')
{
sqlite3_snprintf(nOut, zOut, "%s", file_path);
}
else
{
int nCwd;
if (getcwd(zOut, nOut - 1) == 0)
{
return _RTTHREAD_LOG_ERROR(SQLITE_CANTOPEN_BKPT, "getcwd", file_path);
}
nCwd = (int)strlen(zOut);
sqlite3_snprintf(nOut - nCwd, &zOut[nCwd], "/%s", file_path);
}
return SQLITE_OK;
}
static int _rtthread_vfs_randomness(sqlite3_vfs* pvfs, int nByte, char *zOut)
{
assert((size_t)nByte >= (sizeof(time_t) + sizeof(int)));
memset(zOut, 0, nByte);
{
int i;
char tick8, tick16;
tick8 = (char)rt_tick_get();
tick16 = (char)(rt_tick_get() >> 8);
for (i = 0; i < nByte; i++)
{
zOut[i] = (char)(i ^ tick8 ^ tick16);
tick8 = zOut[i];
tick16 = ~(tick8 ^ tick16);
}
}
return nByte;
}
static int _rtthread_vfs_sleep(sqlite3_vfs* pvfs, int microseconds)
{
int millisecond = (microseconds + 999) / 1000;
rt_thread_delay(rt_tick_from_millisecond(millisecond));
return millisecond * 1000;
}
static int _rtthread_vfs_current_time_int64(sqlite3_vfs*, sqlite3_int64*);
static int _rtthread_vfs_current_time(sqlite3_vfs* pvfs, double* pnow)
{
sqlite3_int64 i = 0;
int rc;
rc = _rtthread_vfs_current_time_int64(0, &i);
*pnow = i / 86400000.0;
return rc;
}
static int _rtthread_vfs_get_last_error(sqlite3_vfs* pvfs, int nBuf, char *zBuf)
{
return 0;
}
static int _rtthread_vfs_current_time_int64(sqlite3_vfs* pvfs, sqlite3_int64*pnow)
{
#ifndef NO_GETTOD
#define NO_GETTOD 1
#endif
static const sqlite3_int64 rtthreadEpoch = 24405875 * (sqlite3_int64)8640000;
int rc = SQLITE_OK;
#if defined(NO_GETTOD)
time_t t;
time(&t);
*pnow = ((sqlite3_int64)t) * 1000 + rtthreadEpoch;
#else
struct timeval sNow;
if (gettimeofday(&sNow, 0) == 0)
{
*pnow = rtthreadEpoch + 1000 * (sqlite3_int64)sNow.tv_sec + sNow.tv_usec / 1000;
}
else
{
rc = SQLITE_ERROR;
}
#endif
#ifdef SQLITE_TEST
if( sqlite3_current_time )
{
*pnow = 1000 * (sqlite3_int64)sqlite3_current_time + rtthreadEpoch;
}
#endif
return rc;
}
static int _rtthread_vfs_set_system_call(sqlite3_vfs* pvfs, const char *file_path, sqlite3_syscall_ptr pfn)
{
return SQLITE_NOTFOUND;
}
static sqlite3_syscall_ptr _rtthread_vfs_get_system_call(sqlite3_vfs* pvfs, const char *file_path)
{
return 0;
}
static const char* _rtthread_vfs_next_system_call(sqlite3_vfs *pvfs, const char *file_path)
{
return 0;
}
/*
** Initialize and deinitialize the operating system interface.
*/
SQLITE_API int sqlite3_os_init(void)
{
static sqlite3_vfs _rtthread_vfs = {
3, /* iVersion */
sizeof(RTTHREAD_SQLITE_FILE_T), /* szOsFile */
RTTHREAD_MAX_PATHNAME, /* mxPathname */
0, /* pNext */
"rt-thread", /* zName */
0, /* pAppData */
_rtthread_vfs_open, /* xOpen */
_rtthread_vfs_delete, /* xDelete */
_rtthread_vfs_access, /* xAccess */
_rtthread_vfs_fullpathname, /* xFullPathname */
0, /* xDlOpen */
0, /* xDlError */
0, /* xDlSym */
0, /* xDlClose */
_rtthread_vfs_randomness, /* xRandomness */
_rtthread_vfs_sleep, /* xSleep */
_rtthread_vfs_current_time, /* xCurrentTime */
_rtthread_vfs_get_last_error, /* xGetLastError */
_rtthread_vfs_current_time_int64, /* xCurrentTimeInt64 */
_rtthread_vfs_set_system_call, /* xSetSystemCall */
_rtthread_vfs_get_system_call, /* xGetSystemCall */
_rtthread_vfs_next_system_call, /* xNextSystemCall */
};
sqlite3_vfs_register(&_rtthread_vfs, 1);
return SQLITE_OK;
}
SQLITE_API int sqlite3_os_end(void)
{
return SQLITE_OK;
}
#endif /* SQLITE_OS_RTTHREAD */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,564 @@
/*
** 2006 June 7
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the SQLite interface for use by
** shared libraries that want to be imported as extensions into
** an SQLite instance. Shared libraries that intend to be loaded
** as extensions by SQLite should #include this file instead of
** sqlite3.h.
*/
#ifndef SQLITE3EXT_H
#define SQLITE3EXT_H
#include "sqlite3.h"
/*
** The following structure holds pointers to all of the SQLite API
** routines.
**
** WARNING: In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only. If you insert new
** interfaces in the middle of this structure, then older different
** versions of SQLite will not be able to load each other's shared
** libraries!
*/
struct sqlite3_api_routines {
void * (*aggregate_context)(sqlite3_context*,int nBytes);
int (*aggregate_count)(sqlite3_context*);
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
int (*bind_double)(sqlite3_stmt*,int,double);
int (*bind_int)(sqlite3_stmt*,int,int);
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
int (*bind_null)(sqlite3_stmt*,int);
int (*bind_parameter_count)(sqlite3_stmt*);
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
int (*busy_timeout)(sqlite3*,int ms);
int (*changes)(sqlite3*);
int (*close)(sqlite3*);
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const char*));
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const void*));
const void * (*column_blob)(sqlite3_stmt*,int iCol);
int (*column_bytes)(sqlite3_stmt*,int iCol);
int (*column_bytes16)(sqlite3_stmt*,int iCol);
int (*column_count)(sqlite3_stmt*pStmt);
const char * (*column_database_name)(sqlite3_stmt*,int);
const void * (*column_database_name16)(sqlite3_stmt*,int);
const char * (*column_decltype)(sqlite3_stmt*,int i);
const void * (*column_decltype16)(sqlite3_stmt*,int);
double (*column_double)(sqlite3_stmt*,int iCol);
int (*column_int)(sqlite3_stmt*,int iCol);
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
const char * (*column_name)(sqlite3_stmt*,int);
const void * (*column_name16)(sqlite3_stmt*,int);
const char * (*column_origin_name)(sqlite3_stmt*,int);
const void * (*column_origin_name16)(sqlite3_stmt*,int);
const char * (*column_table_name)(sqlite3_stmt*,int);
const void * (*column_table_name16)(sqlite3_stmt*,int);
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
const void * (*column_text16)(sqlite3_stmt*,int iCol);
int (*column_type)(sqlite3_stmt*,int iCol);
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
int (*complete)(const char*sql);
int (*complete16)(const void*sql);
int (*create_collation)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_collation16)(sqlite3*,const void*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_function)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_function16)(sqlite3*,const void*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
int (*data_count)(sqlite3_stmt*pStmt);
sqlite3 * (*db_handle)(sqlite3_stmt*);
int (*declare_vtab)(sqlite3*,const char*);
int (*enable_shared_cache)(int);
int (*errcode)(sqlite3*db);
const char * (*errmsg)(sqlite3*);
const void * (*errmsg16)(sqlite3*);
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
int (*expired)(sqlite3_stmt*);
int (*finalize)(sqlite3_stmt*pStmt);
void (*free)(void*);
void (*free_table)(char**result);
int (*get_autocommit)(sqlite3*);
void * (*get_auxdata)(sqlite3_context*,int);
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
int (*global_recover)(void);
void (*interruptx)(sqlite3*);
sqlite_int64 (*last_insert_rowid)(sqlite3*);
const char * (*libversion)(void);
int (*libversion_number)(void);
void *(*malloc)(int);
char * (*mprintf)(const char*,...);
int (*open)(const char*,sqlite3**);
int (*open16)(const void*,sqlite3**);
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
void *(*realloc)(void*,int);
int (*reset)(sqlite3_stmt*pStmt);
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_double)(sqlite3_context*,double);
void (*result_error)(sqlite3_context*,const char*,int);
void (*result_error16)(sqlite3_context*,const void*,int);
void (*result_int)(sqlite3_context*,int);
void (*result_int64)(sqlite3_context*,sqlite_int64);
void (*result_null)(sqlite3_context*);
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_value)(sqlite3_context*,sqlite3_value*);
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
char * (*snprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
void (*thread_cleanup)(void);
int (*total_changes)(sqlite3*);
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
sqlite_int64),void*);
void * (*user_data)(sqlite3_context*);
const void * (*value_blob)(sqlite3_value*);
int (*value_bytes)(sqlite3_value*);
int (*value_bytes16)(sqlite3_value*);
double (*value_double)(sqlite3_value*);
int (*value_int)(sqlite3_value*);
sqlite_int64 (*value_int64)(sqlite3_value*);
int (*value_numeric_type)(sqlite3_value*);
const unsigned char * (*value_text)(sqlite3_value*);
const void * (*value_text16)(sqlite3_value*);
const void * (*value_text16be)(sqlite3_value*);
const void * (*value_text16le)(sqlite3_value*);
int (*value_type)(sqlite3_value*);
char *(*vmprintf)(const char*,va_list);
/* Added ??? */
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
/* Added by 3.3.13 */
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
int (*clear_bindings)(sqlite3_stmt*);
/* Added by 3.4.1 */
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
void (*xDestroy)(void *));
/* Added by 3.5.0 */
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
int (*blob_bytes)(sqlite3_blob*);
int (*blob_close)(sqlite3_blob*);
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
int,sqlite3_blob**);
int (*blob_read)(sqlite3_blob*,void*,int,int);
int (*blob_write)(sqlite3_blob*,const void*,int,int);
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*),
void(*)(void*));
int (*file_control)(sqlite3*,const char*,int,void*);
sqlite3_int64 (*memory_highwater)(int);
sqlite3_int64 (*memory_used)(void);
sqlite3_mutex *(*mutex_alloc)(int);
void (*mutex_enter)(sqlite3_mutex*);
void (*mutex_free)(sqlite3_mutex*);
void (*mutex_leave)(sqlite3_mutex*);
int (*mutex_try)(sqlite3_mutex*);
int (*open_v2)(const char*,sqlite3**,int,const char*);
int (*release_memory)(int);
void (*result_error_nomem)(sqlite3_context*);
void (*result_error_toobig)(sqlite3_context*);
int (*sleep)(int);
void (*soft_heap_limit)(int);
sqlite3_vfs *(*vfs_find)(const char*);
int (*vfs_register)(sqlite3_vfs*,int);
int (*vfs_unregister)(sqlite3_vfs*);
int (*xthreadsafe)(void);
void (*result_zeroblob)(sqlite3_context*,int);
void (*result_error_code)(sqlite3_context*,int);
int (*test_control)(int, ...);
void (*randomness)(int,void*);
sqlite3 *(*context_db_handle)(sqlite3_context*);
int (*extended_result_codes)(sqlite3*,int);
int (*limit)(sqlite3*,int,int);
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
const char *(*sql)(sqlite3_stmt*);
int (*status)(int,int*,int*,int);
int (*backup_finish)(sqlite3_backup*);
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
int (*backup_pagecount)(sqlite3_backup*);
int (*backup_remaining)(sqlite3_backup*);
int (*backup_step)(sqlite3_backup*,int);
const char *(*compileoption_get)(int);
int (*compileoption_used)(const char*);
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void(*xDestroy)(void*));
int (*db_config)(sqlite3*,int,...);
sqlite3_mutex *(*db_mutex)(sqlite3*);
int (*db_status)(sqlite3*,int,int*,int*,int);
int (*extended_errcode)(sqlite3*);
void (*log)(int,const char*,...);
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
const char *(*sourceid)(void);
int (*stmt_status)(sqlite3_stmt*,int,int);
int (*strnicmp)(const char*,const char*,int);
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
int (*wal_autocheckpoint)(sqlite3*,int);
int (*wal_checkpoint)(sqlite3*,const char*);
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
int (*vtab_config)(sqlite3*,int op,...);
int (*vtab_on_conflict)(sqlite3*);
/* Version 3.7.16 and later */
int (*close_v2)(sqlite3*);
const char *(*db_filename)(sqlite3*,const char*);
int (*db_readonly)(sqlite3*,const char*);
int (*db_release_memory)(sqlite3*);
const char *(*errstr)(int);
int (*stmt_busy)(sqlite3_stmt*);
int (*stmt_readonly)(sqlite3_stmt*);
int (*stricmp)(const char*,const char*);
int (*uri_boolean)(const char*,const char*,int);
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
const char *(*uri_parameter)(const char*,const char*);
char *(*vsnprintf)(int,char*,const char*,va_list);
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
/* Version 3.8.7 and later */
int (*auto_extension)(void(*)(void));
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
void(*)(void*));
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
void(*)(void*),unsigned char);
int (*cancel_auto_extension)(void(*)(void));
int (*load_extension)(sqlite3*,const char*,const char*,char**);
void *(*malloc64)(sqlite3_uint64);
sqlite3_uint64 (*msize)(void*);
void *(*realloc64)(void*,sqlite3_uint64);
void (*reset_auto_extension)(void);
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
void(*)(void*));
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
void(*)(void*), unsigned char);
int (*strglob)(const char*,const char*);
/* Version 3.8.11 and later */
sqlite3_value *(*value_dup)(const sqlite3_value*);
void (*value_free)(sqlite3_value*);
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
/* Version 3.9.0 and later */
unsigned int (*value_subtype)(sqlite3_value*);
void (*result_subtype)(sqlite3_context*,unsigned int);
/* Version 3.10.0 and later */
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
int (*strlike)(const char*,const char*,unsigned int);
int (*db_cacheflush)(sqlite3*);
/* Version 3.12.0 and later */
int (*system_errno)(sqlite3*);
/* Version 3.14.0 and later */
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
char *(*expanded_sql)(sqlite3_stmt*);
/* Version 3.18.0 and later */
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
};
/*
** This is the function signature used for all extension entry points. It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
sqlite3 *db, /* Handle to the database. */
char **pzErrMsg, /* Used to set error string on failure. */
const sqlite3_api_routines *pThunk /* Extension API function pointers. */
);
/*
** The following macros redefine the API routines so that they are
** redirected through the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that
** it can get access to the sqlite3_api_routines structure
** definition. But the main library does not want to redefine
** the API. So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined.
*/
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
#endif
#define sqlite3_bind_blob sqlite3_api->bind_blob
#define sqlite3_bind_double sqlite3_api->bind_double
#define sqlite3_bind_int sqlite3_api->bind_int
#define sqlite3_bind_int64 sqlite3_api->bind_int64
#define sqlite3_bind_null sqlite3_api->bind_null
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
#define sqlite3_bind_text sqlite3_api->bind_text
#define sqlite3_bind_text16 sqlite3_api->bind_text16
#define sqlite3_bind_value sqlite3_api->bind_value
#define sqlite3_busy_handler sqlite3_api->busy_handler
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
#define sqlite3_changes sqlite3_api->changes
#define sqlite3_close sqlite3_api->close
#define sqlite3_collation_needed sqlite3_api->collation_needed
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
#define sqlite3_column_blob sqlite3_api->column_blob
#define sqlite3_column_bytes sqlite3_api->column_bytes
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
#define sqlite3_column_count sqlite3_api->column_count
#define sqlite3_column_database_name sqlite3_api->column_database_name
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
#define sqlite3_column_decltype sqlite3_api->column_decltype
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
#define sqlite3_column_double sqlite3_api->column_double
#define sqlite3_column_int sqlite3_api->column_int
#define sqlite3_column_int64 sqlite3_api->column_int64
#define sqlite3_column_name sqlite3_api->column_name
#define sqlite3_column_name16 sqlite3_api->column_name16
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
#define sqlite3_column_table_name sqlite3_api->column_table_name
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
#define sqlite3_column_text sqlite3_api->column_text
#define sqlite3_column_text16 sqlite3_api->column_text16
#define sqlite3_column_type sqlite3_api->column_type
#define sqlite3_column_value sqlite3_api->column_value
#define sqlite3_commit_hook sqlite3_api->commit_hook
#define sqlite3_complete sqlite3_api->complete
#define sqlite3_complete16 sqlite3_api->complete16
#define sqlite3_create_collation sqlite3_api->create_collation
#define sqlite3_create_collation16 sqlite3_api->create_collation16
#define sqlite3_create_function sqlite3_api->create_function
#define sqlite3_create_function16 sqlite3_api->create_function16
#define sqlite3_create_module sqlite3_api->create_module
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
#define sqlite3_data_count sqlite3_api->data_count
#define sqlite3_db_handle sqlite3_api->db_handle
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
#define sqlite3_errcode sqlite3_api->errcode
#define sqlite3_errmsg sqlite3_api->errmsg
#define sqlite3_errmsg16 sqlite3_api->errmsg16
#define sqlite3_exec sqlite3_api->exec
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_expired sqlite3_api->expired
#endif
#define sqlite3_finalize sqlite3_api->finalize
#define sqlite3_free sqlite3_api->free
#define sqlite3_free_table sqlite3_api->free_table
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
#define sqlite3_get_table sqlite3_api->get_table
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_global_recover sqlite3_api->global_recover
#endif
#define sqlite3_interrupt sqlite3_api->interruptx
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
#define sqlite3_libversion sqlite3_api->libversion
#define sqlite3_libversion_number sqlite3_api->libversion_number
#define sqlite3_malloc sqlite3_api->malloc
#define sqlite3_mprintf sqlite3_api->mprintf
#define sqlite3_open sqlite3_api->open
#define sqlite3_open16 sqlite3_api->open16
#define sqlite3_prepare sqlite3_api->prepare
#define sqlite3_prepare16 sqlite3_api->prepare16
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_profile sqlite3_api->profile
#define sqlite3_progress_handler sqlite3_api->progress_handler
#define sqlite3_realloc sqlite3_api->realloc
#define sqlite3_reset sqlite3_api->reset
#define sqlite3_result_blob sqlite3_api->result_blob
#define sqlite3_result_double sqlite3_api->result_double
#define sqlite3_result_error sqlite3_api->result_error
#define sqlite3_result_error16 sqlite3_api->result_error16
#define sqlite3_result_int sqlite3_api->result_int
#define sqlite3_result_int64 sqlite3_api->result_int64
#define sqlite3_result_null sqlite3_api->result_null
#define sqlite3_result_text sqlite3_api->result_text
#define sqlite3_result_text16 sqlite3_api->result_text16
#define sqlite3_result_text16be sqlite3_api->result_text16be
#define sqlite3_result_text16le sqlite3_api->result_text16le
#define sqlite3_result_value sqlite3_api->result_value
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
#define sqlite3_snprintf sqlite3_api->snprintf
#define sqlite3_step sqlite3_api->step
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
#define sqlite3_total_changes sqlite3_api->total_changes
#define sqlite3_trace sqlite3_api->trace
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
#endif
#define sqlite3_update_hook sqlite3_api->update_hook
#define sqlite3_user_data sqlite3_api->user_data
#define sqlite3_value_blob sqlite3_api->value_blob
#define sqlite3_value_bytes sqlite3_api->value_bytes
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
#define sqlite3_value_double sqlite3_api->value_double
#define sqlite3_value_int sqlite3_api->value_int
#define sqlite3_value_int64 sqlite3_api->value_int64
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
#define sqlite3_value_text sqlite3_api->value_text
#define sqlite3_value_text16 sqlite3_api->value_text16
#define sqlite3_value_text16be sqlite3_api->value_text16be
#define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf
#define sqlite3_vsnprintf sqlite3_api->vsnprintf
#define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
#define sqlite3_blob_close sqlite3_api->blob_close
#define sqlite3_blob_open sqlite3_api->blob_open
#define sqlite3_blob_read sqlite3_api->blob_read
#define sqlite3_blob_write sqlite3_api->blob_write
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
#define sqlite3_file_control sqlite3_api->file_control
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
#define sqlite3_memory_used sqlite3_api->memory_used
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
#define sqlite3_mutex_free sqlite3_api->mutex_free
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
#define sqlite3_mutex_try sqlite3_api->mutex_try
#define sqlite3_open_v2 sqlite3_api->open_v2
#define sqlite3_release_memory sqlite3_api->release_memory
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
#define sqlite3_sleep sqlite3_api->sleep
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
#define sqlite3_vfs_find sqlite3_api->vfs_find
#define sqlite3_vfs_register sqlite3_api->vfs_register
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
#define sqlite3_result_error_code sqlite3_api->result_error_code
#define sqlite3_test_control sqlite3_api->test_control
#define sqlite3_randomness sqlite3_api->randomness
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
#define sqlite3_limit sqlite3_api->limit
#define sqlite3_next_stmt sqlite3_api->next_stmt
#define sqlite3_sql sqlite3_api->sql
#define sqlite3_status sqlite3_api->status
#define sqlite3_backup_finish sqlite3_api->backup_finish
#define sqlite3_backup_init sqlite3_api->backup_init
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
#define sqlite3_backup_step sqlite3_api->backup_step
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
#define sqlite3_db_config sqlite3_api->db_config
#define sqlite3_db_mutex sqlite3_api->db_mutex
#define sqlite3_db_status sqlite3_api->db_status
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
#define sqlite3_log sqlite3_api->log
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
#define sqlite3_sourceid sqlite3_api->sourceid
#define sqlite3_stmt_status sqlite3_api->stmt_status
#define sqlite3_strnicmp sqlite3_api->strnicmp
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook sqlite3_api->wal_hook
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
#define sqlite3_vtab_config sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
/* Version 3.7.16 and later */
#define sqlite3_close_v2 sqlite3_api->close_v2
#define sqlite3_db_filename sqlite3_api->db_filename
#define sqlite3_db_readonly sqlite3_api->db_readonly
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
#define sqlite3_errstr sqlite3_api->errstr
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
#define sqlite3_stricmp sqlite3_api->stricmp
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
#define sqlite3_uri_int64 sqlite3_api->uri_int64
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
/* Version 3.8.7 and later */
#define sqlite3_auto_extension sqlite3_api->auto_extension
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
#define sqlite3_bind_text64 sqlite3_api->bind_text64
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
#define sqlite3_load_extension sqlite3_api->load_extension
#define sqlite3_malloc64 sqlite3_api->malloc64
#define sqlite3_msize sqlite3_api->msize
#define sqlite3_realloc64 sqlite3_api->realloc64
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
#define sqlite3_result_blob64 sqlite3_api->result_blob64
#define sqlite3_result_text64 sqlite3_api->result_text64
#define sqlite3_strglob sqlite3_api->strglob
/* Version 3.8.11 and later */
#define sqlite3_value_dup sqlite3_api->value_dup
#define sqlite3_value_free sqlite3_api->value_free
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
/* Version 3.9.0 and later */
#define sqlite3_value_subtype sqlite3_api->value_subtype
#define sqlite3_result_subtype sqlite3_api->result_subtype
/* Version 3.10.0 and later */
#define sqlite3_status64 sqlite3_api->status64
#define sqlite3_strlike sqlite3_api->strlike
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
/* Version 3.12.0 and later */
#define sqlite3_system_errno sqlite3_api->system_errno
/* Version 3.14.0 and later */
#define sqlite3_trace_v2 sqlite3_api->trace_v2
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
/* Version 3.18.0 and later */
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
/* This case when the file really is being compiled as a loadable
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
# define SQLITE_EXTENSION_INIT3 \
extern const sqlite3_api_routines *sqlite3_api;
#else
/* This case when the file is being statically linked into the
** application */
# define SQLITE_EXTENSION_INIT1 /*no-op*/
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
# define SQLITE_EXTENSION_INIT3 /*no-op*/
#endif
#endif /* SQLITE3EXT_H */

View File

@ -0,0 +1,44 @@
#ifndef _SQLITE_CONFIG_RTTHREAD_H_
#define _SQLITE_CONFIG_RTTHREAD_H_
/*
* SQLite compile macro
*/
#ifndef SQLITE_MINIMUM_FILE_DESCRIPTOR
#define SQLITE_MINIMUM_FILE_DESCRIPTOR 0
#endif
#define SQLITE_OMIT_LOAD_EXTENSION 0
#define SQLITE_OMIT_WAL 1
#define SQLITE_OMIT_AUTOINIT 1
#ifndef SQLITE_RTTHREAD_NO_WIDE
#define SQLITE_RTTHREAD_NO_WIDE 1
#endif
#ifndef SQLITE_TEMP_STORE
#define SQLITE_TEMP_STORE 1
#endif
#ifndef SQLITE_THREADSAFE
#define SQLITE_THREADSAFE 1
#endif
#ifndef HAVE_READLINE
#define HAVE_READLINE 0
#endif
#ifndef NDEBUG
#define NDEBUG
#endif
#ifndef SQLITE_OS_OTHER
#define SQLITE_OS_OTHER 1
#endif
#ifndef SQLITE_OS_RTTHREAD
#define SQLITE_OS_RTTHREAD 1
#endif
#endif

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file sqlite_config_xiuos.h
* @brief support SQLite define for XiUOS, include rtthread and xizi kernel
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023-10-16
*/
/*************************************************
File name: sqlite_config_xiuos.h
Description: support SQLite define for XiUOS, include rtthread and xizi kernel
Others:
History:
1. Date: 2023-10-16
Author: AIIT XUOS Lab
Modification:
1modify ifndef description
*************************************************/
#ifndef _SQLITE_CONFIG_XIUOS_H_
#define _SQLITE_CONFIG_XIUOS_H_
#include <transform.h>
/*
* SQLite compile macro
*/
#ifndef SQLITE_MINIMUM_FILE_DESCRIPTOR
#define SQLITE_MINIMUM_FILE_DESCRIPTOR 0
#endif
#define SQLITE_OMIT_LOAD_EXTENSION 0
#define SQLITE_OMIT_WAL 1
#define SQLITE_OMIT_AUTOINIT 1
#ifndef SQLITE_RTTHREAD_NO_WIDE
#define SQLITE_RTTHREAD_NO_WIDE 1
#endif
#ifndef SQLITE_TEMP_STORE
#define SQLITE_TEMP_STORE 1
#endif
#ifndef SQLITE_THREADSAFE
#define SQLITE_THREADSAFE 1
#endif
#ifndef HAVE_READLINE
#define HAVE_READLINE 0
#endif
#ifndef NDEBUG
#define NDEBUG
#endif
#ifndef SQLITE_OS_OTHER
#define SQLITE_OS_OTHER 1
#endif
#ifndef SQLITE_OS_XIUOS
#define SQLITE_OS_XIUOS 1
#endif
#ifndef PKG_SQLITE_SQL_MAX_LEN
#define PKG_SQLITE_SQL_MAX_LEN LIB_SQLITE_SQL_MAX_LEN
#endif
#ifndef PKG_SQLITE_DB_NAME_MAX_LEN
#define PKG_SQLITE_DB_NAME_MAX_LEN LIB_SQLITE_DB_NAME_MAX_LEN
#endif
#ifndef SQLITE_ASSERT
#define SQLITE_ASSERT(EXPR) \
if (!(EXPR)) \
{ \
printf("(%s) has CHECK failed at %s.", #EXPR, __FUNCTION__); \
while (1); \
}
#endif
#endif

View File

@ -0,0 +1,744 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-10 lizhen9880 first version
*/
/**
* @file student_dao.c
* @brief support SQLite demo using dbhelper api in XiUOS
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023-10-25
*/
/*************************************************
File name: student_dao.c
Description: support SQLite demo using dbhelper api in XiUOS
Others:
History:
1. Date: 2023-10-25
Author: AIIT XUOS Lab
Modification:
1add XiUOS function.
*************************************************/
#include <transform.h>
#ifdef ADD_RTTHREAD_FEATURES
#include <rtthread.h>
#include <dfs_posix.h>
#endif
#ifdef ADD_XIZI_FEATURES
#include <list.h>
#endif
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
#include "dbhelper.h"
#include "student_dao.h"
#define DBG_ENABLE
#define DBG_SECTION_NAME "app.student_dao"
#define DBG_LEVEL DBG_INFO
#define DBG_COLOR
#ifdef ADD_RTTHREAD_FEATURES
#include <rtdbg.h>
static int student_insert_bind(sqlite3_stmt *stmt, int index, void *arg)
{
int rc;
rt_list_t *h = arg, *pos, *n;
student_t *s = RT_NULL;
rt_list_for_each_safe(pos, n, h)
{
s = rt_list_entry(pos, student_t, list);
sqlite3_reset(stmt); //reset the stmt
sqlite3_bind_text(stmt, 1, s->name, strlen(s->name), NULL); //bind the 1st data,is a string
sqlite3_bind_int(stmt, 2, s->score); //bind the 1st data,is a int
rc = sqlite3_step(stmt); //execute the stmt by step
}
if (rc != SQLITE_DONE)
return rc;
return SQLITE_OK;
}
int student_add(rt_list_t *h)
{
return db_nonquery_operator("insert into student(name,score) values (?,?);", student_insert_bind, h);
}
int student_del(int id)
{
return db_nonquery_by_varpara("delete from student where id=?;", "%d", id);
}
int student_del_all(void)
{
return db_nonquery_operator("delete from student;", 0, 0);
}
static int student_update_bind(sqlite3_stmt *stmt, int index, void *arg)
{
int rc;
student_t *s = arg;
sqlite3_bind_text(stmt, 1, s->name, strlen(s->name), NULL);
sqlite3_bind_int(stmt, 2, s->score);
sqlite3_bind_int(stmt, 3, s->id);
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE)
return rc;
return SQLITE_OK;
}
int student_update(student_t *s)
{
return db_nonquery_operator("update student set name=?,score=? where id=?;", student_update_bind, s);
}
static int student_create(sqlite3_stmt *stmt, void *arg)
{
student_t *s = arg;
int ret = sqlite3_step(stmt);
if (ret != SQLITE_ROW)
{
return 0;
}
else
{
s->id = db_stmt_get_int(stmt, 0);
db_stmt_get_text(stmt, 1, s->name);
s->score = db_stmt_get_int(stmt, 2);
}
return ret;
}
int student_get_by_id(student_t *s, int id)
{
int res = db_query_by_varpara("select * from student where id=?;", student_create, s, "%d", id);
return res;
}
void student_free_list(rt_list_t *h)
{
rt_list_t *head = h, *pos, *n;
student_t *p = RT_NULL;
rt_list_for_each_safe(pos, n, head)
{
p = rt_list_entry(pos, student_t, list);
rt_free(p);
}
rt_free(head);
}
void student_print_list(rt_list_t *q)
{
student_t *s = NULL;
for (s = rt_list_entry((q)->next, student_t, list);
&s->list != (q);
s = rt_list_entry(s->list.next, student_t, list))
{
rt_kprintf("id:%d\tname:%s\tscore:%d\n", s->id, s->name, s->score);
}
}
static int student_create_queue(sqlite3_stmt *stmt, void *arg)
{
rt_list_t *q = arg;
student_t *s;
int ret, count = 0;
ret = sqlite3_step(stmt);
if (ret != SQLITE_ROW)
{
return 0;
}
do
{
s = rt_calloc(sizeof(student_t), 1);
if (!s)
{
LOG_E("No enough memory!");
goto __create_student_fail;
}
s->id = db_stmt_get_int(stmt, 0);
db_stmt_get_text(stmt, 1, s->name);
s->score = db_stmt_get_int(stmt, 2);
rt_list_insert_before(q, &(s->list));
count++;
} while ((ret = sqlite3_step(stmt)) == SQLITE_ROW);
return count;
__create_student_fail:
return -1;
}
int student_get_all(rt_list_t *q)
{
return db_query_by_varpara("select * from student;", student_create_queue, q, RT_NULL);
}
static void list_all(void)
{
rt_kprintf("test get all students\n");
rt_list_t *h = rt_calloc(sizeof(student_t), 1);
rt_list_init(h);
int ret = student_get_all(h);
if (ret >= 0)
{
student_print_list(h);
rt_kprintf("record(s):%d\n", ret);
}
else
{
rt_kprintf("Get students information failed");
}
student_free_list(h);
return;
}
int student_get_by_score(rt_list_t *h, int ls, int hs, enum order_type order)
{
char sql[128];
rt_snprintf(sql, 128, "select * from student where score between %d and %d ORDER BY score %s;", ls, hs, order == ASC ? "ASC" : "DESC");
return db_query_by_varpara(sql, student_create_queue, h, RT_NULL);
}
static void list_by_score(int ls, int hs, enum order_type order)
{
rt_list_t *h = rt_calloc(sizeof(rt_list_t), 1);
rt_list_init(h);
rt_kprintf("the student list of score between %d and %d:\n", ls, hs);
int ret = student_get_by_score(h, ls, hs, order);
if (ret >= 0)
{
student_print_list(h);
rt_kprintf("record(s):%d\n", ret);
}
else
{
LOG_E("Get students information failed!");
}
student_free_list(h);
return;
}
static void stu(uint8_t argc, char **argv)
{
if (argc < 2)
{
list_all();
return;
}
else
{
char *cmd = argv[1];
int rand = 0;
if (rt_strcmp(cmd, "add") == 0)
{
int i = 0, count = 0;
if (argc >= 3)
{
count = atol(argv[2]);
}
if (count == 0)
{
count = 1;
}
rt_tick_t ticks = rt_tick_get();
rand = ticks;
rt_list_t *h = (rt_list_t *)rt_calloc(1, sizeof(rt_list_t));
rt_list_init(h);
for (i = 0; i < count; i++)
{
student_t *s = (student_t *)rt_calloc(1, sizeof(student_t));
rand += i;
rand %= 99999;
s->score = (rand % 81) + 20;
sprintf(s->name, "Student%d", rand);
rt_list_insert_before(h, &(s->list));
}
int res = student_add(h);
student_free_list(h);
if (res != SQLITE_OK)
{
LOG_E("add failed!");
}
else
{
ticks = rt_tick_get() - ticks;
rt_kprintf("Insert %d record(s): %dms, speed: %dms/record\n", count,
ticks * 1000 / RT_TICK_PER_SECOND, ticks * 1000 / RT_TICK_PER_SECOND / count);
}
}
else if (rt_strcmp(cmd, "del") == 0)
{
if (argc == 2)
{
if (student_del_all() == SQLITE_OK)
{
rt_kprintf("Del all record success!\n");
}
else
{
rt_kprintf("Del all record failed!\n");
}
}
else
{
rt_uint32_t id = atol(argv[2]);
if (student_del(id) == SQLITE_OK)
{
rt_kprintf("Del record success with id:%d\n", id);
}
else
{
rt_kprintf("Del record failed with id:%d\n", id);
}
}
}
else if (rt_strcmp(cmd, "update") == 0)
{
/* update student record by id */
if (argc >= 5)
{
student_t *s = rt_calloc(sizeof(student_t), 1);
s->id = atol(argv[2]);
rt_strncpy(s->name, argv[3], rt_strlen(argv[3]));
s->score = atol(argv[4]);
if (student_update(s) == SQLITE_OK)
{
rt_kprintf("update record success!\n");
}
else
{
rt_kprintf("update record failed!\n");
}
rt_free(s);
}
else
{
rt_kprintf("usage: stu update id name score\n");
}
}
else if (rt_strcmp(cmd, "score") == 0)
{
/* query student's score between LOW and HIGH. */
if (argc >= 4)
{
enum order_type order = ASC;
int ls = atol(argv[2]);
int hs = atol(argv[3]);
if (rt_strcmp(argv[4], "-d") == 0)
{
order = DESC;
}
list_by_score(ls, hs, order);
}
else
{
rt_kprintf("usage: stu score LOW HIGH [OPTION]\n"
"desc:query student's score between LOW and HIGH.\n"
"OPTION(default ascending):\n -a:ascending\n -d:descending\n"
"e.g: stu score 60 100 or stu score -d 60 100\n");
}
}
else
{
student_t *s = rt_calloc(sizeof(student_t), 1);
rt_uint32_t id = atol(argv[1]);
if (student_get_by_id(s, id) > 0)
{
rt_kprintf("id:%d\t\tname:%s\tscore:%d\n", s->id, s->name, s->score);
}
else
{
rt_kprintf("no record with id:%d\n", id);
}
rt_free(s);
}
}
}
MSH_CMD_EXPORT(stu, student add del update query);
static int create_student_tbl(void)
{
int fd = 0;
db_set_name("/stu_info.db");
fd = open(db_get_name(), O_RDONLY);
rt_kprintf(db_get_name());
if (fd < 0)
{
/* there is not the .db file.create db and table */
const char *sql = "CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);";
return db_create_database(sql);
}
else if (db_table_is_exist("student") > 0)
{
/* there is the table int db.close the db. */
close(fd);
LOG_I("The table has already existed!\n");
return RT_EOK;
}
else
{
/* there is not the table int db.create the table */
const char *sql = "CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);";
return db_create_database(sql);
}
}
MSH_CMD_EXPORT(create_student_tbl, create sqlite db);
#endif
static int student_insert_bind(sqlite3_stmt *stmt, int index, void *arg)
{
int rc = 0;
DoublelistType *h = arg, *node, *node_next;
student_t *s = NULL;
DOUBLE_LIST_FOR_EACH_SAFE(node, node_next, h)
{
s = DOUBLE_LIST_ENTRY(node, student_t, list);
sqlite3_reset(stmt); //reset the stmt
sqlite3_bind_text(stmt, 1, s->name, strlen(s->name), NULL); //bind the 1st data,is a string
sqlite3_bind_int(stmt, 2, s->score); //bind the 1st data,is a int
rc = sqlite3_step(stmt); //execute the stmt by step
}
if (rc != SQLITE_DONE)
return rc;
return SQLITE_OK;
}
int student_add(DoublelistType *h)
{
return db_nonquery_operator("insert into student(name,score) values (?,?);", student_insert_bind, h);
}
int student_del(int id)
{
return db_nonquery_by_varpara("delete from student where id=?;", "%d", id);
}
int student_del_all(void)
{
return db_nonquery_operator("delete from student;", 0, 0);
}
static int student_update_bind(sqlite3_stmt *stmt, int index, void *arg)
{
int rc;
student_t *s = arg;
sqlite3_bind_text(stmt, 1, s->name, strlen(s->name), NULL);
sqlite3_bind_int(stmt, 2, s->score);
sqlite3_bind_int(stmt, 3, s->id);
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE)
return rc;
return SQLITE_OK;
}
int student_update(student_t *s)
{
return db_nonquery_operator("update student set name=?,score=? where id=?;", student_update_bind, s);
}
static int student_create(sqlite3_stmt *stmt, void *arg)
{
student_t *s = arg;
int ret = sqlite3_step(stmt);
if (ret != SQLITE_ROW)
{
return 0;
}
else
{
s->id = db_stmt_get_int(stmt, 0);
db_stmt_get_text(stmt, 1, s->name);
s->score = db_stmt_get_int(stmt, 2);
}
return ret;
}
int student_get_by_id(student_t *s, int id)
{
int res = db_query_by_varpara("select * from student where id=?;", student_create, s, "%d", id);
return res;
}
void student_free_list(DoublelistType *h)
{
DoublelistType *head = h, *node, *node_next;
student_t *p = NULL;
DOUBLE_LIST_FOR_EACH_SAFE(node, node_next, head)
{
p = DOUBLE_LIST_ENTRY(node, student_t, list);
PrivFree(p);
}
PrivFree(head);
}
void student_print_list(DoublelistType *q)
{
student_t *s = NULL;
for (s = DOUBLE_LIST_ENTRY((q)->node_next, student_t, list);
&s->list != (q);
s = DOUBLE_LIST_ENTRY(s->list.node_next, student_t, list))
{
printf("id:%d\tname:%s\tscore:%d\n", s->id, s->name, s->score);
}
}
static int student_create_queue(sqlite3_stmt *stmt, void *arg)
{
DoublelistType *q = arg;
student_t *s;
int ret, count = 0;
ret = sqlite3_step(stmt);
if (ret != SQLITE_ROW)
{
return 0;
}
do
{
s = PrivCalloc(1, sizeof(student_t));
if (!s)
{
printf("No enough memory!");
goto __create_student_fail;
}
s->id = db_stmt_get_int(stmt, 0);
db_stmt_get_text(stmt, 1, s->name);
s->score = db_stmt_get_int(stmt, 2);
AppDoubleListInsertNodeBefore(q, &(s->list));
count++;
} while ((ret = sqlite3_step(stmt)) == SQLITE_ROW);
return count;
__create_student_fail:
return -1;
}
int student_get_all(DoublelistType *q)
{
return db_query_by_varpara("select * from student;", student_create_queue, q, NULL);
}
static void list_all(void)
{
printf("test get all students\n");
DoublelistType *h = PrivCalloc(1, sizeof(student_t));
AppInitDoubleList(h);
int ret = student_get_all(h);
if (ret >= 0)
{
student_print_list(h);
printf("record(s):%d\n", ret);
}
else
{
printf("Get students information failed");
}
student_free_list(h);
return;
}
int student_get_by_score(DoublelistType *h, int ls, int hs, enum order_type order)
{
char sql[128];
snprintf(sql, 128, "select * from student where score between %d and %d ORDER BY score %s;", ls, hs, order == ASC ? "ASC" : "DESC");
return db_query_by_varpara(sql, student_create_queue, h, NULL);
}
static void list_by_score(int ls, int hs, enum order_type order)
{
DoublelistType *h = PrivCalloc(1, sizeof(DoublelistType));
AppInitDoubleList(h);
printf("the student list of score between %d and %d:\n", ls, hs);
int ret = student_get_by_score(h, ls, hs, order);
if (ret >= 0)
{
student_print_list(h);
printf("record(s):%d\n", ret);
}
else
{
printf("Get students information failed!");
}
student_free_list(h);
return;
}
static int stu(int argc, char *argv[])
{
if (argc < 2)
{
list_all();
}
else
{
char *cmd = argv[1];
int rand = 0;
if (strcmp(cmd, "add") == 0)
{
int i = 0, count = 0;
if (argc >= 3)
{
count = atol(argv[2]);
}
if (count == 0)
{
count = 1;
}
int start_time = PrivGetTickTime();
rand = start_time;
DoublelistType *h = (DoublelistType *)PrivCalloc(1, sizeof(DoublelistType));
AppInitDoubleList(h);
for (i = 0; i < count; i++)
{
student_t *s = (student_t *)PrivCalloc(1, sizeof(student_t));
rand += i;
rand %= 99999;
s->score = (rand % 81) + 20;
sprintf(s->name, "Student%d", rand);
AppDoubleListInsertNodeBefore(h, &(s->list));
}
int res = student_add(h);
student_free_list(h);
if (res != SQLITE_OK)
{
printf("add failed!");
}
else
{
int end_time = PrivGetTickTime() - start_time;
printf("Insert %d record(s): %dms, speed: %dms/record\n", count,
end_time, end_time / count);
}
}
else if (strcmp(cmd, "del") == 0)
{
if (argc == 2)
{
if (student_del_all() == SQLITE_OK)
{
printf("Del all record success!\n");
}
else
{
printf("Del all record failed!\n");
}
}
else
{
uint32_t id = atol(argv[2]);
if (student_del(id) == SQLITE_OK)
{
printf("Del record success with id:%d\n", id);
}
else
{
printf("Del record failed with id:%d\n", id);
}
}
}
else if (strcmp(cmd, "update") == 0)
{
/* update student record by id */
if (argc >= 5)
{
student_t *s = PrivCalloc(sizeof(student_t), 1);
s->id = atol(argv[2]);
strncpy(s->name, argv[3], strlen(argv[3]));
s->score = atol(argv[4]);
if (student_update(s) == SQLITE_OK)
{
printf("update record success!\n");
}
else
{
printf("update record failed!\n");
}
PrivFree(s);
}
else
{
printf("usage: stu update id name score\n");
}
}
else if (strcmp(cmd, "score") == 0)
{
/* query student's score between LOW and HIGH. */
if (argc >= 4)
{
enum order_type order = ASC;
int ls = atol(argv[2]);
int hs = atol(argv[3]);
if (strcmp(argv[4], "-d") == 0)
{
order = DESC;
}
list_by_score(ls, hs, order);
}
else
{
printf("usage: stu score LOW HIGH [OPTION]\n"
"desc:query student's score between LOW and HIGH.\n"
"OPTION(default ascending):\n -a:ascending\n -d:descending\n"
"e.g: stu score 60 100 or stu score -d 60 100\n");
}
}
else
{
student_t *s = PrivCalloc(sizeof(student_t), 1);
uint32_t id = atol(argv[1]);
if (student_get_by_id(s, id) > 0)
{
printf("id:%d\t\tname:%s\tscore:%d\n", s->id, s->name, s->score);
}
else
{
printf("no record with id:%d\n", id);
}
PrivFree(s);
}
}
return 0;
}
PRIV_SHELL_CMD_FUNCTION(stu, student add del update query, PRIV_SHELL_CMD_MAIN_ATTR);
static int create_student_tbl(void)
{
int fd = -1;
//init sqlite3
db_helper_init();
db_set_name("/stu_info.db");
fd = PrivOpen("/stu_info.db", O_RDONLY);
printf(db_get_name());
printf(" fd %d\n", fd);
if (fd < 0)
{
/* there is not the .db file.create db and table */
const char *sql = "CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);";
return db_create_database(sql);
}
else if (db_table_is_exist("student") > 0)
{
/* there is the table int db.close the db. */
PrivClose(fd);
printf("The table has already existed!\n");
return 0;
}
else
{
/* there is not the table int db.create the table */
const char *sql = "CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);";
return db_create_database(sql);
}
}
PRIV_SHELL_CMD_FUNCTION(create_student_tbl, create sqlite db, PRIV_SHELL_CMD_FUNC_ATTR);

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-10 lizhen9880 first version
*/
#ifndef __STUDENT_DAO_H__
#define __STUDENT_DAO_H__
#ifdef ADD_RTTHREAD_FEATURES
#include <rtthread.h>
#endif
struct student
{
unsigned int id;
char name[32];
int score;
#ifdef ADD_RTTHREAD_FEATURES
rt_list_t list;
#endif
#ifdef ADD_XIZI_FEATURES
DoublelistType list;
#endif
};
typedef struct student student_t;
/**
* ASC:Ascending
* DESC:Descending
* */
enum order_type
{
ASC = 0,
DESC = 1,
};
#ifdef ADD_RTTHREAD_FEATURES
int student_get_by_id(student_t *e, int id);
int student_get_by_score(rt_list_t *h, int ls, int hs, enum order_type order);
int student_get_all(rt_list_t *q);
int student_add(rt_list_t *h);
int student_del(int id);
int student_del_all(void);
int student_update(student_t *e);
void student_free_list(rt_list_t *h);
void student_print_list(rt_list_t *q);
#endif
#ifdef ADD_XIZI_FEATURES
int student_get_by_id(student_t *e, int id);
int student_get_by_score(DoublelistType *h, int ls, int hs, enum order_type order);
int student_get_all(DoublelistType *q);
int student_add(DoublelistType *h);
int student_del(int id);
int student_del_all(void);
int student_update(student_t *e);
void student_free_list(DoublelistType *h);
void student_print_list(DoublelistType *q);
#endif
#endif

View File

@ -0,0 +1,4 @@
SRC_FILES := xizi_io_methods.c xizi_mutex.c xizi_vfs.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,469 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file xizi_io_methods.c
* @brief support SQLite io function in XiZi kernel
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023-10-16
*/
/*************************************************
File name: xizi_io_methods.c
Description: support SQLite io function in XiZi kernel
Others:
History:
1. Date: 2023-10-16
Author: AIIT XUOS Lab
Modification:
1add xizi vfs io function.
*************************************************/
#include "xizi_port.h"
static int _xizi_io_read(sqlite3_file *file_id, void *pbuf, int cnt, sqlite3_int64 offset)
{
XIZI_SQLITE_FILE_T *file = (XIZI_SQLITE_FILE_T*)file_id;
sqlite3_int64 new_offset;
int r_cnt;
SQLITE_ASSERT(file_id);
SQLITE_ASSERT(offset >= 0);
SQLITE_ASSERT(cnt > 0);
new_offset = PrivLseek(file->fd, offset, SEEK_SET);
if (new_offset != offset) {
return SQLITE_IOERR_READ;
}
do {
r_cnt = PrivRead(file->fd, pbuf, cnt);
if (r_cnt == cnt) {
break;
}
if (r_cnt < 0) {
if (errno != EINTR) {
return SQLITE_IOERR_READ;
}
r_cnt = 1;
continue;
} else if (r_cnt > 0) {
cnt -= r_cnt;
pbuf = (void*)(r_cnt + (char*)pbuf);
}
} while (r_cnt > 0);
if (r_cnt != cnt) {
memset(&((char*)pbuf)[r_cnt], 0, cnt - r_cnt);
return SQLITE_IOERR_SHORT_READ;
}
return SQLITE_OK;
}
static int _xizi_io_write(sqlite3_file* file_id, const void *pbuf, int cnt, sqlite3_int64 offset)
{
XIZI_SQLITE_FILE_T *file = (XIZI_SQLITE_FILE_T*)file_id;
sqlite3_int64 new_offset;
int w_cnt;
SQLITE_ASSERT(file_id);
SQLITE_ASSERT(cnt > 0);
new_offset = PrivLseek(file->fd, offset, SEEK_SET);
if (new_offset != offset) {
return SQLITE_IOERR_WRITE;
}
do {
w_cnt = PrivWrite(file->fd, pbuf, cnt);
if (w_cnt == cnt) {
break;
}
if (w_cnt < 0) {
if (errno != EINTR) {
return SQLITE_IOERR_WRITE;
}
w_cnt = 1;
continue;
} else if (w_cnt > 0) {
cnt -= w_cnt;
pbuf = (void*)(w_cnt + (char*)pbuf);
}
} while (w_cnt > 0);
if (w_cnt != cnt) {
return SQLITE_FULL;
}
return SQLITE_OK;
}
static int _xizi_io_truncate(sqlite3_file* file_id, sqlite3_int64 size)
{
return SQLITE_IOERR_TRUNCATE;
}
static int _xizi_io_sync(sqlite3_file* file_id, int flags)
{
XIZI_SQLITE_FILE_T *file = (XIZI_SQLITE_FILE_T*)file_id;
SQLITE_ASSERT((flags & 0x0F) == SQLITE_SYNC_NORMAL
|| (flags & 0x0F) == SQLITE_SYNC_FULL);
PrivFsync(file->fd);
return SQLITE_OK;
}
static int _xizi_io_file_size(sqlite3_file* file_id, sqlite3_int64 *psize)
{
int rc;
struct stat buf;
XIZI_SQLITE_FILE_T *file = (XIZI_SQLITE_FILE_T*)file_id;
SQLITE_ASSERT(file_id);
rc = PrivFstat(file->fd, &buf);
if (rc != 0) {
return SQLITE_IOERR_FSTAT;
}
*psize = buf.st_size;
/* When opening a zero-size database, the findInodeInfo() procedure
** writes a single byte into that file in order to work around a bug
** in the OS-X msdos filesystem. In order to avoid problems with upper
** layers, we need to report this file size as zero even though it is
** really 1. Ticket #3260.
*/
if (*psize == 1) *psize = 0;
return SQLITE_OK;
}
/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, set *pResOut
** to a non-zero value otherwise *pResOut is set to zero. The return value
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int _xizi_io_check_reserved_lock(sqlite3_file *file_id, int *pResOut)
{
XIZI_SQLITE_FILE_T *file = (XIZI_SQLITE_FILE_T*)file_id;
sem_t psem = file->sem;
int reserved = 0;
/* Check if a thread in this process holds such a lock */
if (file->eFileLock > 1) {
reserved = 1;
}
/* Otherwise see if some other process holds it. */
if (!reserved) {
if (PrivSemaphoreObtainNoWait(&psem) != 0) {
/* someone else has the lock when we are in NO_LOCK */
reserved = (file->eFileLock < 1);
} else {
/* we could have it if we want it */
PrivSemaphoreAbandon(&psem);
}
}
*pResOut = reserved;
return SQLITE_OK;
}
/*
** Lock the file with the lock specified by parameter eFileLock - one
** of the following:
**
** (1) SHARED_LOCK
** (2) RESERVED_LOCK
** (3) PENDING_LOCK
** (4) EXCLUSIVE_LOCK
**
** Sometimes when requesting one lock state, additional lock states
** are inserted in between. The locking might fail on one of the later
** transitions leaving the lock state different from what it started but
** still short of its goal. The following chart shows the allowed
** transitions and the inserted intermediate states:
**
** UNLOCKED -> SHARED
** SHARED -> RESERVED
** SHARED -> (PENDING) -> EXCLUSIVE
** RESERVED -> (PENDING) -> EXCLUSIVE
** PENDING -> EXCLUSIVE
**
** Semaphore locks only really support EXCLUSIVE locks. We track intermediate
** lock states in the sqlite3_file structure, but all locks SHARED or
** above are really EXCLUSIVE locks and exclude all other processes from
** access the file.
**
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
static int _xizi_io_lock(sqlite3_file *file_id, int eFileLock)
{
XIZI_SQLITE_FILE_T *file = (XIZI_SQLITE_FILE_T*)file_id;
sem_t psem = file->sem;
int rc = SQLITE_OK;
/* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
if (file->eFileLock > 0) {
file->eFileLock = eFileLock;
rc = SQLITE_OK;
goto sem_end_lock;
}
/* lock semaphore now but bail out when already locked. */
if (PrivSemaphoreObtainNoWait(&psem) != 0) {
rc = SQLITE_BUSY;
goto sem_end_lock;
}
/* got it, set the type and return ok */
file->eFileLock = eFileLock;
sem_end_lock:
return rc;
}
/*
** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
*/
static int _xizi_io_unlock(sqlite3_file *file_id, int eFileLock)
{
XIZI_SQLITE_FILE_T *file = (XIZI_SQLITE_FILE_T*)file_id;
sem_t psem = file->sem;
SQLITE_ASSERT(eFileLock <= 1);
/* no-op if possible */
if (file->eFileLock == eFileLock) {
return SQLITE_OK;
}
/* shared can just be set because we always have an exclusive */
if (eFileLock == 1) {
file->eFileLock = 1;
return SQLITE_OK;
}
/* no, really unlock. */
PrivSemaphoreAbandon(&psem);
file->eFileLock = 0;
return SQLITE_OK;
}
static int _xizi_io_close(sqlite3_file *file_id)
{
int rc = 0;
XIZI_SQLITE_FILE_T *file = (XIZI_SQLITE_FILE_T*)file_id;
if (file->fd >= 0) {
_xizi_io_unlock(file_id, 0);
PrivSemaphoreDelete(&file->sem);
rc = PrivClose(file->fd);
file->fd = -1;
}
return rc;
}
static int _xizi_fcntl_size_hint(sqlite3_file *file_id, sqlite3_int64 nByte)
{
XIZI_SQLITE_FILE_T *file = (XIZI_SQLITE_FILE_T*)file_id;
if (file->szChunk > 0) {
sqlite3_int64 nSize; /* Required file size */
struct stat buf; /* Used to hold return values of fstat() */
if (PrivFstat(file->fd, &buf)) {
return SQLITE_IOERR_FSTAT;
}
nSize = ((nByte + file->szChunk - 1) / file->szChunk) * file->szChunk;
if (nSize > (sqlite3_int64)buf.st_size) {
/* If the OS does not have posix_fallocate(), fake it. Write a
** single byte to the last byte in each block that falls entirely
** within the extended region. Then, if required, a single byte
** at offset (nSize-1), to set the size of the file correctly.
** This is a similar technique to that used by glibc on systems
** that do not have a real fallocate() call.
*/
int nBlk = 512; /* File-system block size */
int nWrite = 0; /* Number of bytes written by seekAndWrite */
sqlite3_int64 iWrite; /* Next offset to write to */
iWrite = (buf.st_size / nBlk) * nBlk + nBlk - 1;
SQLITE_ASSERT(iWrite >= buf.st_size);
SQLITE_ASSERT(((iWrite + 1) % nBlk) == 0);
for (/*no-op*/; iWrite < nSize + nBlk - 1; iWrite += nBlk) {
if (iWrite >= nSize) {
iWrite = nSize - 1;
}
nWrite = _xizi_io_write(file_id, "", 1, iWrite);
if (nWrite != 1) {
return SQLITE_IOERR_WRITE;
}
}
}
}
return SQLITE_OK;
}
/*
** Information and control of an open file handle.
*/
static int _xizi_io_file_ctrl(sqlite3_file *file_id, int op, void *pArg)
{
XIZI_SQLITE_FILE_T *file = (XIZI_SQLITE_FILE_T*)file_id;
switch( op ) {
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = file->eFileLock;
return SQLITE_OK;
}
case SQLITE_LAST_ERRNO: {
*(int*)pArg = 0;
return SQLITE_OK;
}
case SQLITE_FCNTL_CHUNK_SIZE: {
file->szChunk = *(int *)pArg;
return SQLITE_OK;
}
case SQLITE_FCNTL_SIZE_HINT: {
int rc;
rc = _xizi_fcntl_size_hint(file_id, *(sqlite3_int64 *)pArg);
return rc;
}
case SQLITE_FCNTL_PERSIST_WAL: {
return SQLITE_OK;
}
case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
return SQLITE_OK;
}
case SQLITE_FCNTL_VFSNAME: {
*(char**)pArg = sqlite3_mprintf("%s", file->pvfs->zName);
return SQLITE_OK;
}
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = sqlite3_malloc(file->pvfs->mxPathname );
if( zTFile ) {
_xizi_get_temp_name(file->pvfs->mxPathname, zTFile);
*(char**)pArg = zTFile;
}
return SQLITE_OK;
}
}
return SQLITE_NOTFOUND;
}
// #ifndef SQLITE_DEFAULT_SECTOR_SIZE
// # define SQLITE_DEFAULT_SECTOR_SIZE 4096
// #endif
static int _xizi_io_sector_size(sqlite3_file *file_id)
{
return 4096;
}
static int _xizi_io_device_characteristics(sqlite3_file *file_id)
{
return SQLITE_IOCAP_SAFE_APPEND;
}
/*
** If possible, return a pointer to a mapping of file fd starting at offset
** iOff. The mapping must be valid for at least nAmt bytes.
**
** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
** Finally, if an error does occur, return an SQLite error code. The final
** value of *pp is undefined in this case.
**
** If this function does return a pointer, the caller must eventually
** release the reference by calling unixUnfetch().
*/
static int _xizi_io_fetch(sqlite3_file *file_id, sqlite3_int64 iOff, int nAmt, void **pp)
{
*pp = 0;
return SQLITE_OK;
}
/*
** If the third argument is non-NULL, then this function releases a
** reference obtained by an earlier call to unixFetch(). The second
** argument passed to this function must be the same as the corresponding
** argument that was passed to the unixFetch() invocation.
**
** Or, if the third argument is NULL, then this function is being called
** to inform the VFS layer that, according to POSIX, any existing mapping
** may now be invalid and should be unmapped.
*/
static int _xizi_io_unfetch(sqlite3_file *fd, sqlite3_int64 iOff, void *p)
{
return SQLITE_OK;
}
static const sqlite3_io_methods _xizi_io_method = {
3,
_xizi_io_close,
_xizi_io_read,
_xizi_io_write,
_xizi_io_truncate,
_xizi_io_sync,
_xizi_io_file_size,
_xizi_io_lock,
_xizi_io_unlock,
_xizi_io_check_reserved_lock,
_xizi_io_file_ctrl,
_xizi_io_sector_size,
_xizi_io_device_characteristics,
0,
0,
0,
0,
_xizi_io_fetch,
_xizi_io_unfetch
};

View File

@ -0,0 +1,202 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file xizi_mutex.c
* @brief support SQLite mutex function in XiZi kernel
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023-10-16
*/
/*************************************************
File name: xizi_mutex.c
Description: support SQLite mutex function in XiZi kernel
Others:
History:
1. Date: 2023-10-16
Author: AIIT XUOS Lab
Modification:
1add xizi mutex function.
*************************************************/
#include "xizi_port.h"
struct sqlite3_mutex {
pthread_mutex_t mutex; /* Mutex controlling the lock */
int id; /* Mutex type */
};
static void sqlite3MemoryBarrier(void)
{
}
/*
** Initialize and deinitialize the mutex subsystem.
The argument to sqlite3_mutex_alloc() must one of these integer constants:
SQLITE_MUTEX_FAST
SQLITE_MUTEX_RECURSIVE
SQLITE_MUTEX_STATIC_MASTER
SQLITE_MUTEX_STATIC_MEM
SQLITE_MUTEX_STATIC_OPEN
SQLITE_MUTEX_STATIC_PRNG
SQLITE_MUTEX_STATIC_LRU
SQLITE_MUTEX_STATIC_PMEM
SQLITE_MUTEX_STATIC_APP1
SQLITE_MUTEX_STATIC_APP2
SQLITE_MUTEX_STATIC_APP3
SQLITE_MUTEX_STATIC_VFS1
SQLITE_MUTEX_STATIC_VFS2
SQLITE_MUTEX_STATIC_VFS3
The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
cause sqlite3_mutex_alloc() to create a new mutex. The new mutex is recursive
when SQLITE_MUTEX_RECURSIVE is used but not necessarily so when SQLITE_MUTEX_FAST
is used. The mutex implementation does not need to make a distinction between
SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does not want to.
SQLite will only request a recursive mutex in cases where it really needs one.
If a faster non-recursive mutex implementation is available on the host platform,
the mutex subsystem might return such a mutex in response to SQLITE_MUTEX_FAST.
The other allowed parameters to sqlite3_mutex_alloc()
(anything other than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return
a pointer to a static preexisting mutex. Nine static mutexes are used by the
current version of SQLite. Future versions of SQLite may add additional static
mutexes. Static mutexes are for internal use by SQLite only. Applications that
use SQLite mutexes should use only the dynamic mutexes returned by SQLITE_MUTEX_FAST
or SQLITE_MUTEX_RECURSIVE.
Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST or SQLITE_MUTEX_RECURSIVE)
is used then sqlite3_mutex_alloc() returns a different mutex on every call.
For the static mutex types, the same mutex is returned on every call that has the same type number.
*/
static sqlite3_mutex _static_mutex[12];
static int _xizi_mtx_init(void)
{
int i;
int err;
for (i = 0; i < sizeof(_static_mutex) / sizeof(_static_mutex[0]); i++) {
err = PrivMutexCreate(&_static_mutex[i].mutex, 0);
if (err != 0) {
return SQLITE_ERROR;
}
}
return SQLITE_OK;
}
static int _xizi_mtx_end(void)
{
int i;
int err;
for (i = 0; i < sizeof(_static_mutex) / sizeof(_static_mutex[0]); i++)
{
err = PrivMutexDelete(&_static_mutex[i].mutex);
if (err != 0) {
return SQLITE_ERROR;
}
}
return SQLITE_OK;
}
static sqlite3_mutex * _xizi_mtx_alloc(int id)
{
sqlite3_mutex *p = NULL;
switch (id)
{
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE:
p = sqlite3_malloc(sizeof(sqlite3_mutex));
if (p != NULL) {
PrivMutexCreate(&p->mutex, 0);
p->id = id;
}
break;
default:
SQLITE_ASSERT(id - 2 >= 0);
// SQLITE_ASSERT(id - 2 < ArraySize(_static_mutex));
p = &_static_mutex[id - 2];
p->id = id;
break;
}
return p;
}
static void _xizi_mtx_free(sqlite3_mutex * p)
{
SQLITE_ASSERT(p != 0);
PrivMutexDelete(&p->mutex);
switch (p->id) {
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE:
sqlite3_free(p);
break;
default:
break;
}
}
static void _xizi_mtx_enter(sqlite3_mutex *p)
{
SQLITE_ASSERT(p != 0);
PrivMutexObtain(&p->mutex);
}
static int _xizi_mtx_try(sqlite3_mutex *p)
{
SQLITE_ASSERT(p != 0);
if (PrivMutexObtain(&p->mutex) != 0) {
return SQLITE_BUSY;
}
return SQLITE_OK;
}
static void _xizi_mtx_leave(sqlite3_mutex *p)
{
SQLITE_ASSERT(p != 0);
PrivMutexAbandon(&p->mutex);
}
static sqlite3_mutex_methods const *sqlite3DefaultMutex(void)
{
static const sqlite3_mutex_methods sMutex = {
_xizi_mtx_init,
_xizi_mtx_end,
_xizi_mtx_alloc,
_xizi_mtx_free,
_xizi_mtx_enter,
_xizi_mtx_try,
_xizi_mtx_leave,
0,
0
};
return &sMutex;
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file xizi_port.h
* @brief support SQLite define for xizi port files
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023-10-25
*/
/*************************************************
File name: xizi_port.h
Description: support SQLite define for xizi port files
Others:
History:
1. Date: 2023-10-25
Author: AIIT XUOS Lab
Modification:
1modify ifndef description
*************************************************/
#ifndef _XIZI_PORT_H_
#define _XIZI_PORT_H_
#include <transform.h>
#include <sqlite_config_xiuos.h>
#include <sqlite3.h>
typedef struct
{
sqlite3_io_methods const *pMethod;
sqlite3_vfs *pvfs;
int fd;
int eFileLock;
int szChunk;
sem_t sem;
} XIZI_SQLITE_FILE_T;
int _xizi_get_temp_name(int nBuf, char *zBuf);
#endif

View File

@ -0,0 +1,668 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file xizi_vfs.c
* @brief support SQLite vfs function in XiZi kernel
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023-10-16
*/
/*************************************************
File name: xizi_vfs.c
Description: support SQLite vfs function in XiZi kernel
Others:
History:
1. Date: 2023-10-16
Author: AIIT XUOS Lab
Modification:
1add xizi vfs function.
*************************************************/
#include "xizi_port.h"
#ifndef SQLITE_OMIT_LOAD_EXTENSION
#error "not support load extension, compile with SQLITE_OMIT_LOAD_EXTENSION."
#endif
#define MAX_PATHNAME 256
/*
** Define various macros that are missing from some systems.
*/
#ifndef O_LARGEFILE
# define O_LARGEFILE 0
#endif
#ifdef SQLITE_DISABLE_LFS
# undef O_LARGEFILE
# define O_LARGEFILE 0
#endif
#ifndef O_NOFOLLOW
# define O_NOFOLLOW 0
#endif
#ifndef O_BINARY
# define O_BINARY 0
#endif
#ifndef RT_USING_NEWLIB
#ifndef EINTR
#define EINTR 4 /* Interrupted system call */
#endif
#ifndef ENOLCK
#define ENOLCK 46 /* No record locks available */
#endif
#ifndef EACCES
#define EACCES 13 /* Permission denied */
#endif
#ifndef EPERM
#define EPERM 1 /* Operation not permitted */
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT 145 /* Connection timed out */
#endif
#ifndef ENOTCONN
#define ENOTCONN 134 /* Transport endpoint is not connected */
#endif
#if defined(__GNUC__) || defined(__ADSPBLACKFIN__)
int _gettimeofday(struct timeval *tp, void *ignore) __attribute__((weak));
int _gettimeofday(struct timeval *tp, void *ignore)
#elif defined(__CC_ARM)
__weak int _gettimeofday(struct timeval *tp, void *ignore)
#elif defined(__IAR_SYSTEMS_ICC__)
#if __VER__ > 540
__weak
#endif
int _gettimeofday(struct timeval *tp, void *ignore)
#else
int _gettimeofday(struct timeval *tp, void *ignore)
#endif
{
return 0;
}
#endif
static int _Access(const char *pathname, int mode)
{
int fd = -1;
fd = PrivOpen(pathname, O_RDONLY);
if (fd >= 0) {
PrivClose(fd);
return 0;
}
return -1;
}
#define _XIZI_LOG_ERROR(a,b,c) _xizi_log_error_at_line(a,b,c,__LINE__)
static int _xizi_log_error_at_line(
int errcode, /* SQLite error code */
const char *zFunc, /* Name of OS function that failed */
const char *zPath, /* File path associated with error */
int iLine /* Source line number where error occurred */
)
{
char *zErr; /* Message from strerror() or equivalent */
int iErrno = errno; /* Saved syscall error number */
/* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
** the strerror() function to obtain the human-readable error message
** equivalent to errno. Otherwise, use strerror_r().
*/
#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
char aErr[80];
memset(aErr, 0, sizeof(aErr));
zErr = aErr;
/* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
** assume that the system provides the GNU version of strerror_r() that
** returns a pointer to a buffer containing the error message. That pointer
** may point to aErr[], or it may point to some static storage somewhere.
** Otherwise, assume that the system provides the POSIX version of
** strerror_r(), which always writes an error message into aErr[].
**
** If the code incorrectly assumes that it is the POSIX version that is
** available, the error message will often be an empty string. Not a
** huge problem. Incorrectly concluding that the GNU version is available
** could lead to a segfault though.
*/
#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
zErr =
#endif
strerror_r(iErrno, aErr, sizeof(aErr)-1);
#elif SQLITE_THREADSAFE
/* This is a threadsafe build, but strerror_r() is not available. */
zErr = "";
#else
/* Non-threadsafe build, use strerror(). */
zErr = strerror(iErrno);
#endif
if( zPath==0 )
zPath = "";
sqlite3_log(errcode, "os_xizi.c:%d: (%d) %s(%s) - %s",
iLine, iErrno, zFunc, zPath, zErr);
return errcode;
}
static const char* _xizi_temp_file_dir(void)
{
const char *azDirs[] = {
0,
"/sql",
"/sql/tmp"
"/tmp",
0 /* List terminator */
};
unsigned int i;
struct stat buf;
const char *zDir = 0;
azDirs[0] = sqlite3_temp_directory;
for (i = 0; i < sizeof(azDirs) / sizeof(azDirs[0]); zDir = azDirs[i++])
{
if( zDir == 0 ) continue;
if( PrivStat(zDir, &buf) ) continue;
if( !S_ISDIR(buf.st_mode) ) continue;
break;
}
return zDir;
}
/*
** Create a temporary file name in zBuf. zBuf must be allocated
** by the calling process and must be big enough to hold at least
** pVfs->mxPathname bytes.
*/
int _xizi_get_temp_name(int nBuf, char *zBuf)
{
const unsigned char zChars[] = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
unsigned int i, j;
const char *zDir;
zDir = _xizi_temp_file_dir();
if (zDir == 0)
{
zDir = ".";
}
/* Check that the output buffer is large enough for the temporary file
** name. If it is not, return SQLITE_ERROR.
*/
if ((strlen(zDir) + strlen("etilqs_") + 18) >= (size_t)nBuf)
{
return SQLITE_ERROR;
}
do {
sqlite3_snprintf(nBuf-18, zBuf, "%s/""etilqs_", zDir);
j = (int)strlen(zBuf);
sqlite3_randomness(15, &zBuf[j]);
for (i = 0; i < 15; i++, j++)
{
zBuf[j] = (char)zChars[((unsigned char)zBuf[j]) % (sizeof(zChars) - 1)];
}
zBuf[j] = 0;
zBuf[j + 1] = 0;
} while (_Access(zBuf, 0) == 0);
return SQLITE_OK;
}
#include "xizi_io_methods.c"
/*
** Invoke open(). Do so multiple times, until it either succeeds or
** fails for some reason other than EINTR.
**
** If the file creation mode "m" is 0 then set it to the default for
** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
** 0644) as modified by the system umask. If m is not 0, then
** make the file creation mode be exactly m ignoring the umask.
**
** The m parameter will be non-zero only when creating -wal, -journal,
** and -shm files. We want those files to have *exactly* the same
** permissions as their original database, unadulterated by the umask.
** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
** transaction crashes and leaves behind hot journals, then any
** process that is able to write to the database will also be able to
** recover the hot journals.
*/
static int _xizi_fs_open(const char *file_path, int f, mode_t m)
{
int fd = -1;
while (fd < 0)
{
fd = PrivOpen(file_path, f);
if (fd < 0)
{
if (errno == EINTR)
continue;
break;
}
}
return fd;
}
static int _xizi_vfs_open(sqlite3_vfs *pvfs, const char *file_path, sqlite3_file *file_id, int flags, int *pOutFlags)
{
XIZI_SQLITE_FILE_T *p;
int fd;
int eType = flags & 0xFFFFFF00; /* Type of file to open */
int rc = SQLITE_OK; /* Function Return Code */
int openFlags = 0;
mode_t openMode = 0;
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
int isCreate = (flags & SQLITE_OPEN_CREATE);
int isReadonly = (flags & SQLITE_OPEN_READONLY);
int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
/* If argument zPath is a NULL pointer, this function is required to open
** a temporary file. Use this buffer to store the file name in.
*/
char zTmpname[MAX_PATHNAME + 2];
p = (XIZI_SQLITE_FILE_T*)file_id;
/* Check the following statements are true:
**
** (a) Exactly one of the READWRITE and READONLY flags must be set, and
** (b) if CREATE is set, then READWRITE must also be set, and
** (c) if EXCLUSIVE is set, then CREATE must also be set.
** (d) if DELETEONCLOSE is set, then CREATE must also be set.
*/
SQLITE_ASSERT((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
SQLITE_ASSERT(isCreate==0 || isReadWrite);
SQLITE_ASSERT(isExclusive==0 || isCreate);
SQLITE_ASSERT(isDelete==0 || isCreate);
/* The main DB, main journal, WAL file and master journal are never
** automatically deleted. Nor are they ever temporary files. */
SQLITE_ASSERT( (!isDelete && file_path) || eType!=SQLITE_OPEN_MAIN_DB );
SQLITE_ASSERT( (!isDelete && file_path) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
SQLITE_ASSERT( (!isDelete && file_path) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
SQLITE_ASSERT( (!isDelete && file_path) || eType!=SQLITE_OPEN_WAL );
/* Assert that the upper layer has set one of the "file-type" flags. */
SQLITE_ASSERT( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
/* Database filenames are double-zero terminated if they are not
** URIs with parameters. Hence, they can always be passed into
** sqlite3_uri_parameter(). */
SQLITE_ASSERT((eType != SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) || file_path[strlen(file_path) + 1] == 0);
memset(p, 0, sizeof(XIZI_SQLITE_FILE_T));
if (!file_path)
{
rc = _xizi_get_temp_name(MAX_PATHNAME + 2, zTmpname);
if (rc != SQLITE_OK )
{
return rc;
}
file_path = zTmpname;
/* Generated temporary filenames are always double-zero terminated
** for use by sqlite3_uri_parameter(). */
SQLITE_ASSERT(file_path[strlen(file_path) + 1] == 0);
}
/* Determine the value of the flags parameter passed to POSIX function
** open(). These must be calculated even if open() is not called, as
** they may be stored as part of the file handle and used by the
** 'conch file' locking functions later on. */
if (isReadonly) openFlags |= O_RDONLY;
if (isReadWrite) openFlags |= O_RDWR;
if (isCreate) openFlags |= O_CREAT;
if (isExclusive) openFlags |= (O_EXCL | O_NOFOLLOW);
openFlags |= (O_LARGEFILE | O_BINARY);
fd = _xizi_fs_open(file_path, openFlags, openMode);
if (fd < 0 && (errno != -EISDIR) && isReadWrite && !isExclusive)
{
/* Failed to open the file for read/write access. Try read-only. */
flags &= ~(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
openFlags &= ~(O_RDWR | O_CREAT);
flags |= SQLITE_OPEN_READONLY;
openFlags |= O_RDONLY;
isReadonly = 1;
fd = _xizi_fs_open(file_path, openFlags, openMode);
}
if (fd < 0)
{
// rc = _XIZI_LOG_ERROR(SQLITE_CANTOPEN_BKPT, "open", file_path);
printf("%s line %d open %s fd failed\n", __func__, __LINE__, file_path);
return rc;
}
if (pOutFlags)
{
*pOutFlags = flags;
}
if (isDelete)
{
PrivUnlink(file_path);
}
p->fd = fd;
p->pMethod = &_xizi_io_method;
p->eFileLock = 0;
p->szChunk = 0;
p->pvfs = pvfs;
PrivSemaphoreCreate(&p->sem, 0, 1);
return rc;
}
int _xizi_vfs_delete(sqlite3_vfs* pvfs, const char *file_path, int syncDir)
{
int rc = SQLITE_OK;
if (PrivUnlink(file_path) == (-1))
{
if (errno == -ENOENT)
{
rc = SQLITE_IOERR_DELETE_NOENT;
}
else
{
rc = _XIZI_LOG_ERROR(SQLITE_IOERR_DELETE, "unlink", file_path);
}
return rc;
}
// sync dir: open dir -> fsync -> close
if ((syncDir & 1) != 0)
{
int ii;
int fd = -1;
char zDirname[MAX_PATHNAME + 1];
sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", file_path);
for (ii=(int)strlen(zDirname); ii > 1 && zDirname[ii] != '/'; ii--);
if (ii > 0)
{
zDirname[ii] = '\0';
fd = _xizi_fs_open(zDirname, O_RDONLY | O_BINARY, 0);
}
if (fd >= 0)
{
if (PrivFsync(fd))
{
rc = _XIZI_LOG_ERROR(SQLITE_IOERR_DIR_FSYNC, "fsync", file_path);
}
PrivClose(fd);
}
rc = SQLITE_OK;
}
return rc;
}
static int _xizi_vfs_access(sqlite3_vfs* pvfs, const char *file_path, int flags, int *pResOut)
{
int amode = 0;
#ifndef F_OK
# define F_OK 0
#endif
#ifndef R_OK
# define R_OK 4
#endif
#ifndef W_OK
# define W_OK 2
#endif
switch (flags)
{
case SQLITE_ACCESS_EXISTS:
amode = F_OK;
break;
case SQLITE_ACCESS_READWRITE:
amode = W_OK | R_OK;
break;
case SQLITE_ACCESS_READ:
amode = R_OK;
break;
default:
_XIZI_LOG_ERROR(flags, "access", file_path);
return -1;
}
*pResOut = (_Access(file_path, amode) == 0);
if (flags == SQLITE_ACCESS_EXISTS && *pResOut)
{
struct stat buf;
if (0 == PrivStat(file_path, &buf) && (buf.st_size == 0))
{
*pResOut = 0;
}
}
return SQLITE_OK;
}
static int _xizi_vfs_fullpathname(sqlite3_vfs* pvfs, const char *file_path, int nOut, char *zOut)
{
SQLITE_ASSERT(pvfs->mxPathname == MAX_PATHNAME);
zOut[nOut - 1] = '\0';
if (file_path[0] == '/')
{
sqlite3_snprintf(nOut, zOut, "%s", file_path);
}
else
{
int nCwd;
if (PrivGetcwd(zOut, nOut - 1) == 0)
{
printf("%s line %d get ced %s failed\n", __func__, __LINE__, file_path);
return -1;
}
nCwd = (int)strlen(zOut);
sqlite3_snprintf(nOut - nCwd, &zOut[nCwd], "/%s", file_path);
}
return SQLITE_OK;
}
static int _xizi_vfs_randomness(sqlite3_vfs* pvfs, int nByte, char *zOut)
{
SQLITE_ASSERT((size_t)nByte >= (sizeof(time_t) + sizeof(int)));
memset(zOut, 0, nByte);
{
int i;
char tick8, tick16;
tick8 = (char)PrivGetTickTime();
tick16 = (char)(PrivGetTickTime() >> 8);
for (i = 0; i < nByte; i++)
{
zOut[i] = (char)(i ^ tick8 ^ tick16);
tick8 = zOut[i];
tick16 = ~(tick8 ^ tick16);
}
}
return nByte;
}
static int _xizi_vfs_sleep(sqlite3_vfs* pvfs, int microseconds)
{
int millisecond = (microseconds + 999) / 1000;
PrivTaskDelay(millisecond);
return millisecond * 1000;
}
static int _xizi_vfs_current_time_int64(sqlite3_vfs*, sqlite3_int64*);
static int _xizi_vfs_current_time(sqlite3_vfs* pvfs, double* pnow)
{
sqlite3_int64 i = 0;
int rc;
rc = _xizi_vfs_current_time_int64(0, &i);
*pnow = i / 86400000.0;
return rc;
}
static int _xizi_vfs_get_last_error(sqlite3_vfs* pvfs, int nBuf, char *zBuf)
{
return 0;
}
static int _xizi_vfs_current_time_int64(sqlite3_vfs* pvfs, sqlite3_int64*pnow)
{
#ifndef NO_GETTOD
#define NO_GETTOD 1
#endif
static const sqlite3_int64 rtthreadEpoch = 24405875 * (sqlite3_int64)8640000;
int rc = SQLITE_OK;
#if defined(NO_GETTOD)
time_t t;
time(&t);
*pnow = ((sqlite3_int64)t) * 1000 + rtthreadEpoch;
#else
struct timeval sNow;
if (gettimeofday(&sNow, 0) == 0)
{
*pnow = rtthreadEpoch + 1000 * (sqlite3_int64)sNow.tv_sec + sNow.tv_usec / 1000;
}
else
{
rc = SQLITE_ERROR;
}
#endif
#ifdef SQLITE_TEST
if( sqlite3_current_time )
{
*pnow = 1000 * (sqlite3_int64)sqlite3_current_time + rtthreadEpoch;
}
#endif
return rc;
}
static int _xizi_vfs_set_system_call(sqlite3_vfs* pvfs, const char *file_path, sqlite3_syscall_ptr pfn)
{
return SQLITE_NOTFOUND;
}
static sqlite3_syscall_ptr _xizi_vfs_get_system_call(sqlite3_vfs* pvfs, const char *file_path)
{
return 0;
}
static const char* _xizi_vfs_next_system_call(sqlite3_vfs *pvfs, const char *file_path)
{
return 0;
}
/*
** Initialize and deinitialize the operating system interface.
*/
SQLITE_API int sqlite3_os_init(void)
{
static sqlite3_vfs _xizi_vfs = {
3, /* iVersion */
sizeof(XIZI_SQLITE_FILE_T), /* szOsFile */
MAX_PATHNAME, /* mxPathname */
0, /* pNext */
"xiuos", /* zName */
0, /* pAppData */
_xizi_vfs_open, /* xOpen */
_xizi_vfs_delete, /* xDelete */
_xizi_vfs_access, /* xAccess */
_xizi_vfs_fullpathname, /* xFullPathname */
0, /* xDlOpen */
0, /* xDlError */
0, /* xDlSym */
0, /* xDlClose */
_xizi_vfs_randomness, /* xRandomness */
_xizi_vfs_sleep, /* xSleep */
_xizi_vfs_current_time, /* xCurrentTime */
_xizi_vfs_get_last_error, /* xGetLastError */
_xizi_vfs_current_time_int64, /* xCurrentTimeInt64 */
_xizi_vfs_set_system_call, /* xSetSystemCall */
_xizi_vfs_get_system_call, /* xGetSystemCall */
_xizi_vfs_next_system_call, /* xNextSystemCall */
};
sqlite3_vfs_register(&_xizi_vfs, 1);
return SQLITE_OK;
}
SQLITE_API int sqlite3_os_end(void)
{
return SQLITE_OK;
}

View File

@ -14,7 +14,9 @@
time_t time(time_t *t)
{
NULL_PARAM_CHECK(t);
if (NULL == t) {
return 0;
}
time_t current = 0;
#ifdef RESOURCES_RTC

View File

@ -20,10 +20,14 @@ xiuos/APP_Framework/lib/lorawan
```
# 下载代码
# 进入APP_Framework/lib/lorawan目录下载更新子模块
# 进入APP_Framework/lib/lorawan目录下载更新子模块,首先执行以下命令:
git submodule init
# 若需要使用lora_radio_driver子模块执行以下命令
git submodule update APP_Framework/lib/lorawan/lora_radio_driver
# 若需要使用lorawan_devicenode子模块执行以下命令
git submodule update APP_Framework/lib/lorawan/lorawan_devicenode
# 若需要使用lorawan_gateway_single_channel子模块执行以下命令
git submodule update APP_Framework/lib/lorawan/lorawan_gateway_single_channel
# 进入 APP_Framework/lib/lorawan/Kconfig 配置增加子模块source路径从而编译时可找到相应lib的配置
menuconfig LIB_USING_LORAWAN_GATEWAY_SC

@ -1 +1 @@
Subproject commit a94c007cb4ee726cc29b10626f8bbfc19c989b89
Subproject commit 2d8abd3eff2a2d5257e17c7f59acb2ba938cb90e

@ -1 +1 @@
Subproject commit 254754bc7d06011cbec4655cd229c8ccfb95240b
Subproject commit 197c320b9917366b6107db30b05bbb51254e7eb4

@ -1 +1 @@
Subproject commit ac1c6516ec9b2998c0c50796a4e5a8b78781dc8c
Subproject commit 6ec2a3d2645b63a6d3d9c4db9f23c653525efbdf

View File

@ -867,4 +867,6 @@ menu "lib using LVGL"
endmenu
endif
source "$APP_DIR/lib/lvgl/examples/Kconfig"
endmenu

View File

@ -0,0 +1,8 @@
menu "lvgl image display parameter settings"
menuconfig LVGL_WIDTH
int "Set the width of the image."
default 320
menuconfig LVGL_HEIGHT
int "set the height of the image."
default 320
endmenu

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,14 +1,15 @@
#include "../../lv_examples.h"
#include <transform.h>
#if LV_USE_IMG && LV_BUILD_EXAMPLES
void lv_example_aoteman(void)
void lv_example_show(void)
{
LV_IMG_DECLARE(aoteman);
LV_IMG_DECLARE(xiuos);
lv_obj_t * img1 = lv_img_create(lv_scr_act());
lv_img_set_src(img1, &aoteman);
lv_img_set_src(img1, &xiuos);
lv_obj_align(img1, LV_ALIGN_CENTER, 0, -20);
lv_obj_set_size(img1, 320, 240);
lv_obj_set_size(img1, LVGL_WIDTH, LVGL_HEIGHT);
lv_obj_t * img2 = lv_img_create(lv_scr_act());
lv_img_set_src(img2, LV_SYMBOL_OK "Accept");

View File

@ -0,0 +1,33 @@
menu "lib using MQTT"
menuconfig TOOL_USING_MQTT
bool "Enable support MQTT function"
default n
select SUPPORT_CONNECTION_FRAMEWORK
select CONNECTION_ADAPTER_4G
if TOOL_USING_MQTT
menu "MQTT connection parameter configuration."
config PLATFORM_PRODUCTKEY
string "Product Key, used to identify a product."
default "iv74vebCdJC"
config CLIENT_DEVICENAME
string "Device name, used to identify a client device."
default "D001"
config CLIENT_DEVICESECRET
string "Device secret, used for device authentication and data encryption."
default "d2e613c4f714b6b0774bd7b68eeceae3"
config PLATFORM_SERVERIP
string "mqtt platform server ip."
default "101.133.196.127"
config PLATFORM_SERVERPORT
string "mqtt platform server port."
default "1883"
endmenu
endif
endmenu

View File

@ -0,0 +1,3 @@
SRC_FILES := platform_mqtt.c utils_hmacsha1.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,438 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: platform_mqtt.c
* @brief: platform_mqtt.c file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2023/7/27
*
*/
#include <string.h>
#include <stdint.h>
#include <adapter.h>
#include <transform.h>
#include "platform_mqtt.h"
MQTT_TCB Platform_mqtt; //创建一个用于连接云平台mqtt的结构体
static struct Adapter *adapter;
static const uint8_t parket_connetAck[] = {0x20,0x02,0x00,0x00}; //连接成功服务器回应报文
static const uint8_t parket_disconnet[] = {0xE0,0x00}; //客户端主动断开连接发送报文
static const uint8_t parket_heart[] = {0xC0,0x00}; //客户端发送保活心跳包
static const uint8_t parket_subAck[] = {0x90,0x03,0x00,0x0A,0x01}; //订阅成功服务器回应报文
static const uint8_t parket_unsubAck[] = {0xB0,0x02,0x00,0x0A}; //取消订阅成功服务器回应报文
static uint8_t mqtt_rxbuf[16];
/*******************************************************************************
* : AdapterNetActive
* : 使,TCP服务器并进入透传模式使4G方式
* :
* : 0,
*******************************************************************************/
int AdapterNetActive(void)
{
int ret = 0;
uint32_t baud_rate = BAUD_RATE_115200;
adapter = AdapterDeviceFindByName(ADAPTER_4G_NAME);
adapter->socket.socket_id = 0;
ret = AdapterDeviceOpen(adapter);
if (ret < 0)
{
goto out;
}
ret = AdapterDeviceControl(adapter, OPE_INT, &baud_rate);
if (ret < 0)
{
goto out;
}
ret = AdapterDeviceConnect(adapter, CLIENT, PLATFORM_SERVERIP, PLATFORM_SERVERPORT, IPV4);
if (ret < 0)
{
goto out;
}
out:
if (ret < 0)
{
AdapterDeviceClose(adapter);
}
return ret;
}
/*******************************************************************************
* : MQTT_Send
* : MQTT client数据发送函数
* : buf:,buflen:
* : 0,-1
*******************************************************************************/
int MQTT_Send(const uint8_t* buf, int buflen)
{
return AdapterDeviceSend(adapter, buf, buflen) ;
}
/*******************************************************************************
* : MQTT_Recv
* : MQTT client数据接收函数
* : buf:,buflen:
* : ,-1
*******************************************************************************/
int MQTT_Recv(uint8_t* buf, int buflen)
{
return AdapterDeviceRecv(adapter, buf, buflen) ;
}
/*******************************************************************************
* : MQTT_Connect
* : MQTT服务器
* :
* : 0,1
*******************************************************************************/
int MQTT_Connect(void)
{
uint8_t TryConnect_time = 10; //尝试登录次数
uint8_t passwdtemp[PASSWARD_SIZE];
memset(&Platform_mqtt,0,sizeof(Platform_mqtt));
sprintf(Platform_mqtt.ClientID,"%s|securemode=3,signmethod=hmacsha1|",CLIENT_DEVICENAME); //构建客户端ID并存入缓冲区
sprintf(Platform_mqtt.Username,"%s&%s",CLIENT_DEVICENAME,PLATFORM_PRODUCTKEY); //构建用户名并存入缓冲区
memset(passwdtemp,0,sizeof(passwdtemp));
sprintf(passwdtemp,"clientId%sdeviceName%sproductKey%s",CLIENT_DEVICENAME,CLIENT_DEVICENAME,PLATFORM_PRODUCTKEY); //构建加密时的明文
utils_hmac_sha1(passwdtemp,strlen(passwdtemp),Platform_mqtt.Passward,(char *)CLIENT_DEVICESECRET,strlen(CLIENT_DEVICESECRET)); //以DeviceSecret为秘钥对temp中的明文进行hmacsha1加密即为密码
Platform_mqtt.MessageID = 0; //报文标识符清零,CONNECT报文虽然不需要添加报文标识符,但是CONNECT报文是第一个发送的报文,在此清零报文标识符为后续报文做准备
Platform_mqtt.Fixed_len = 1; //CONNECT报文固定报头长度暂定为1
Platform_mqtt.Variable_len = 10; //CONNECT报文可变报头长度为10
Platform_mqtt.Payload_len = (2+strlen(Platform_mqtt.ClientID)) + (2+strlen(Platform_mqtt.Username)) + (2+strlen(Platform_mqtt.Passward)); //CONNECT报文中负载长度
Platform_mqtt.Remaining_len = Platform_mqtt.Variable_len + Platform_mqtt.Payload_len; //剩余长度=可变报头长度+负载长度
memset(Platform_mqtt.Pack_buff,0,sizeof(Platform_mqtt.Pack_buff));
Platform_mqtt.Pack_buff[0] = 0x10; //CONNECT报文 固定报头第1个字节0x10
do{
if((Platform_mqtt.Remaining_len/128) == 0)
{
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len] = Platform_mqtt.Remaining_len;
}
else
{
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len] = (Platform_mqtt.Remaining_len%128)|0x80;
}
Platform_mqtt.Fixed_len++;
Platform_mqtt.Remaining_len = Platform_mqtt.Remaining_len/128;
}while(Platform_mqtt.Remaining_len);
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+0] = 0x00; //CONNECT报文,可变报头第1个字节:固定0x00
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+1] = 0x04; //CONNECT报文,可变报头第2个字节:固定0x04
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+2] = 0x4D; //CONNECT报文,可变报头第3个字节:固定0x4D,大写字母M
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+3] = 0x51; //CONNECT报文,可变报头第4个字节:固定0x51,大写字母Q
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+4] = 0x54; //CONNECT报文,可变报头第5个字节:固定0x54,大写字母T
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+5] = 0x54; //CONNECT报文,可变报头第6个字节:固定0x54,大写字母T
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+6] = 0x04; //CONNECT报文,可变报头第7个字节:固定0x04
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+7] = 0xC2; //CONNECT报文,可变报头第8个字节:使能用户名和密码校验,不使用遗嘱功能,不保留会话功能
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+8] = KEEPALIVE_TIME/256; //CONNECT报文,可变报头第9个字节:保活时间高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+9] = KEEPALIVE_TIME%256; //CONNECT报文,可变报头第10个字节:保活时间低字节,单位s
/* CLIENT_ID */
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+10] = strlen(Platform_mqtt.ClientID)/256; //客户端ID长度高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+11] = strlen(Platform_mqtt.ClientID)%256; //客户端ID长度低字节
memcpy(&Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+12],Platform_mqtt.ClientID,strlen(Platform_mqtt.ClientID)); //复制过来客户端ID字串
/* USER_NAME */
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+12+strlen(Platform_mqtt.ClientID)] = strlen(Platform_mqtt.Username)/256; //用户名长度高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+13+strlen(Platform_mqtt.ClientID)] = strlen(Platform_mqtt.Username)%256; //用户名长度低字节
memcpy(&Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+14+strlen(Platform_mqtt.ClientID)],Platform_mqtt.Username,strlen(Platform_mqtt.Username)); //复制过来用户名字串
/* PASSWARD */
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+14+strlen(Platform_mqtt.ClientID)+strlen(Platform_mqtt.Username)] = strlen(Platform_mqtt.Passward)/256; //密码长度高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+15+strlen(Platform_mqtt.ClientID)+strlen(Platform_mqtt.Username)] = strlen(Platform_mqtt.Passward)%256; //密码长度低字节
memcpy(&Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+16+strlen(Platform_mqtt.ClientID)+strlen(Platform_mqtt.Username)],Platform_mqtt.Passward,strlen(Platform_mqtt.Passward)); //复制过来密码字串
while(TryConnect_time > 0)
{
memset(mqtt_rxbuf,0,sizeof(mqtt_rxbuf));
MQTT_Send(Platform_mqtt.Pack_buff,Platform_mqtt.Fixed_len + Platform_mqtt.Variable_len + Platform_mqtt.Payload_len);
MdelayKTask(50);
MQTT_Recv(mqtt_rxbuf, 4);
if(mqtt_rxbuf[0] == parket_connetAck[0] && mqtt_rxbuf[1] == parket_connetAck[1]) //连接成功
{
return 0;
}
TryConnect_time--;
}
return 1;
}
/*******************************************************************************
* : MQTT_Disconnect
* : MQTT服务器的连接
* :
* :
*******************************************************************************/
void MQTT_Disconnect(void)
{
while(MQTT_Send(parket_disconnet,sizeof(parket_disconnet)) < 0);
}
/*******************************************************************************
* : MQTT_SubscribeTopic
* : MQTT订阅单个主题
* : topic_name:
* : 0,1
*******************************************************************************/
int MQTT_SubscribeTopic(uint8_t *topic_name)
{
uint8_t TrySub_time = 10; //尝试订阅次数
Platform_mqtt.Fixed_len = 1; //SUBSCRIBE报文,固定报头长度暂定为1
Platform_mqtt.Variable_len = 2;//SUBSCRIBE报文,可变报头长度=2,2为字节报文标识符
Platform_mqtt.Payload_len = 0; //SUBSCRIBE报文,负载数据长度暂定为0
Platform_mqtt.Payload_len = strlen(topic_name) + 2 + 1; //每个需要订阅的topic除了本身的字符串长度,还包含表示topic字符串长度的2字节,以及订阅等级1字节
Platform_mqtt.Remaining_len = Platform_mqtt.Variable_len + Platform_mqtt.Payload_len; //计算剩余长度=可变报头长度+负载长度
memset(Platform_mqtt.Pack_buff,0,sizeof(Platform_mqtt.Pack_buff));
Platform_mqtt.Pack_buff[0]=0x82; //SUBSCRIBE报文,固定报头第1个字节0x82
do{
if((Platform_mqtt.Remaining_len/128) == 0)
{
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len] = Platform_mqtt.Remaining_len;
}
else
{
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len] = (Platform_mqtt.Remaining_len%128)|0x80;
}
Platform_mqtt.Fixed_len++;
Platform_mqtt.Remaining_len = Platform_mqtt.Remaining_len/128;
}while(Platform_mqtt.Remaining_len);
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+0] = Platform_mqtt.MessageID/256; //报文标识符高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+1] = Platform_mqtt.MessageID%256; //报文标识符低字节
Platform_mqtt.MessageID++; //每用一次MessageID加1
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+2] = strlen(topic_name)/256; //主题长度高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+3] = strlen(topic_name)%256; //主题长度低字节
memcpy(&Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+4],topic_name,strlen(topic_name)); //复制主题字串
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+4+strlen(topic_name)] = 0; //QOS等级设置为0
while(TrySub_time > 0)
{
memset(mqtt_rxbuf,0,sizeof(mqtt_rxbuf));
MQTT_Send(Platform_mqtt.Pack_buff,Platform_mqtt.Fixed_len + Platform_mqtt.Variable_len + Platform_mqtt.Payload_len);
MdelayKTask(50);
MQTT_Recv(mqtt_rxbuf, 5);
if(mqtt_rxbuf[0] == parket_subAck[0] && mqtt_rxbuf[1] == parket_subAck[1]) //订阅成功
{
return 0;
}
TrySub_time--;
}
return 1;
}
/*******************************************************************************
* : MQTT_UnSubscribeTopic
* : MQTT取消订阅单个主题
* : topic_name:
* : 0,1
*******************************************************************************/
int MQTT_UnSubscribeTopic(uint8_t *topic_name)
{
uint8_t TryUnSub_time = 10; //尝试取消订阅次数
Platform_mqtt.Fixed_len = 1; //UNSUBSCRIBE报文,固定报头长度暂定为1
Platform_mqtt.Variable_len = 2; //UNSUBSCRIBE报文,可变报头长度=2,2为字节报文标识符
Platform_mqtt.Payload_len = strlen(topic_name) + 2; //每个需要取消的订阅topic除了本身的字符串长度,还包含表示topic字符串长度的2字节
Platform_mqtt.Remaining_len = Platform_mqtt.Variable_len + Platform_mqtt.Payload_len; //计算剩余长度=可变报头长度+负载长度
memset(Platform_mqtt.Pack_buff,0,sizeof(Platform_mqtt.Pack_buff));
Platform_mqtt.Pack_buff[0]=0xA0; //UNSUBSCRIBE报文,固定报头第1个字节0xA0
do{
if((Platform_mqtt.Remaining_len/128) == 0)
{
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len] = Platform_mqtt.Remaining_len;
}
else
{
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len] = (Platform_mqtt.Remaining_len%128)|0x80;
}
Platform_mqtt.Fixed_len++;
Platform_mqtt.Remaining_len = Platform_mqtt.Remaining_len/128;
}while(Platform_mqtt.Remaining_len);
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+0] = Platform_mqtt.MessageID/256; //报文标识符高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+1] = Platform_mqtt.MessageID%256; //报文标识符低字节
Platform_mqtt.MessageID++; //每用一次MessageID加1
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+2] = strlen(topic_name)/256; //主题长度高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+3] = strlen(topic_name)%256; //主题长度低字节
memcpy(&Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+4],topic_name,strlen(topic_name)); //复制主题字串
while(TryUnSub_time > 0)
{
memset(mqtt_rxbuf,0,sizeof(mqtt_rxbuf));
MQTT_Send(Platform_mqtt.Pack_buff,Platform_mqtt.Fixed_len + Platform_mqtt.Variable_len + Platform_mqtt.Payload_len);
MdelayKTask(50);
MQTT_Recv(mqtt_rxbuf, 4);
if(mqtt_rxbuf[0] == parket_unsubAck[0] && mqtt_rxbuf[1] == parket_unsubAck[1]) //取消订阅成功
{
return 0;
}
TryUnSub_time--;
}
return 1;
}
/*******************************************************************************
* : MQTT_PublishDataQs0
* : 0Publish报文
* : topic_name:
data:
data_len:
* : Qs=0
*******************************************************************************/
void MQTT_PublishDataQs0(uint8_t *topic_name,uint8_t *data, uint16_t data_len)
{
Platform_mqtt.Fixed_len = 1; //PUBLISH等级0报文固定报头长度暂定为1
Platform_mqtt.Variable_len = 2 + strlen(topic_name); //PUBLISH等级0报文,可变报头长度=2字节topic长度标识字节+topic字符串的长度
Platform_mqtt.Payload_len = data_len; //PUBLISH等级0报文,负载数据长度=data_len
Platform_mqtt.Remaining_len = Platform_mqtt.Variable_len + Platform_mqtt.Payload_len; //计算剩余长度=可变报头长度+负载长度
memset(Platform_mqtt.Pack_buff,0,sizeof(Platform_mqtt.Pack_buff));
Platform_mqtt.Pack_buff[0]=0x30; //PUBLISH等级0报文固定报头第1个字节0x30
do{
if((Platform_mqtt.Remaining_len/128) == 0)
{
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len] = Platform_mqtt.Remaining_len;
}
else
{
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len] = (Platform_mqtt.Remaining_len%128)|0x80;
}
Platform_mqtt.Fixed_len++;
Platform_mqtt.Remaining_len = Platform_mqtt.Remaining_len/128;
}while(Platform_mqtt.Remaining_len);
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+0]=strlen(topic_name)/256; //主题长度高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+1]=strlen(topic_name)%256; //主题长度低字节
memcpy(&Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+2],topic_name,strlen(topic_name)); //复制主题字串
memcpy(&Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+2+strlen(topic_name)],data,data_len); //复制data数据
MQTT_Send(Platform_mqtt.Pack_buff, Platform_mqtt.Fixed_len + Platform_mqtt.Variable_len + Platform_mqtt.Payload_len);
}
/*******************************************************************************
* : MQTT_PublishDataQs1
* : 1Publish报文
* : topic_name:
data:
data_len:
* :
*******************************************************************************/
void MQTT_PublishDataQs1(uint8_t *topic_name,uint8_t *data, uint16_t data_len)
{
Platform_mqtt.Fixed_len = 1; //PUBLISH等级1报文固定报头长度暂定为1
Platform_mqtt.Variable_len = 2 + 2 + strlen(topic_name); //PUBLISH等级1报文,可变报头长度=2字节消息标识符+2字节topic长度标识字节+topic字符串的长度
Platform_mqtt.Payload_len = data_len; //PUBLISH等级1报文,负载数据长度=data_len
Platform_mqtt.Remaining_len = Platform_mqtt.Variable_len + Platform_mqtt.Payload_len; //计算剩余长度=可变报头长度+负载长度
Platform_mqtt.Pack_buff[0] = 0x32; //等级1的Publish报文固定报头第1个字节0x32
do{
if(Platform_mqtt.Remaining_len/128 == 0)
{
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len] = Platform_mqtt.Remaining_len;
}
else
{
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len] = (Platform_mqtt.Remaining_len%128)|0x80;
}
Platform_mqtt.Fixed_len++;
Platform_mqtt.Remaining_len = Platform_mqtt.Remaining_len/128;
}while(Platform_mqtt.Remaining_len);
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+0] = strlen(topic_name)/256; //主题长度高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+1] = strlen(topic_name)%256; //主题长度低字节
memcpy(&Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+2],topic_name,strlen(topic_name)); //复制主题字串
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+2+strlen(topic_name)] = Platform_mqtt.MessageID/256; //报文标识符高字节
Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+3+strlen(topic_name)] = Platform_mqtt.MessageID%256; //报文标识符低字节
Platform_mqtt.MessageID++; //每用一次MessageID加1
memcpy(&Platform_mqtt.Pack_buff[Platform_mqtt.Fixed_len+4+strlen(topic_name)],data,strlen(data)); //复制data数据
MQTT_Send(Platform_mqtt.Pack_buff,Platform_mqtt.Fixed_len + Platform_mqtt.Variable_len + Platform_mqtt.Payload_len);
}
/*******************************************************************************
* : MQTT_SendHeart
* :
* :
* : 0,
*******************************************************************************/
int MQTT_SendHeart(void)
{
uint8_t TrySentHeart_time = 10; //尝试发送心跳保活次数
while(TrySentHeart_time > 0)
{
memset(mqtt_rxbuf,0,sizeof(mqtt_rxbuf));
MQTT_Send(parket_heart,sizeof(parket_heart));
MdelayKTask(50);
MQTT_Recv(mqtt_rxbuf, 2);
if(mqtt_rxbuf[0] == 0xD0 && mqtt_rxbuf[1] == 0x00)
{
return 0;
}
TrySentHeart_time--;
}
return 1;
}
/*******************************************************************************
* : MQTT_DealPublishData
* : 0,topic信息
* : redata:,data_len:
* :
*******************************************************************************/
void MQTT_DealPublishData(uint8_t *data, uint16_t data_len)
{
uint8_t i;
uint16_t cmdpos,cmdlen;
for(i = 1;i < 5;i++)
{
if((data[i] & 0x80) == 0)
break;
}
cmdpos = 1+i+2;
cmdlen = data_len-(1+i+2);
if(data_len <= CMD_SIZE)
{
memset(Platform_mqtt.cmdbuff, 0, CMD_SIZE);
memcpy(Platform_mqtt.cmdbuff, &data[cmdpos], cmdlen);
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: platform_mqtt.h
* @brief: platform_mqtt.h file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2023/7/27
*
*/
#ifndef _PLATFORM_MQTT_H_
#define _PLATFORM_MQTT_H_
#include <stdint.h>
#include "utils_hmacsha1.h"
#define KEEPALIVE_TIME 300 //保活时间(单位s),300s
#define HEART_TIME 120000 //空闲时发送心跳包的时间间隔(单位ms),120s
#define PACK_SIZE 512 //存放报文数据缓冲区大小
#define CMD_SIZE 3072 //保存推送的PUBLISH报文中的数据缓冲区大小
#define CLIENTID_SIZE 64 //存放客户端ID的缓冲区大小
#define USERNAME_SIZE 64 //存放用户名的缓冲区大小
#define PASSWARD_SIZE 64 //存放密码的缓冲区大小
typedef struct{
uint8_t ClientID[CLIENTID_SIZE]; //存放客户端ID的缓冲区
uint8_t Username[USERNAME_SIZE]; //存放用户名的缓冲区
uint8_t Passward[PASSWARD_SIZE]; //存放密码的缓冲区
uint8_t Pack_buff[PACK_SIZE]; //存放发送报文数据缓冲区
uint16_t MessageID; //记录报文标识符
uint16_t Fixed_len; //固定报头长度
uint16_t Variable_len; //可变报头长度
uint16_t Payload_len; //有效负荷长度
uint16_t Remaining_len; //保存报文剩余长度字节
uint8_t cmdbuff[CMD_SIZE]; //保存推送的PUBLISH报文中的数据缓冲区
}MQTT_TCB;
extern MQTT_TCB Platform_mqtt; //外部变量声明
int AdapterNetActive(void);
int MQTT_Send(const uint8_t* buf, int buflen);
int MQTT_Recv(uint8_t* buf, int buflen);
int MQTT_Connect(void);
void MQTT_Disconnect(void);
int MQTT_SubscribeTopic(uint8_t *topic_name);
int MQTT_UnSubscribeTopic(uint8_t *topic_name);
void MQTT_PublishDataQs0(uint8_t *topic_name,uint8_t *data, uint16_t data_len);
void MQTT_PublishDataQs1(uint8_t *topic_name,uint8_t *data, uint16_t data_len);
int MQTT_SendHeart(void);
void MQTT_DealPublishData(uint8_t *data, uint16_t data_len);
#endif

View File

@ -0,0 +1,399 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: utils_hmacsha1.c
* @brief: utils_hmacsha1.c file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2023/7/27
*
*/
#include "utils_hmacsha1.h"
#define KEY_IOPAD_SIZE 64
#define SHA1_DIGEST_SIZE 20
static void utils_sha1_zeroize(void *v, size_t n);
static void utils_sha1_init(iot_sha1_context *ctx);
static void utils_sha1_free(iot_sha1_context *ctx);
static void utils_sha1_clone(iot_sha1_context *dst, const iot_sha1_context *src);
static void utils_sha1_starts(iot_sha1_context *ctx);
static void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]);
static void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t ilen);
static void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20]);
static void utils_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]);
static int8_t utils_hb2hex(uint8_t hb);
const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* Implementation that should never be optimized out by the compiler */
static void utils_sha1_zeroize(void *v, size_t n)
{
volatile unsigned char *p = v;
while(n--) {
*p++ = 0;
}
}
/* 32-bit integer manipulation macros (big endian) */
#ifndef IOT_SHA1_GET_UINT32_BE
#define IOT_SHA1_GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef IOT_SHA1_PUT_UINT32_BE
#define IOT_SHA1_PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
void utils_sha1_init(iot_sha1_context *ctx)
{
memset(ctx, 0, sizeof(iot_sha1_context));
}
void utils_sha1_free(iot_sha1_context *ctx)
{
if(ctx == NULL) {
return;
}
utils_sha1_zeroize(ctx, sizeof(iot_sha1_context));
}
void utils_sha1_clone(iot_sha1_context *dst,
const iot_sha1_context *src)
{
*dst = *src;
}
/* SHA-1 context setup */
void utils_sha1_starts(iot_sha1_context *ctx)
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64])
{
uint32_t temp, W[16], A, B, C, D, E;
IOT_SHA1_GET_UINT32_BE(W[ 0], data, 0);
IOT_SHA1_GET_UINT32_BE(W[ 1], data, 4);
IOT_SHA1_GET_UINT32_BE(W[ 2], data, 8);
IOT_SHA1_GET_UINT32_BE(W[ 3], data, 12);
IOT_SHA1_GET_UINT32_BE(W[ 4], data, 16);
IOT_SHA1_GET_UINT32_BE(W[ 5], data, 20);
IOT_SHA1_GET_UINT32_BE(W[ 6], data, 24);
IOT_SHA1_GET_UINT32_BE(W[ 7], data, 28);
IOT_SHA1_GET_UINT32_BE(W[ 8], data, 32);
IOT_SHA1_GET_UINT32_BE(W[ 9], data, 36);
IOT_SHA1_GET_UINT32_BE(W[10], data, 40);
IOT_SHA1_GET_UINT32_BE(W[11], data, 44);
IOT_SHA1_GET_UINT32_BE(W[12], data, 48);
IOT_SHA1_GET_UINT32_BE(W[13], data, 52);
IOT_SHA1_GET_UINT32_BE(W[14], data, 56);
IOT_SHA1_GET_UINT32_BE(W[15], data, 60);
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P(A, B, C, D, E, W[0]);
P(E, A, B, C, D, W[1]);
P(D, E, A, B, C, W[2]);
P(C, D, E, A, B, W[3]);
P(B, C, D, E, A, W[4]);
P(A, B, C, D, E, W[5]);
P(E, A, B, C, D, W[6]);
P(D, E, A, B, C, W[7]);
P(C, D, E, A, B, W[8]);
P(B, C, D, E, A, W[9]);
P(A, B, C, D, E, W[10]);
P(E, A, B, C, D, W[11]);
P(D, E, A, B, C, W[12]);
P(C, D, E, A, B, W[13]);
P(B, C, D, E, A, W[14]);
P(A, B, C, D, E, W[15]);
P(E, A, B, C, D, R(16));
P(D, E, A, B, C, R(17));
P(C, D, E, A, B, R(18));
P(B, C, D, E, A, R(19));
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P(A, B, C, D, E, R(20));
P(E, A, B, C, D, R(21));
P(D, E, A, B, C, R(22));
P(C, D, E, A, B, R(23));
P(B, C, D, E, A, R(24));
P(A, B, C, D, E, R(25));
P(E, A, B, C, D, R(26));
P(D, E, A, B, C, R(27));
P(C, D, E, A, B, R(28));
P(B, C, D, E, A, R(29));
P(A, B, C, D, E, R(30));
P(E, A, B, C, D, R(31));
P(D, E, A, B, C, R(32));
P(C, D, E, A, B, R(33));
P(B, C, D, E, A, R(34));
P(A, B, C, D, E, R(35));
P(E, A, B, C, D, R(36));
P(D, E, A, B, C, R(37));
P(C, D, E, A, B, R(38));
P(B, C, D, E, A, R(39));
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P(A, B, C, D, E, R(40));
P(E, A, B, C, D, R(41));
P(D, E, A, B, C, R(42));
P(C, D, E, A, B, R(43));
P(B, C, D, E, A, R(44));
P(A, B, C, D, E, R(45));
P(E, A, B, C, D, R(46));
P(D, E, A, B, C, R(47));
P(C, D, E, A, B, R(48));
P(B, C, D, E, A, R(49));
P(A, B, C, D, E, R(50));
P(E, A, B, C, D, R(51));
P(D, E, A, B, C, R(52));
P(C, D, E, A, B, R(53));
P(B, C, D, E, A, R(54));
P(A, B, C, D, E, R(55));
P(E, A, B, C, D, R(56));
P(D, E, A, B, C, R(57));
P(C, D, E, A, B, R(58));
P(B, C, D, E, A, R(59));
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P(A, B, C, D, E, R(60));
P(E, A, B, C, D, R(61));
P(D, E, A, B, C, R(62));
P(C, D, E, A, B, R(63));
P(B, C, D, E, A, R(64));
P(A, B, C, D, E, R(65));
P(E, A, B, C, D, R(66));
P(D, E, A, B, C, R(67));
P(C, D, E, A, B, R(68));
P(B, C, D, E, A, R(69));
P(A, B, C, D, E, R(70));
P(E, A, B, C, D, R(71));
P(D, E, A, B, C, R(72));
P(C, D, E, A, B, R(73));
P(B, C, D, E, A, R(74));
P(A, B, C, D, E, R(75));
P(E, A, B, C, D, R(76));
P(D, E, A, B, C, R(77));
P(C, D, E, A, B, R(78));
P(B, C, D, E, A, R(79));
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/* SHA-1 process buffer */
void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t ilen)
{
size_t fill;
uint32_t left;
if(ilen == 0) {
return;
}
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if(ctx->total[0] < (uint32_t) ilen) {
ctx->total[1]++;
}
if(left && ilen >= fill) {
memcpy((void *)(ctx->buffer + left), input, fill);
utils_sha1_process(ctx, ctx->buffer);
input += fill;
ilen -= fill;
left = 0;
}
while(ilen >= 64) {
utils_sha1_process(ctx, input);
input += 64;
ilen -= 64;
}
if(ilen > 0) {
memcpy((void *)(ctx->buffer + left), input, ilen);
}
}
static const unsigned char iot_sha1_padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* SHA-1 final digest */
void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20])
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = (ctx->total[0] >> 29)
| (ctx->total[1] << 3);
low = (ctx->total[0] << 3);
IOT_SHA1_PUT_UINT32_BE(high, msglen, 0);
IOT_SHA1_PUT_UINT32_BE(low, msglen, 4);
last = ctx->total[0] & 0x3F;
padn = (last < 56) ? (56 - last) : (120 - last);
utils_sha1_update(ctx, iot_sha1_padding, padn);
utils_sha1_update(ctx, msglen, 8);
IOT_SHA1_PUT_UINT32_BE(ctx->state[0], output, 0);
IOT_SHA1_PUT_UINT32_BE(ctx->state[1], output, 4);
IOT_SHA1_PUT_UINT32_BE(ctx->state[2], output, 8);
IOT_SHA1_PUT_UINT32_BE(ctx->state[3], output, 12);
IOT_SHA1_PUT_UINT32_BE(ctx->state[4], output, 16);
}
/* output = SHA-1(input buffer) */
void utils_sha1(const unsigned char *input, size_t ilen, unsigned char output[20])
{
iot_sha1_context ctx;
utils_sha1_init(&ctx);
utils_sha1_starts(&ctx);
utils_sha1_update(&ctx, input, ilen);
utils_sha1_finish(&ctx, output);
utils_sha1_free(&ctx);
}
inline int8_t utils_hb2hex(uint8_t hb)
{
hb = hb & 0xF;
return (int8_t)(hb < 10 ? '0' + hb : hb - 10 + 'a');
}
void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len)
{
iot_sha1_context context;
unsigned char k_ipad[KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
unsigned char k_opad[KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
unsigned char out[SHA1_DIGEST_SIZE];
int i;
if((NULL == msg) || (NULL == digest) || (NULL == key)) {
return;
}
if(key_len > KEY_IOPAD_SIZE) {
return;
}
/* start out by storing key in pads */
memset(k_ipad, 0, sizeof(k_ipad));
memset(k_opad, 0, sizeof(k_opad));
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
/* XOR key with ipad and opad values */
for(i = 0; i < KEY_IOPAD_SIZE; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/* perform inner SHA */
utils_sha1_init(&context); /* init context for 1st pass */
utils_sha1_starts(&context); /* setup context for 1st pass */
utils_sha1_update(&context, k_ipad, KEY_IOPAD_SIZE); /* start with inner pad */
utils_sha1_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */
utils_sha1_finish(&context, out); /* finish up 1st pass */
/* perform outer SHA */
utils_sha1_init(&context); /* init context for 2nd pass */
utils_sha1_starts(&context); /* setup context for 2nd pass */
utils_sha1_update(&context, k_opad, KEY_IOPAD_SIZE); /* start with outer pad */
utils_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */
utils_sha1_finish(&context, out); /* finish up 2nd pass */
for(i = 0; i < SHA1_DIGEST_SIZE; ++i) {
digest[i * 2] = utils_hb2hex(out[i] >> 4);
digest[i * 2 + 1] = utils_hb2hex(out[i]);
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: utils_hmacsha1.h
* @brief: utils_hmacsha1.h file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2023/7/27
*
*/
#ifndef UTILS_HMACSHA1_H_
#define UTILS_HMACSHA1_H_
#include "stdio.h"
#include "stdint.h"
#include "stdlib.h"
#include "string.h"
/* SHA-1 context structure */
typedef struct {
uint32_t total[2]; /* number of bytes processed */
uint32_t state[5]; /* intermediate digest state */
unsigned char buffer[64]; /* data block being processed */
} iot_sha1_context;
void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len);
#endif

View File

@ -5,9 +5,10 @@ MAKEFLAGS += --no-print-directory
.PHONY:COMPILE_APP COMPILE_KERNEL
riscv_support := kd233 maix-go hifive1-rev-B gapuino gd32vf103-rvstar rv32m1-vega aiit-riscv64-board xidatong-riscv64 edu-riscv64
riscv_support := kd233 maix-go hifive1-rev-B gapuino gd32vf103-rvstar rv32m1-vega aiit-riscv64-board xidatong-riscv64 edu-riscv64 ch32v307vct6
arm_support += stm32f407-st-discovery stm32f407zgt6 stm32f103-nano nuvoton-m2354 ok1052-c imxrt1176-sbc aiit-arm32-board xidatong-arm32 xiwangtong-arm32 edu-arm32
emulator_support += hifive1-emulator k210-emulator cortex-m0-emulator cortex-m3-emulator cortex-m4-emulator
emulator_support += hifive1-emulator k210-emulator cortex-m0-emulator cortex-m3-emulator cortex-m4-emulator cortex-m7-emulator
support := $(riscv_support) $(arm_support) $(emulator_support)
SRC_DIR :=

View File

@ -35,6 +35,11 @@ SRC_DIR := shared
SRC_DIR += cortex-m7
endif
ifeq ($(CONFIG_BOARD_CORTEX_V2M_EVB),y)
SRC_DIR := shared
SRC_DIR += cortex-m7
endif
ifeq ($(CONFIG_BOARD_IMXRT1176_SBC_EVB),y)
SRC_DIR := shared
SRC_DIR += cortex-m7

View File

@ -1,3 +1,8 @@
ifeq ($(CONFIG_BOARD_CORTEX_M7_EVB),y)
SRC_FILES := boot.S interrupt.c interrupt_vector.S
endif
ifeq ($(CONFIG_BOARD_CORTEX_V2M_EVB),y)
SRC_DIR += V2M
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_FILES := boot.S interrupt.c interrupt_vector.S
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef ARCH_INTERRUPT_H__
#define ARCH_INTERRUPT_H__
#include <xs_base.h>
#define ARCH_MAX_IRQ_NUM (256)
//#define ARCH_IRQ_NUM_OFFSET 0
//#define SYSTICK_IRQN 15
//#define UART1_IRQn 36
//#define UART2_IRQn 37
#define ARCH_IRQ_NUM_OFFSET 16
#define SYSTICK_IRQN -1
#define UART0RX_IRQn 0
#define UART0TX_IRQn 1
#define UART1RX_IRQn 2
// #define USB1_IRQn 113
// #define USB2_IRQn 112
int32 ArchEnableHwIrq(uint32 irq_num);
int32 ArchDisableHwIrq(uint32 irq_num);
#endif

View File

@ -0,0 +1,204 @@
/* ------------------------------------------------------------------------- */
/* @file: startup_MIMXRT1052.s */
/* @purpose: CMSIS Cortex-M7 Core Device Startup File */
/* MIMXRT1052 */
/* @version: 1.0 */
/* @date: 2018-9-21 */
/* @build: b180921 */
/* ------------------------------------------------------------------------- */
/* */
/* Copyright 1997-2016 Freescale Semiconductor, Inc. */
/* Copyright 2016-2018 NXP */
/* All rights reserved. */
/* */
/* SPDX-License-Identifier: BSD-3-Clause */
/*****************************************************************************/
/* Version: GCC for ARM Embedded Processors */
/*****************************************************************************/
/**
* @file boot.S
* @brief Cortex-M7 start function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-05-28
*/
/*************************************************
File name: boot.S
Description: Contex-M7 start function function
Others: take startup_MIMXRT1052.s for references
History:
1. Date: 2021-05-28
Author: AIIT XUOS Lab
Modification:
1. add OS entry function
*************************************************/
.syntax unified
.arch armv7-m
.text
.thumb
/* Reset Handler */
.thumb_func
.align 2
.globl Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
#ifdef __BOOTLOADER /* BOOT */
cpsid i /* Mask interrupts */
.equ VTOR, 0xE000ED08
ldr r0, =VTOR
ldr r1, =__isr_vector
str r1, [r0]
ldr r2, [r1]
msr msp, r2
ldr r0,=SystemInit
blx r0
/* Loop to copy data from read only memory to RAM. The ranges
* of copy from/to are specified by following symbols evaluated in
* linker script.
* __bootloader_end: End of code section, i.e., begin of data sections to copy from.
* __data_start__/__data_end__: RAM address range that data should be
* __noncachedata_start__/__noncachedata_end__ : none cachable region
* copied to. Both must be aligned to 4 bytes boundary. */
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
/* Here are two copies of loop implemenations. First one favors code size
* and the second one favors performance. Default uses the first one.
* Change to "#if 0" to use the second one */
.LoopCopy0:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .LoopCopy0
/* This part of work usually is done in C library startup code. Otherwise,
* define this macro to enable it in this startup.
*
* Loop to zero out BSS section, which uses following symbols
* in linker script:
* __bss_start__: start of BSS section. Must align to 4
* __bss_end__: end of BSS section. Must align to 4
*/
ldr r1, =__bss_start__
ldr r2, =__bss_end__
movs r0, 0
.LoopCopy1:
cmp r1, r2
itt lt
strlt r0, [r1], #4
blt .LoopCopy1
ldr r0,=ota_entry
blx r0
#else /* APP */
cpsid i /* Mask interrupts */
.equ VTOR, 0xE000ED08
ldr r0, =VTOR
ldr r1, =__isr_vector
str r1, [r0]
ldr r2, [r1]
msr msp, r2
#ifndef __NO_SYSTEM_INIT
ldr r0,=SystemInit
blx r0
#endif
/* Loop to copy data from read only memory to RAM. The ranges
* of copy from/to are specified by following symbols evaluated in
* linker script.
* __etext: End of code section, i.e., begin of data sections to copy from.
* __data_start__/__data_end__: RAM address range that data should be
* __noncachedata_start__/__noncachedata_end__ : none cachable region
* copied to. Both must be aligned to 4 bytes boundary. */
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
#if 1
/* Here are two copies of loop implemenations. First one favors code size
* and the second one favors performance. Default uses the first one.
* Change to "#if 0" to use the second one */
.LC0:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .LC0
#else
subs r3, r2
ble .LC1
.LC0:
subs r3, #4
ldr r0, [r1, r3]
str r0, [r2, r3]
bgt .LC0
.LC1:
#endif
#ifdef __STARTUP_INITIALIZE_NONCACHEDATA
ldr r2, =__noncachedata_start__
ldr r3, =__noncachedata_init_end__
#if 1
.LC2:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .LC2
#else
subs r3, r2
ble .LC3
.LC2:
subs r3, #4
ldr r0, [r1, r3]
str r0, [r2, r3]
bgt .LC2
.LC3:
#endif
/* zero inited ncache section initialization */
ldr r3, =__noncachedata_end__
movs r0,0
.LC4:
cmp r2,r3
itt lt
strlt r0,[r2],#4
blt .LC4
#endif /* __STARTUP_INITIALIZE_NONCACHEDATA */
#if 1
/* This part of work usually is done in C library startup code. Otherwise,
* define this macro to enable it in this startup.
*
* Loop to zero out BSS section, which uses following symbols
* in linker script:
* __bss_start__: start of BSS section. Must align to 4
* __bss_end__: end of BSS section. Must align to 4
*/
ldr r1, =__bss_start__
ldr r2, =__bss_end__
movs r0, 0
.LC5:
cmp r1, r2
itt lt
strlt r0, [r1], #4
blt .LC5
#endif /* __STARTUP_CLEAR_BSS */
ldr r0,=entry
blx r0
#endif /* MCUBOOT_BOOTLOADER */
.size Reset_Handler, . - Reset_Handler

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file interrupt.c
* @brief support arm cortex-m7 interrupt function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-05-28
*/
#include <xs_base.h>
#include <xs_isr.h>
#include "fsl_common.h"
x_base __attribute__((naked)) DisableLocalInterrupt()
{
asm volatile ("MRS r0, PRIMASK");
asm volatile ("CPSID I");
asm volatile ("BX LR ");
}
void __attribute__((naked)) EnableLocalInterrupt(x_base level)
{
asm volatile ("MSR PRIMASK, r0");
asm volatile ("BX LR");
}
int32 ArchEnableHwIrq(uint32 irq_num)
{
EnableIRQ(irq_num);
return EOK;
}
int32 ArchDisableHwIrq(uint32 irq_num)
{
DisableIRQ(irq_num);
return EOK;
}
extern void KTaskOsAssignAfterIrq(void *context);
void IsrEntry()
{
uint32 ipsr;
__asm__ volatile("MRS %0, IPSR" : "=r"(ipsr));
if (ipsr!=17){
KPrintf("%d\n",ipsr);
}
isrManager.done->incCounter();
isrManager.done->handleIrq(ipsr);
KTaskOsAssignAfterIrq(NONE);
isrManager.done->decCounter();
}
void UsageFault_Handler(int irqn, void *arg)
{
/* Go to infinite loop when Usage Fault exception occurs */
while (1)
{
}
}
void BusFault_Handler(int irqn, void *arg)
{
/* Go to infinite loop when Bus Fault exception occurs */
while (1)
{
}
}
void NMI_Handler(int irqn, void *arg)
{
while (1)
{
}
}

View File

@ -0,0 +1,319 @@
/* ------------------------------------------------------------------------- */
/* @file: startup_MIMXRT1052.s */
/* @purpose: CMSIS Cortex-M7 Core Device Startup File */
/* MIMXRT1052 */
/* @version: 1.0 */
/* @date: 2018-9-21 */
/* @build: b180921 */
/* ------------------------------------------------------------------------- */
/* */
/* Copyright 1997-2016 Freescale Semiconductor, Inc. */
/* Copyright 2016-2018 NXP */
/* All rights reserved. */
/* */
/* SPDX-License-Identifier: BSD-3-Clause */
/*****************************************************************************/
/* Version: GCC for ARM Embedded Processors */
/*****************************************************************************/
/**
* @file interrupt_vector.S
* @brief vector table for Cortex M7
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-05-28
*/
/*************************************************
File name: interrupt_vector.S
Description: vector table for a Cortex M7
Others:
History:
1. Date: 2021-05-28
Author: AIIT XUOS Lab
Modification:
1. add IsrEntry as default isr function
*************************************************/
.syntax unified
.arch armv7-m
.section .isr_vector, "a"
.align 2
.globl __isr_vector
__isr_vector:
.long __StackTop /* Initial Stack Pointer */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler*/
.long HardFaultHandler /* Hard Fault Handler*/
.long MemFaultHandler /* MPU Fault Handler*/
.long BusFault_Handler /* Bus Fault Handler*/
.long UsageFault_Handler /* Usage Fault Handler*/
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long SVC_Handler /* -5 SVC Handler */
.long DebugMon_Handler /* -4 Debug Monitor Handler */
.long 0 /* Reserved */
.long PendSV_Handler /* -2 PendSV Handler */
.long SysTick_Handler /* -1 SysTick Handler */
/* Interrupts */
.long UART0RX_Handler /* 0 UART 0 receive interrupt */
.long UART0TX_Handler /* 1 UART 0 transmit interrupt */
.long UART1RX_Handler /* 2 UART 1 receive interrupt */
.long UART1TX_Handler /* 3 UART 1 transmit interrupt */
.long UART2RX_Handler /* 4 UART 2 receive interrupt */
.long UART2TX_Handler /* 5 UART 2 transmit interrupt */
.long GPIO0ALL_Handler /* 6 GPIO 0 combined interrupt */
.long GPIO1ALL_Handler /* 7 GPIO 1 combined interrupt */
.long TIMER0_Handler /* 8 Timer 0 interrupt */
.long TIMER1_Handler /* 9 Timer 1 interrupt */
.long DUALTIMER_Handler /* 10 Dual Timer interrupt */
.long SPI_0_1_Handler /* 11 SPI 0, 1 interrupt */
.long UART_0_1_2_OVF_Handler /* 12 UART overflow (0, 1 & 2) interrupt */
.long ETHERNET_Handler /* 13 Ethernet interrupt */
.long I2S_Handler /* 14 Audio I2S interrupt */
.long TOUCHSCREEN_Handler /* 15 Touch Screen interrupt */
.long GPIO2_Handler /* 16 GPIO 2 combined interrupt */
.long GPIO3_Handler /* 17 GPIO 3 combined interrupt */
.long UART3RX_Handler /* 18 UART 3 receive interrupt */
.long UART3TX_Handler /* 19 UART 3 transmit interrupt */
.long UART4RX_Handler /* 20 UART 4 receive interrupt */
.long UART4TX_Handler /* 21 UART 4 transmit interrupt */
.long SPI_2_Handler /* 22 SPI 2 interrupt */
.long SPI_3_4_Handler /* 23 SPI 3, 4 interrupt */
.long GPIO0_0_Handler /* 24 GPIO 0 individual interrupt ( 0) */
.long GPIO0_1_Handler /* 25 GPIO 0 individual interrupt ( 1) */
.long GPIO0_2_Handler /* 26 GPIO 0 individual interrupt ( 2) */
.long GPIO0_3_Handler /* 27 GPIO 0 individual interrupt ( 3) */
.long GPIO0_4_Handler /* 28 GPIO 0 individual interrupt ( 4) */
.long GPIO0_5_Handler /* 29 GPIO 0 individual interrupt ( 5) */
.long GPIO0_6_Handler /* 30 GPIO 0 individual interrupt ( 6) */
.long GPIO0_7_Handler /* 31 GPIO 0 individual interrupt ( 7) */
.long 0 /* 32 Reserved */
.long 0 /* 33 Reserved */
.long 0 /* 34 Reserved */
.long 0 /* 35 Reserved */
.long 0 /* 36 Reserved */
.long 0 /* 37 Reserved */
.long 0 /* 38 Reserved */
.long 0 /* 39 Reserved */
.long 0 /* 40 Reserved */
.long 0 /* 41 Reserved */
.long 0 /* 42 Reserved */
.long 0 /* 43 Reserved */
.long 0 /* 44 Reserved */
.long 0 /* 45 Reserved */
.long 0 /* 46 Reserved */
.long 0 /* 47 Reserved */
.long 0 /* 48 Reserved */
.long 0 /* 49 Reserved */
.long 0 /* 50 Reserved */
.long 0 /* 51 Reserved */
.long 0 /* 52 Reserved */
.long 0 /* 53 Reserved */
.long 0 /* 54 Reserved */
.long 0 /* 55 Reserved */
.long 0 /* 56 Reserved */
.long 0 /* 57 Reserved */
.long 0 /* 58 Reserved */
.long 0 /* 59 Reserved */
.long 0 /* 60 Reserved */
.long 0 /* 61 Reserved */
.long 0 /* 62 Reserved */
.long 0 /* 63 Reserved */
.long 0 /* 64 Reserved */
.long 0 /* 65 Reserved */
.long 0 /* 66 Reserved */
.long 0 /* 67 Reserved */
.long 0 /* 68 Reserved */
.long 0 /* 69 Reserved */
.long 0 /* 70 Reserved */
.long 0 /* 71 Reserved */
.long 0 /* 72 Reserved */
.long 0 /* 73 Reserved */
.long 0 /* 74 Reserved */
.long 0 /* 75 Reserved */
.long 0 /* 76 Reserved */
.long 0 /* 77 Reserved */
.long 0 /* 78 Reserved */
.long 0 /* 79 Reserved */
.long 0 /* 80 Reserved */
.long 0 /* 81 Reserved */
.long 0 /* 82 Reserved */
.long 0 /* 83 Reserved */
.long 0 /* 84 Reserved */
.long 0 /* 85 Reserved */
.long 0 /* 86 Reserved */
.long 0 /* 87 Reserved */
.long 0 /* 88 Reserved */
.long 0 /* 89 Reserved */
.long 0 /* 90 Reserved */
.long 0 /* 91 Reserved */
.long 0 /* 92 Reserved */
.long 0 /* 93 Reserved */
.long 0 /* 94 Reserved */
.long 0 /* 95 Reserved */
.long 0 /* 96 Reserved */
.long 0 /* 97 Reserved */
.long 0 /* 98 Reserved */
.long 0 /* 99 Reserved */
.long 0 /* 100 Reserved */
.long 0 /* 101 Reserved */
.long 0 /* 102 Reserved */
.long 0 /* 103 Reserved */
.long 0 /* 104 Reserved */
.long 0 /* 105 Reserved */
.long 0 /* 106 Reserved */
.long 0 /* 107 Reserved */
.long 0 /* 108 Reserved */
.long 0 /* 109 Reserved */
.long 0 /* 110 Reserved */
.long 0 /* 111 Reserved */
.long 0 /* 112 Reserved */
.long 0 /* 113 Reserved */
.long 0 /* 114 Reserved */
.long 0 /* 115 Reserved */
.long 0 /* 116 Reserved */
.long 0 /* 117 Reserved */
.long 0 /* 118 Reserved */
.long 0 /* 119 Reserved */
.long 0 /* 120 Reserved */
.long 0 /* 121 Reserved */
.long 0 /* 122 Reserved */
.long 0 /* 123 Reserved */
.long 0 /* 124 Reserved */
.long 0 /* 125 Reserved */
.long 0 /* 126 Reserved */
.long 0 /* 127 Reserved */
.long 0 /* 128 Reserved */
.long 0 /* 129 Reserved */
.long 0 /* 130 Reserved */
.long 0 /* 131 Reserved */
.long 0 /* 132 Reserved */
.long 0 /* 133 Reserved */
.long 0 /* 134 Reserved */
.long 0 /* 135 Reserved */
.long 0 /* 136 Reserved */
.long 0 /* 137 Reserved */
.long 0 /* 138 Reserved */
.long 0 /* 139 Reserved */
.long 0 /* 140 Reserved */
.long 0 /* 141 Reserved */
.long 0 /* 142 Reserved */
.long 0 /* 143 Reserved */
.long 0 /* 144 Reserved */
.long 0 /* 145 Reserved */
.long 0 /* 146 Reserved */
.long 0 /* 147 Reserved */
.long 0 /* 148 Reserved */
.long 0 /* 149 Reserved */
.long 0 /* 150 Reserved */
.long 0 /* 151 Reserved */
.long 0 /* 152 Reserved */
.long 0 /* 153 Reserved */
.long 0 /* 154 Reserved */
.long 0 /* 155 Reserved */
.long 0 /* 156 Reserved */
.long 0 /* 157 Reserved */
.long 0 /* 158 Reserved */
.long 0 /* 159 Reserved */
.long 0 /* 160 Reserved */
.long 0 /* 161 Reserved */
.long 0 /* 162 Reserved */
.long 0 /* 163 Reserved */
.long 0 /* 164 Reserved */
.long 0 /* 165 Reserved */
.long 0 /* 166 Reserved */
.long 0 /* 167 Reserved */
.long 0 /* 168 Reserved */
.long 0 /* 169 Reserved */
.long 0 /* 170 Reserved */
.long 0 /* 171 Reserved */
.long 0 /* 172 Reserved */
.long 0 /* 173 Reserved */
.long 0 /* 174 Reserved */
.long 0 /* 175 Reserved */
.long 0 /* 176 Reserved */
.long 0 /* 177 Reserved */
.long 0 /* 178 Reserved */
.long 0 /* 179 Reserved */
.long 0 /* 180 Reserved */
.long 0 /* 181 Reserved */
.long 0 /* 182 Reserved */
.long 0 /* 183 Reserved */
.long 0 /* 184 Reserved */
.long 0 /* 185 Reserved */
.long 0 /* 186 Reserved */
.long 0 /* 187 Reserved */
.long 0 /* 188 Reserved */
.long 0 /* 189 Reserved */
.long 0 /* 190 Reserved */
.long 0 /* 191 Reserved */
.long 0 /* 192 Reserved */
.long 0 /* 193 Reserved */
.long 0 /* 194 Reserved */
.long 0 /* 195 Reserved */
.long 0 /* 196 Reserved */
.long 0 /* 197 Reserved */
.long 0 /* 198 Reserved */
.long 0 /* 199 Reserved */
.long 0 /* 200 Reserved */
.long 0 /* 201 Reserved */
.long 0 /* 202 Reserved */
.long 0 /* 203 Reserved */
.long 0 /* 204 Reserved */
.long 0 /* 205 Reserved */
.long 0 /* 206 Reserved */
.long 0 /* 207 Reserved */
.long 0 /* 208 Reserved */
.long 0 /* 209 Reserved */
.long 0 /* 210 Reserved */
.long 0 /* 211 Reserved */
.long 0 /* 212 Reserved */
.long 0 /* 213 Reserved */
.long 0 /* 214 Reserved */
.long 0 /* 215 Reserved */
.long 0 /* 216 Reserved */
.long 0 /* 217 Reserved */
.long 0 /* 218 Reserved */
.long 0 /* 219 Reserved */
.long 0 /* 220 Reserved */
.long 0 /* 221 Reserved */
.long 0 /* 222 Reserved */
.long 0 /* 223 Reserved */
#if defined CMSDK_CM7_VHT || defined CMSDK_CM7_SP_VHT || defined CMSDK_CM7_DP_VHT
.long ARM_VSI0_Handler /* 224 VSI 0 interrupt */
.long ARM_VSI1_Handler /* 225 VSI 1 interrupt */
.long ARM_VSI2_Handler /* 226 VSI 2 interrupt */
.long ARM_VSI3_Handler /* 227 VSI 3 interrupt */
.long ARM_VSI4_Handler /* 228 VSI 4 interrupt */
.long ARM_VSI5_Handler /* 229 VSI 5 interrupt */
.long ARM_VSI6_Handler /* 230 VSI 6 interrupt */
.long ARM_VSI7_Handler /* 231 VSI 7 interrupt */
#else
.long 0 /* 224 reserved */
.long 0 /* 225 reserved */
.long 0 /* 226 reserved */
.long 0 /* 227 reserved */
.long 0 /* 228 reserved */
.long 0 /* 229 reserved */
.long 0 /* 230 reserved */
.long 0 /* 231 reserved */
#endif
.long 0 /* 232 reserved */
.long 0 /* 233 reserved */
.long 0 /* 234 reserved */
.long 0 /* 235 reserved */
.long 0 /* 236 reserved */
.long 0 /* 237 reserved */
.long 0 /* 238 reserved */
.long 0 /* 239 reserved */
.size __isr_vector, . - __isr_vector
.text
.thumb

View File

@ -14,6 +14,7 @@
#define PMP_H
#include <xs_klist.h>
#include <stddef.h>
#define PMP_MAX_ENTRY_NUMBER 16
#define PMP_ENTRY_RESERVE 6
@ -40,11 +41,11 @@
struct PmpEntry
{
uint8_t pmpcfg;
uint8 pmpcfg;
#if defined(ARCH_RISCV64)
uint64_t pmpaddr;
uint64 pmpaddr;
#else
uint32_t pmpaddr;
uint32 pmpaddr;
#endif
};
@ -53,8 +54,8 @@ struct PmpRegionNapot
{
x_ubase start ;
x_ubase end;
uint16_t swap_count;
uint8_t region_type;
uint16 swap_count;
uint8 region_type;
struct PmpEntry entry;
DoubleLinklistType link;
@ -64,8 +65,8 @@ struct PmpRegionTor
{
x_ubase start ;
x_ubase end;
uint16_t swap_count;
uint8_t region_type;
uint16 swap_count;
uint8 region_type;
struct PmpEntry entry[2];
DoubleLinklistType link;
@ -73,8 +74,8 @@ struct PmpRegionTor
struct Pmp
{
uint8_t count;
uint8_t reserve;
uint8 count;
uint8 reserve;
struct PmpEntry pmp_entry_reserve[PMP_ENTRY_RESERVE];
DoubleLinklistType tor_list;
@ -82,7 +83,7 @@ struct Pmp
};
x_err_t PmpAddTorRegion(void *task_pmp, x_ubase start , size_t size , uint8_t flag );
x_err_t PmpAddTorRegion(void *task_pmp, x_ubase start , size_t size , uint8 flag );
x_err_t PmpInitIsolation(void **task_pmp, x_ubase stack_start , size_t stack_size);
void PmpFree(void *task_pmp);
void PmpClear(void);

View File

@ -268,13 +268,17 @@ static uint32 Stm32SerialInit(struct SerialDriver *serial_drv, struct BusConfigu
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
struct UsartHwCfg *serial_hw_cfg = (struct UsartHwCfg *)serial_cfg->hw_cfg.private_data;
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (configure_info->private_data) {
struct SerialCfgParam *serial_cfg_new = (struct SerialCfgParam *)configure_info->private_data;
SerialCfgParamCheck(serial_cfg, serial_cfg_new);
}
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (serial_cfg_new->data_cfg.dev_recv_callback) {
BusDevRecvCallback(&(serial_dev->haldev), serial_cfg_new->data_cfg.dev_recv_callback);
}
}
// config serial receive sem timeout
dev_param->serial_timeout = serial_cfg->data_cfg.serial_timeout;

View File

@ -143,13 +143,17 @@ static uint32 SerialHsInit(struct SerialDriver *serial_drv, struct BusConfigureI
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (configure_info->private_data) {
struct SerialCfgParam *serial_cfg_new = (struct SerialCfgParam *)configure_info->private_data;
SerialCfgParamCheck(serial_cfg, serial_cfg_new);
}
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (serial_cfg_new->data_cfg.dev_recv_callback) {
BusDevRecvCallback(&(serial_dev->haldev), serial_cfg_new->data_cfg.dev_recv_callback);
}
}
// config serial receive sem timeout
dev_param->serial_timeout = serial_cfg->data_cfg.serial_timeout;
@ -226,13 +230,17 @@ static uint32 SerialInit(struct SerialDriver *serial_drv, struct BusConfigureInf
NULL_PARAM_CHECK(serial_drv);
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (configure_info->private_data) {
struct SerialCfgParam *serial_cfg_new = (struct SerialCfgParam *)configure_info->private_data;
SerialCfgParamCheck(serial_cfg, serial_cfg_new);
}
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (serial_cfg_new->data_cfg.dev_recv_callback) {
BusDevRecvCallback(&(serial_dev->haldev), serial_cfg_new->data_cfg.dev_recv_callback);
}
}
// config serial receive sem timeout
dev_param->serial_timeout = serial_cfg->data_cfg.serial_timeout;

View File

@ -81,13 +81,17 @@ static uint32 SerialInit(struct SerialDriver *serial_drv, struct BusConfigureInf
struct SerialCfgParam* serial_cfg = (struct SerialCfgParam*)serial_drv->private_data;
// struct UsartHwCfg *serial_hw_cfg = (struct UsartHwCfg *)serial_cfg->hw_cfg.private_data;
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (configure_info->private_data) {
struct SerialCfgParam *serial_cfg_new = (struct SerialCfgParam *)configure_info->private_data;
SerialCfgParamCheck(serial_cfg, serial_cfg_new);
}
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (serial_cfg_new->data_cfg.dev_recv_callback) {
BusDevRecvCallback(&(serial_dev->haldev), serial_cfg_new->data_cfg.dev_recv_callback);
}
}
// config serial receive sem timeout
dev_param->serial_timeout = serial_cfg->data_cfg.serial_timeout;

View File

@ -120,6 +120,10 @@ static uint32 SerialInit(struct SerialDriver *serial_drv, struct BusConfigureInf
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
if (serial_cfg->data_cfg.dev_recv_callback) {
BusDevRecvCallback(&(serial_dev->haldev), serial_cfg->data_cfg.dev_recv_callback);
}
// config serial receive sem timeout
dev_param->serial_timeout = serial_cfg->data_cfg.serial_timeout;

View File

@ -121,6 +121,10 @@ static uint32 SerialInit(struct SerialDriver *serial_drv, struct BusConfigureInf
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
if (serial_cfg->data_cfg.dev_recv_callback) {
BusDevRecvCallback(&(serial_dev->haldev), serial_cfg->data_cfg.dev_recv_callback);
}
// config serial receive sem timeout
dev_param->serial_timeout = serial_cfg->data_cfg.serial_timeout;

View File

@ -269,13 +269,17 @@ static uint32 Stm32SerialInit(struct SerialDriver *serial_drv, struct BusConfigu
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
struct UsartHwCfg *serial_hw_cfg = (struct UsartHwCfg *)serial_cfg->hw_cfg.private_data;
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (configure_info->private_data) {
struct SerialCfgParam *serial_cfg_new = (struct SerialCfgParam *)configure_info->private_data;
SerialCfgParamCheck(serial_cfg, serial_cfg_new);
}
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (serial_cfg_new->data_cfg.dev_recv_callback) {
BusDevRecvCallback(&(serial_dev->haldev), serial_cfg_new->data_cfg.dev_recv_callback);
}
}
// config serial receive sem timeout
dev_param->serial_timeout = serial_cfg->data_cfg.serial_timeout;

View File

@ -0,0 +1,294 @@
#
# Automatically generated file; DO NOT EDIT.
# XiZi_IIoT Project Configuration
#
CONFIG_BOARD_CORTEX_M7_EVB=y
CONFIG_ARCH_ARM=y
#
# xidatong-arm32 feature
#
CONFIG_BSP_USING_LPUART=y
CONFIG_BSP_USING_LPUART1=y
CONFIG_SERIAL_BUS_NAME_1="uart1"
CONFIG_SERIAL_DRV_NAME_1="uart1_drv"
CONFIG_SERIAL_1_DEVICE_NAME_0="uart1_dev1"
CONFIG_BSP_USING_LPUART2=y
CONFIG_SERIAL_BUS_NAME_2="uart2"
CONFIG_SERIAL_DRV_NAME_2="uart2_drv"
CONFIG_SERIAL_2_DEVICE_NAME_0="uart2_dev2"
CONFIG_BSP_USING_LPUART3=y
CONFIG_SERIAL_BUS_NAME_3="uart3"
CONFIG_SERIAL_DRV_NAME_3="uart3_drv"
CONFIG_SERIAL_3_DEVICE_NAME_0="uart3_dev3"
# CONFIG_BSP_USING_LPUART4 is not set
# CONFIG_BSP_USING_LPUART8 is not set
# CONFIG_BSP_USING_CH438 is not set
CONFIG_BSP_USING_GPIO=y
CONFIG_PIN_BUS_NAME="pin"
CONFIG_PIN_DRIVER_NAME="pin_drv"
CONFIG_PIN_DEVICE_NAME="pin_dev"
# CONFIG_BSP_USING_I2C is not set
# CONFIG_BSP_USING_LWIP is not set
# CONFIG_BSP_USING_SEMC is not set
# CONFIG_BSP_USING_SDIO is not set
# CONFIG_BSP_USING_LCD is not set
# CONFIG_BSP_USING_TOUCH is not set
# CONFIG_BSP_USING_USB is not set
# CONFIG_BSP_USING_WDT is not set
#
# config default board resources
#
#
# config board app name
#
CONFIG_BOARD_APP_NAME="/XiUOS_xidatong_app.bin"
#
# config board service table
#
CONFIG_SERVICE_TABLE_ADDRESS=0x2007F0000
CONFIG___STACKSIZE__=4096
#
# config board peripheral
#
# CONFIG_MOUNT_SDCARD is not set
# CONFIG_MOUNT_USB is not set
#
# Hardware feature
#
CONFIG_RESOURCES_SERIAL=y
CONFIG_SERIAL_USING_DMA=y
CONFIG_SERIAL_RB_BUFSZ=128
CONFIG_RESOURCES_PIN=y
#
# Kernel feature
#
#
# separate compile(choose none for compile once)
#
# CONFIG_SEPARATE_COMPILE is not set
# CONFIG_COMPILER_APP is not set
# CONFIG_APP_STARTUP_FROM_SDCARD is not set
CONFIG_APP_STARTUP_FROM_FLASH=y
# CONFIG_COMPILER_KERNEL is not set
#
# Memory Management
#
# CONFIG_KERNEL_MEMBLOCK is not set
CONFIG_MEM_ALIGN_SIZE=8
# CONFIG_MEM_EXTERN_SRAM is not set
CONFIG_MM_PAGE_SIZE=4096
#
# Using small memory allocator
#
CONFIG_KERNEL_SMALL_MEM_ALLOC=y
CONFIG_SMALL_NUMBER_32B=64
CONFIG_SMALL_NUMBER_64B=32
#
# Task feature
#
CONFIG_USER_APPLICATION=y
# CONFIG_TASK_ISOLATION is not set
#
# Inter-Task communication
#
CONFIG_KERNEL_SEMAPHORE=y
CONFIG_KERNEL_MUTEX=y
CONFIG_KERNEL_EVENT=y
CONFIG_KERNEL_MESSAGEQUEUE=y
# CONFIG_KERNEL_SOFTTIMER is not set
CONFIG_SCHED_POLICY_RR_REMAINSLICE=y
# CONFIG_SCHED_POLICY_RR is not set
# CONFIG_SCHED_POLICY_FIFO is not set
# CONFIG_KTASK_PRIORITY_8 is not set
CONFIG_KTASK_PRIORITY_32=y
# CONFIG_KTASK_PRIORITY_256 is not set
CONFIG_KTASK_PRIORITY_MAX=32
CONFIG_TICK_PER_SECOND=1000
CONFIG_KERNEL_STACK_OVERFLOW_CHECK=y
CONFIG_IDLE_KTASK_STACKSIZE=1024
CONFIG_ZOMBIE_KTASK_STACKSIZE=2048
#
# Kernel Console
#
CONFIG_KERNEL_CONSOLE=y
CONFIG_KERNEL_BANNER=y
CONFIG_KERNEL_CONSOLEBUF_SIZE=128
#
# Kernel Hook
#
# CONFIG_KERNEL_HOOK is not set
#
# Command shell
#
CONFIG_TOOL_SHELL=y
CONFIG_SHELL_ENTER_CR=y
CONFIG_SHELL_ENTER_LF=y
CONFIG_SHELL_ENTER_CR_AND_LF=y
# CONFIG_SHELL_ENTER_CRLF is not set
#
# Set shell user control
#
CONFIG_SHELL_DEFAULT_USER="letter"
CONFIG_SHELL_DEFAULT_USER_PASSWORD=""
CONFIG_SHELL_LOCK_TIMEOUT=10000
#
# Set shell config param
#
CONFIG_SHELL_TASK_STACK_SIZE=4096
CONFIG_SHELL_TASK_PRIORITY=20
CONFIG_SHELL_MAX_NUMBER=5
CONFIG_SHELL_PARAMETER_MAX_NUMBER=8
CONFIG_SHELL_HISTORY_MAX_NUMBER=5
CONFIG_SHELL_PRINT_BUFFER=128
CONFIG_SHELL_HELP_SHOW_PERMISSION=y
# CONFIG_SHELL_HELP_LIST_USER is not set
CONFIG_SHELL_HELP_LIST_VAR=y
# CONFIG_SHELL_HELP_LIST_KEY is not set
#
# Kernel data structure Manage
#
CONFIG_KERNEL_QUEUEMANAGE=y
CONFIG_KERNEL_WORKQUEUE=y
CONFIG_WORKQUEUE_KTASK_STACKSIZE=2048
CONFIG_WORKQUEUE_KTASK_PRIORITY=23
CONFIG_QUEUE_MAX=16
CONFIG_KERNEL_WAITQUEUE=y
CONFIG_KERNEL_DATAQUEUE=y
# CONFIG_KERNEL_CIRCULAR_AREA is not set
# CONFIG_KERNEL_AVL_TREE is not set
#
# Kernel components init
#
CONFIG_KERNEL_COMPONENTS_INIT=y
CONFIG_ENV_INIT_KTASK_STACK_SIZE=8192
CONFIG_KERNEL_USER_MAIN=y
CONFIG_NAME_NUM_MAX=32
# CONFIG_KERNEL_DEBUG is not set
# CONFIG_ARCH_SMP is not set
#
# hash table config
#
CONFIG_ID_HTABLE_SIZE=16
CONFIG_ID_NUM_MAX=128
# CONFIG_KERNEL_TEST is not set
#
# Lib
#
CONFIG_LIB=y
CONFIG_LIB_POSIX=y
CONFIG_LIB_NEWLIB=y
# CONFIG_LIB_MUSLLIB is not set
#
# C++ features
#
# CONFIG_LIB_CPLUSPLUS is not set
#
# File system
#
# CONFIG_FS_VFS=y
# CONFIG_VFS_USING_WORKDIR=y
# CONFIG_FS_VFS_DEVFS=y
# CONFIG_FS_VFS_FATFS=y
# CONFIG_FS_CH376 is not set
# CONFIG_FS_LWEXT4 is not set
#
# APP_Framework
#
#
# Framework
#
CONFIG_TRANSFORM_LAYER_ATTRIUBUTE=y
CONFIG_ADD_XIZI_FEATURES=y
# CONFIG_ADD_NUTTX_FEATURES is not set
# CONFIG_ADD_RTTHREAD_FEATURES is not set
# CONFIG_SUPPORT_SENSOR_FRAMEWORK is not set
# CONFIG_SUPPORT_CONNECTION_FRAMEWORK is not set
# CONFIG_SUPPORT_KNOWING_FRAMEWORK is not set
# CONFIG_SUPPORT_CONTROL_FRAMEWORK is not set
#
# Security
#
# CONFIG_CRYPTO is not set
# CONFIG_MBEDTLS is not set
#
# Applications
#
#
# config stack size and priority of main task
#
CONFIG_MAIN_KTASK_STACK_SIZE=4096
CONFIG_MAIN_KTASK_PRIORITY=16
#
# ota app
#
# CONFIG_APPLICATION_OTA is not set
#
# test app
#
# CONFIG_USER_TEST is not set
#
# connection app
#
# CONFIG_APPLICATION_CONNECTION is not set
#
# control app
#
#
# knowing app
#
# CONFIG_APPLICATION_KNOWING is not set
#
# sensor app
#
# CONFIG_APPLICATION_SENSOR is not set
# CONFIG_USING_EMBEDDED_DATABASE_APP is not set
# CONFIG_APP_USING_WEBNET is not set
#
# lib
#
CONFIG_APP_SELECT_NEWLIB=y
# CONFIG_APP_SELECT_OTHER_LIB is not set
# CONFIG_LIB_USING_CJSON is not set
# CONFIG_LIB_USING_QUEUE is not set
# CONFIG_LIB_LV is not set
#
# LVGL configuration
#
# CONFIG_LV_CONF_MINIMAL is not set
# CONFIG_USING_EMBEDDED_DATABASE is not set

View File

@ -0,0 +1,61 @@
mainmenu "XiZi_IIoT Project Configuration"
config BSP_DIR
string
option env="BSP_ROOT"
default "."
config KERNEL_DIR
string
option env="KERNEL_ROOT"
default "../.."
config BOARD_CORTEX_V2M_EVB
bool
select ARCH_ARM
default y
source "$KERNEL_DIR/arch/Kconfig"
menu "cortex-m7-emulator feature"
source "$BSP_DIR/third_party_driver/Kconfig"
menu "config default board resources"
menu "config board app name"
config BOARD_APP_NAME
string "config board app name"
default "/XiUOS_cortex-m7-emulator_app.bin"
endmenu
menu "config board service table"
config SERVICE_TABLE_ADDRESS
hex "board service table address"
default 0x20000000
endmenu
endmenu
config __STACKSIZE__
int "stack size for interrupt"
default 4096
menu "config board peripheral"
config MOUNT_SDCARD
bool
default n
config MOUNT_USB
bool
default n
endmenu
endmenu
menu "Hardware feature"
source "$KERNEL_DIR/resources/Kconfig"
endmenu
source "$KERNEL_DIR/Kconfig"

View File

@ -0,0 +1,8 @@
SRC_FILES := board.c
SRC_DIR := third_party_driver
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,208 @@
# 从零开始构建矽璓工业物联操作系统使用ARM架构的cortex-m7 emulator
[XiUOS](http://xuos.io/) (X Industrial Ubiquitous Operating System) 矽璓XiUOS是一款面向智慧车间的工业物联网操作系统主要由一个极简的微型实时操作系统内核和其上的工业物联框架构成通过高效管理工业物联网设备、支撑工业物联应用在生产车间内实现智能化的“感知环境、联网传输、知悉识别、控制调整”促进以工业设备和工业控制系统为核心的人、机、物深度互联帮助提升生产线的数字化和智能化水平。
## 1. 简介
QEMU 是一个通用的开源模拟器和虚拟化工具。目前QEMU已经可以较完整的支持ARM cortex-m4架构。XiUOS同样支持运行在QEMU上
| 硬件 | 描述 |
| -------- | ------------- |
| 芯片型号 | mps2-an500 |
| 架构 | cortex-m7 |
| 主频 | 168MHz |
| 片内SRAM | 100+KB |
| 外设支持 | UART、GPIO |
## 2. 开发环境搭建
### 推荐使用:
**操作系统:** ubuntu18.04 [https://ubuntu.com/download/desktop](https://ubuntu.com/download/desktop)
更新`ubuntu 18.04`源的方法:(根据自身情况而定,可以不更改)
第一步:打开sources.list文件
```c
sudo vim /etc/apt/sources.list
```
第二步:将以下内容复制到sources.list文件
```c
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
```
第三步:更新源和系统软件
```c
sudo apt-get update
sudo apt-get upgrade
```
**开发工具推荐使用 VSCode VScode下载地址为** VSCode [https://code.visualstudio.com/](https://code.visualstudio.com/),推荐下载地址为 [http://vscode.cdn.azure.cn/stable/3c4e3df9e89829dce27b7b5c24508306b151f30d/code_1.55.2-1618307277_amd64.deb](http://vscode.cdn.azure.cn/stable/3c4e3df9e89829dce27b7b5c24508306b151f30d/code_1.55.2-1618307277_amd64.deb)
### 依赖包安装:
```
$ sudo apt install build-essential pkg-config git
$ sudo apt install gcc make libncurses5-dev openssl libssl-dev bison flex libelf-dev autoconf libtool gperf libc6-dev
```
**XiUOS操作系统源码下载** XiUOS [https://www.gitlink.org.cn/xuos/xiuos](https://www.gitlink.org.cn/xuos/xiuos)
新建一个空文件夹并进入文件夹中,并下载源码,具体命令如下:
```c
mkdir test && cd test
git clone https://gitlink.org.cn/xuos/xiuos.git
```
1、打开XiUOS源码文件包可以看到以下目录
| 名称 | 说明 |
| -- | -- |
| APP_Framework | 应用代码 |
| Ubiquitous | 板级支持包,支持NuttX、RT-Thread和XiZi内核 |
2、打开XiZi内核源码文件包可以看到以下目录
| 名称 | 说明 |
| -- | -- |
| arch | 架构代码 |
| board | 板级支持包 |
| fs | 文件系统 |
| kernel | 内核源码 |
| lib | 第三方库源码 |
| resources | 驱动文件 |
| tool | 系统工具 |
使用VScode打开代码具体操作步骤为在源码文件夹下打开系统终端输入`code .`即可打开VScode开发环境如下图所示
<div align= "center">
<img src="img/vscode.jpg" width =1000>
</div>
### 裁减配置工具的下载
裁减配置工具:
**工具地址:** kconfig-frontends [https://www.gitlink.org.cn/xuos/kconfig-frontends](https://www.gitlink.org.cn/xuos/kconfig-frontends),下载与安装的具体命令如下:
```c
mkdir kfrontends && cd kfrontends
git clone https://gitlink.org.cn/xuos/kconfig-frontends.git
```
下载源码后按以下步骤执行软件安装:
```c
cd kconfig-frontends
./xs_build.sh
```
### 编译工具链:
ARM arm-none-eabi(`gcc version 6.3.1`)默认安装到Ubuntu的/usr/bin/arm-none-eabi-,使用如下命令行下载和安装。
```shell
$ sudo apt install gcc-arm-none-eabi
```
## 3. 编译说明
### 编辑环境:`Ubuntu18.04`
### 编译工具链:`arm-none-eabi-gcc`
使用`VScode`打开工程的方法有多种,本文介绍一种快捷键,在项目目录下将`code .`输入linux系统命令终端即可打开目标项目
编译步骤:
1.在VScode命令终端中执行以下命令生成配置文件
```c
cd ./Ubiquitous/XiZi
make BOARD=cortex-m7-emulator distclean
make BOARD=cortex-m7-emulator menuconfig
```
2.在menuconfig界面配置需要关闭和开启的功能按回车键进入下级菜单按Y键选中需要开启的功能按N键选中需要关闭的功能配置结束后保存并退出本例旨在演示简单的输出例程所以没有需要配置的选项双击快捷键ESC退出配置
<div align= "center">
<img src="img/menuconfig.png" width =1000>
</div>
退出时选择`yes`保存上面所配置的内容,如下图所示:
<div align= "center">
<img src="img/menuconfig1.png" width =1000>
</div>
3.继续执行以下命令,进行编译
```
make BOARD=cortex-m7-emulator
```
4.如果编译正确无误会产生XiZi-cortex-m7-emulator.elf、XiZi-cortex-m7-emulator.bin文件。
## 4. 运行
### 4.1 安装QEMU
```
sudo apt install qemu-system-arm
```
### 4.2 运行结果
通过以下命令启动QEMU并加载XiUOS ELF文件
```
qemu-system-arm -machine mps2-an500 -nographic -kernel build/XiZi-cortex-m7-emulator.elf
```
QEMU运行起来后将会在终端上看到信息打印输出
<div align= "center">
<img src="img/terminal.png" width =1000>
</div>
### 4.3 调试
通过QEMU可以方便的对XiUOS进行调试首先安装gdb调试工具
```
sudo apt install gdb-multiarch
```
并通过以下命令启动QEMU
```
qemu-system-arm -machine mps2-an500 -nographic -kernel build/XiZi-cortex-m7-emulator.elf -s -S
```
然后要重新开启另一个linux系统终端一个终端执行`riscv-none-embed-gdb`命令
```
gdb-multiarch build/XiZi-cortex-m7-emulator.elf -ex "target remote localhost:1234"
```

View File

@ -0,0 +1,202 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file board.c
* @brief support cortex-m7-emulator-board init configure and start-up
* @version 1.0
* @author AIIT XUOS Lab
* @date 2023-09-27
*/
/*************************************************
File name: board.c
Description: support cortex-m7-emulator-board init configure and driver/task/... init
Others:
History:
1. Date: 2023-09-27
Author: AIIT XUOS Lab
Modification:
1. support cortex-m7-emulator-board InitBoardHardware
*************************************************/
#include "board.h"
#include "clock_config.h"
#include <device.h>
#ifdef BSP_USING_LPUART
#include <connect_uart.h>
#endif
#ifdef BSP_USING_GPIO
#include <connect_gpio.h>
#endif
extern uint32_t SystemCoreClock;
/* MPU configuration. */
void BOARD_ConfigMPU(void)
{
/* Disable MPU */
ARM_MPU_Disable();
/* MPU configure:
* Use ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable,
* SubRegionDisable, Size)
* API in mpu_armv7.h.
* param DisableExec Instruction access (XN) disable bit,0=instruction fetches enabled, 1=instruction fetches
* disabled.
* param AccessPermission Data access permissions, allows you to configure read/write access for User and
* Privileged mode.
* Use MACROS defined in mpu_armv7.h:
* ARM_MPU_AP_NONE/ARM_MPU_AP_PRIV/ARM_MPU_AP_URO/ARM_MPU_AP_FULL/ARM_MPU_AP_PRO/ARM_MPU_AP_RO
* Combine TypeExtField/IsShareable/IsCacheable/IsBufferable to configure MPU memory access attributes.
* TypeExtField IsShareable IsCacheable IsBufferable Memory Attribtue Shareability Cache
* 0 x 0 0 Strongly Ordered shareable
* 0 x 0 1 Device shareable
* 0 0 1 0 Normal not shareable Outer and inner write
* through no write allocate
* 0 0 1 1 Normal not shareable Outer and inner write
* back no write allocate
* 0 1 1 0 Normal shareable Outer and inner write
* through no write allocate
* 0 1 1 1 Normal shareable Outer and inner write
* back no write allocate
* 1 0 0 0 Normal not shareable outer and inner
* noncache
* 1 1 0 0 Normal shareable outer and inner
* noncache
* 1 0 1 1 Normal not shareable outer and inner write
* back write/read acllocate
* 1 1 1 1 Normal shareable outer and inner write
* back write/read acllocate
* 2 x 0 0 Device not shareable
* Above are normal use settings, if your want to see more details or want to config different inner/outter cache
* policy.
* please refer to Table 4-55 /4-56 in arm cortex-M7 generic user guide <dui0646b_cortex_m7_dgug.pdf>
* param SubRegionDisable Sub-region disable field. 0=sub-region is enabled, 1=sub-region is disabled.
* param Size Region size of the region to be configured. use ARM_MPU_REGION_SIZE_xxx MACRO in
* mpu_armv7.h.
*/
// /* Region 0 setting: Memory with Device type, not shareable, non-cacheable. */
// MPU->RBAR = ARM_MPU_RBAR(0, 0xC0000000U);
// MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB);
/* Region 1 setting: Memory with Device type, not shareable, non-cacheable. */
MPU->RBAR = ARM_MPU_RBAR(0, 0x20000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_256MB);
/* Region 2 setting */
#if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1)
/* Setting Memory with Normal type, not shareable, outer/inner write back. */
MPU->RBAR = ARM_MPU_RBAR(2, 0x60000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64MB);
#else
/* Setting Memory with Device type, not shareable, non-cacheable. */
MPU->RBAR = ARM_MPU_RBAR(1, 0x20000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_64MB);
#endif
/* Region 3 setting: Memory with Device type, not shareable, non-cacheable. */
MPU->RBAR = ARM_MPU_RBAR(2, 0x00000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB);
/* Region 4 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(3, 0x00000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB);
/* Region 5 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(4, 0x20000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB);
/* Region 6 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(5, 0x20200000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB);
/* The define sets the cacheable memory to shareable,
* this suggestion is referred from chapter 2.2.1 Memory regions,
* types and attributes in Cortex-M7 Devices, Generic User Guide */
#if defined(SDRAM_IS_SHAREABLE)
/* Region 7 setting: Memory with Normal type, shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(7, 0x80000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 1, 1, 1, 0, ARM_MPU_REGION_SIZE_32MB);
#else
/* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(6, 0x21000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_2MB);
#endif
/* Region 8 setting, set last 2MB of SDRAM can't be accessed by cache, glocal variables which are not expected to be
* accessed by cache can be put here */
/* Memory with Normal type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(7, 0x21200000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_2MB);
/* Enable MPU */
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
/* Enable I cache and D cache */
SCB_EnableDCache();
SCB_EnableICache();
}
/* This is the timer interrupt service routine. */
void SysTick_Handler(int irqn, void *arg)
{
TickAndTaskTimesliceUpdate();
}
void InitBoardHardware()
{
int i = 0;
int ret = 0;
BOARD_ConfigMPU();
// BOARD_InitPins();
BOARD_BootClockRUN();
NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
SysTick_Config(SystemCoreClock / TICK_PER_SECOND);
InitBoardMemory((void *)HEAP_BEGIN, (void *)HEAP_END);
#ifdef BSP_USING_LPUART
Imxrt1052HwUartInit();
#endif
InstallConsole(KERNEL_CONSOLE_BUS_NAME, KERNEL_CONSOLE_DRV_NAME, KERNEL_CONSOLE_DEVICE_NAME);
KPrintf("0");
KPrintf("\nconsole init completed.\n");
KPrintf("board initialization......\n");
// for(i = 0; _board_init[i].fn != NONE; i++) {
// ret = _board_init[i].fn();
// KPrintf("initialize %s %s\n",_board_init[i].fn_name, ret == 0 ? "success" : "failed");
// }
KPrintf("board init done.\n");
KPrintf("start kernel...\n");
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 2017-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file board.h
* @brief definecortex-m7-emulator init configure and start-up function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-05-28
*/
/*************************************************
File name: board.h
Description: define cortex-m7-emulator init function and struct
Others:
History:
1. Date: 2023-09-27
Author: AIIT XUOS Lab
Modification:
1. define imxrt-board InitBoardHardware
2. define imxrt-board heap struct
*************************************************/
#ifndef __BOARD_H__
#define __BOARD_H__
#define M7_EMULATOR
#include <stdint.h>
#include <xizi.h>
#include <arch_interrupt.h>
#include "fsl_common.h"
#include "xsconfig.h"
#define NVIC_PRIORITYGROUP_0 0x00000007U /*!< 0 bits for pre-emption priority
4 bits for subpriority */
#define NVIC_PRIORITYGROUP_1 0x00000006U /*!< 1 bits for pre-emption priority
3 bits for subpriority */
#define NVIC_PRIORITYGROUP_2 0x00000005U /*!< 2 bits for pre-emption priority
2 bits for subpriority */
#define NVIC_PRIORITYGROUP_3 0x00000004U /*!< 3 bits for pre-emption priority
1 bits for subpriority */
#define NVIC_PRIORITYGROUP_4 0x00000003U /*!< 4 bits for pre-emption priority*/
extern int heap_start;
extern int heap_end;
#define HEAP_BEGIN (&heap_start)
#define HEAP_END (&heap_end)
#define HEAP_SIZE ((uint32_t)HEAP_END - (uint32_t)HEAP_BEGIN)
void InitBoardHardware(void);
#endif /* _BOARD_H_ */

View File

@ -0,0 +1,15 @@
export CROSS_COMPILE ?=/usr/bin/arm-none-eabi-
export CFLAGS := -mcpu=cortex-m7 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror
export AFLAGS := -c -mcpu=cortex-m7 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -x assembler-with-cpp -Wa,-mimplicit-it=thumb -gdwarf-2
export LFLAGS := -mcpu=cortex-m7 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi-cortex-m7-emulator.map,-cref,-u,Reset_Handler -T $(BSP_ROOT)/link.lds
export CXXFLAGS := -mcpu=cortex-m7 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -Werror
export APPLFLAGS := -mcpu=cortex-m7 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi-app.map,-cref,-u, -T $(BSP_ROOT)/link_userspace.lds
export DEFINES := -DHAVE_CCONFIG_H -DCPU_MIMXRT1052CVL5B
export ARCH = arm
export MCU = cortex-m7

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Some files were not shown because too many files have changed in this diff Show More