Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
沁恒CH32V
flashDB
RT-Thread一般讨论
FlashDB环境搭建
发布于 2022-08-15 09:14:54 浏览:1488
订阅该版
[tocm] ## 前言 # FlashDB环境搭建(基于CH32V307,模拟SPI&片外Flash—GD25Q16) ## 前言 FlashDB是一款超轻量级的嵌入式数据库,专注于提供嵌入式产品的数据存储方案。与传统的基于文件系统的数据库不同,FlashDB 结合了 Flash 的特性,具有较强的性能及可靠性。并在保证极低的资源占用前提下,尽可能延长 Flash 使用寿命。 FlashDB 提供两种数据库模式: - **键值数据库** :是一种非关系数据库,它将数据存储为键值(Key-Value)对集合,其中键作为唯一标识符。KVDB 操作简洁,可扩展性强。 - **时序数据库** :时间序列数据库 (Time Series Database , 简称 TSDB),它将数据按照 **时间顺序存储** 。TSDB 数据具有时间戳,数据存储量大,插入及查询性能高。 ## 移植步骤 FlashDB 底层的 Flash 管理及操作依赖于 RT-Thread 的 FAL (Flash Abstraction Layer) Flash 抽象层开源软件包 ,所以只需要将所用到的 **Flash 对接到 FAL** ,即可完成整个移植工作。 FlashDB的移植关键在于FAL的移植,FAL的移植的关键在于在片外flash上搭建FAL,具体步骤如下: 1. 模拟SPI读写功能的实现(板子画错了,因此使用模拟SPI);**//后续有机会添加会根据spi-bit-ops来实现模拟spi** 2. 挂载片外Flash(GD25Q16); 3. 搭建FAL抽象层; 4. 对接FlashDB。 ## 1.模拟SPI读写功能的实现 ### 1.1 新建一个空白的项目(不具体描述了吧) ### 1.2 在/board/Kconfig内添加以下内容,不清楚的话,需要回去了解一下RTT的构建与配置系统 ![screenshot_image-20220814223330520.png](https://oss-club.rt-thread.org/uploads/20220815/3db5dea83bd771d68f9ce1f908baeae0.png) ```python menuconfig BSP_USING_SOFT_SPI_FLASH bool "Enable SOFT SPI Flash(SOFT SPI)" default n select RT_USING_SPI # select RT_USING_SPI_BITOPS # select RT_SPI_BITOPS_DEBUG select RT_USING_SFUD if BSP_USING_SOFT_SPI_FLASH config SOFT_SPI_FLASH_NAME string "soft spi flash device name" default "GD25Q16" config SOFT_SPI_FLASH_BUS_NAME string "spi flash bus name" default "soft_spi1" config SOFT_SPI_FLASH_DEVICE_NAME string "spi flash device name" default "soft_spi10" endif ``` **RTT的构建与配置系统**: ![screenshot_buildconfig1.png](https://oss-club.rt-thread.org/uploads/20220815/1fa7e98dd19fc8cd8a293d6de9bcaa9d.png) ### 1.3 在SConscript内添加以下内容,不清楚的话,需要回去了解一下RTT的构建与配置系统 ```python path += [cwd + '/on-chip_drivers'] ··· if GetDepend('BSP_USING_SOFT_SPI_FLASH'): src += ['on-chip_drivers/soft_spi_flash.c'] src += ['on-chip_drivers/drv_soft_spi.c'] ``` ### 1.4 在hal_drivers下添加文件夹/on-chip_drivers,在文件夹内添加drv_soft_spi.c/drv_soft_spi.h/soft_spi_flash.c文件 ![screenshot_image-20220814223647982.png](https://oss-club.rt-thread.org/uploads/20220815/18eb6a4959aad5ef3f92b7e433cf9d60.png) **drv_soft_spi.c:** ```c /* * Change Logs: * Date Author Notes * 2020-05-20 Roy.yu first version * 2022-08-14 MXH fit ch32v307 */ #include "board.h" #include "rtconfig.h" #ifdef BSP_USING_SOFT_SPI_FLASH #include "drv_soft_spi.h" #include
//#define DRV_DEBUG #define LOG_TAG "drv.spisoft" #include
//enum{ // SOFT_SPI1_INDEX, //}; #define SOFT_SPI1_BUS_CONFIG { \ .mosi_pin.GPIOx = GPIOD, \ .mosi_pin.GPIO_Pin = GPIO_Pin_4, \ .miso_pin.GPIOx = GPIOB, \ .miso_pin.GPIO_Pin = GPIO_Pin_5, \ .sclk_pin.GPIOx = GPIOD, \ .sclk_pin.GPIO_Pin = GPIO_Pin_6, \ .bus_name = "soft_spi1", \ } //#define SOFT_SPI1_BUS_CONFIG { \ // .mosi_pin.GPIOx = GPIOB, \ // .mosi_pin.GPIO_Pin = GPIO_Pin_5, \ // .miso_pin.GPIOx = GPIOB, \ // .miso_pin.GPIO_Pin = GPIO_Pin_4, \ // .sclk_pin.GPIOx = GPIOB, \ // .sclk_pin.GPIO_Pin = GPIO_Pin_3, \ // .bus_name = "soft_spi1", \ //} static struct ch32_soft_spi_config soft_spi_config[] ={ SOFT_SPI1_BUS_CONFIG, }; static struct ch32_soft_spi soft_spi_bus_obj[sizeof(soft_spi_config) / sizeof(soft_spi_config[0])] = {0}; static rt_err_t ch32_spi_init(struct ch32_soft_spi *spi_drv, struct rt_spi_configuration *cfg) { RT_ASSERT(spi_drv != RT_NULL); RT_ASSERT(cfg != RT_NULL); //mode = master if (cfg->mode & RT_SPI_SLAVE){ return RT_EIO; } else spi_drv->mode = RT_SPI_MASTER; if (cfg->mode & RT_SPI_3WIRE){ return RT_EIO; } if (cfg->data_width == 8 || cfg->data_width == 16) spi_drv->data_width = cfg->data_width; else{ return RT_EIO; } if (cfg->mode & RT_SPI_CPHA){ spi_drv->cpha = 1; } else{ spi_drv->cpha = 0; } if (cfg->mode & RT_SPI_CPOL){ spi_drv->cpol = 1; } else{ spi_drv->cpol = 0; } if (cfg->mode & RT_SPI_NO_CS){ } else{ } if (cfg->max_hz >= 1200000){ spi_drv->spi_delay = 0; }else if (cfg->max_hz >= 1000000){ spi_drv->spi_delay = 8; }else if (cfg->max_hz >= 830000){ spi_drv->spi_delay = 16; } LOG_D("SPI limiting freq: %d, BaudRatePrescaler: %d", cfg->max_hz, spi_drv->spi_delay); if (cfg->mode & RT_SPI_MSB){ spi_drv->msb = 1; } else{ spi_drv->msb = 0; } //init spi pin GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = spi_drv->config->mosi_pin.GPIO_Pin; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(spi_drv->config->mosi_pin.GPIOx, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = spi_drv->config->miso_pin.GPIO_Pin; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(spi_drv->config->miso_pin.GPIOx, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = spi_drv->config->sclk_pin.GPIO_Pin; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(spi_drv->config->sclk_pin.GPIOx, &GPIO_InitStruct); // GPIO_Initure.Pin = spi_drv->config->mosi_pin.GPIO_Pin; // GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; // GPIO_Initure.Pull = GPIO_PULLUP; // GPIO_Initure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // HAL_GPIO_Init(spi_drv->config->mosi_pin.GPIOx, &GPIO_Initure); // HAL_GPIO_WritePin(spi_drv->config->mosi_pin.GPIOx, spi_drv->config->mosi_pin.GPIO_Pin, GPIO_PIN_RESET); // GPIO_Initure.Pin = spi_drv->config->miso_pin.GPIO_Pin; // GPIO_Initure.Mode = GPIO_MODE_INPUT; // GPIO_Initure.Pull = GPIO_NOPULL; // GPIO_Initure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // HAL_GPIO_Init(spi_drv->config->miso_pin.GPIOx, &GPIO_Initure); // GPIO_Initure.Pin = spi_drv->config->sclk_pin.GPIO_Pin; // GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; // GPIO_Initure.Pull = GPIO_PULLUP; // GPIO_Initure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // HAL_GPIO_Init(spi_drv->config->sclk_pin.GPIOx, &GPIO_Initure); if(spi_drv->cpol) // HAL_GPIO_WritePin(spi_drv->config->sclk_pin.GPIOx,spi_drv->config->sclk_pin.GPIO_Pin,GPIO_PIN_SET); GPIO_WriteBit(spi_drv->config->sclk_pin.GPIOx,spi_drv->config->sclk_pin.GPIO_Pin, 1); else // HAL_GPIO_WritePin(spi_drv->config->sclk_pin.GPIOx,spi_drv->config->sclk_pin.GPIO_Pin,GPIO_PIN_RESET); GPIO_WriteBit(spi_drv->config->sclk_pin.GPIOx,spi_drv->config->sclk_pin.GPIO_Pin, 0); LOG_D("%s init done", spi_drv->config->bus_name); return RT_EOK; } static inline void spi_delay(uint8_t time){ switch(time){ case 16:__NOP(); case 15:__NOP(); case 14:__NOP(); case 13:__NOP(); case 12:__NOP(); case 11:__NOP(); case 10:__NOP(); case 9:__NOP(); case 8:__NOP(); case 7:__NOP(); case 6:__NOP(); case 5:__NOP(); case 4:__NOP(); case 3:__NOP(); case 2:__NOP(); case 1:__NOP(); default: break; } } static rt_uint32_t soft_spi_read_write_bytes(struct ch32_soft_spi *spi_drv, uint8_t* send_buff, uint8_t* recv_buff, uint32_t len){ uint32_t dataIndex = 0; uint8_t time = 0; for(uint32_t i = 0; i
cpha){ //CPHA=1 // HAL_GPIO_TogglePin(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin); // GPIO_WriteBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin, // (GPIO_ReadOutputDataBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin) ? 0 : 1)); spi_drv->config->sclk_pin.GPIOx->OUTDR ^= spi_drv->config->sclk_pin.GPIO_Pin; } if(spi_drv->data_width == 16) time = 1; else time = 0; do{ for(uint8_t j = 0; j < 8; j++){ if ((send_buff[dataIndex] & 0x80) != 0){ // HAL_GPIO_WritePin(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,GPIO_PIN_SET); GPIO_WriteBit(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,1); }else{ // HAL_GPIO_WritePin(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,GPIO_PIN_RESET); GPIO_WriteBit(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,0); } send_buff[dataIndex] <<= 1; spi_delay(spi_drv->spi_delay); // HAL_GPIO_TogglePin(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin); // GPIO_WriteBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin, // (GPIO_ReadOutputDataBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin) ? 0 : 1)); spi_drv->config->sclk_pin.GPIOx->OUTDR ^= spi_drv->config->sclk_pin.GPIO_Pin; recv_buff[dataIndex] <<= 1; // if (HAL_GPIO_ReadPin(spi_drv->config->miso_pin.GPIOx, spi_drv->config->miso_pin.GPIO_Pin)) if (GPIO_ReadInputDataBit(spi_drv->config->miso_pin.GPIOx, spi_drv->config->miso_pin.GPIO_Pin)) recv_buff[dataIndex] |= 0x01; spi_delay(spi_drv->spi_delay); // if(time != 0 || j != 7){ if(time != 0 || j != 7 || spi_drv->cpha == 0){ // HAL_GPIO_TogglePin(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin); // GPIO_WriteBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin, // (GPIO_ReadOutputDataBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin) ? 0 : 1)); spi_drv->config->sclk_pin.GPIOx->OUTDR ^= spi_drv->config->sclk_pin.GPIO_Pin; } } dataIndex++; }while(time--); spi_delay(spi_drv->spi_delay); } return len; } static rt_uint32_t soft_spi_read_bytes(struct ch32_soft_spi *spi_drv, uint8_t* recv_buff, uint32_t len){ uint8_t send_buff = spi_drv->dummy_data; uint32_t dataIndex = 0; uint8_t time = 0; for(uint32_t i = 0; i
cpha){ //CPHA=1 // HAL_GPIO_TogglePin(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin); // GPIO_WriteBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin, // (GPIO_ReadOutputDataBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin) ? 0 : 1)); spi_drv->config->sclk_pin.GPIOx->OUTDR ^= spi_drv->config->sclk_pin.GPIO_Pin; } if(spi_drv->data_width == 16) time = 1; else time = 0; do{ for(uint8_t j = 0; j < 8; j++){ if ((send_buff & 0x80) != 0){ // HAL_GPIO_WritePin(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,GPIO_PIN_SET); GPIO_WriteBit(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,1); }else{ // HAL_GPIO_WritePin(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,GPIO_PIN_RESET); GPIO_WriteBit(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,0); } send_buff <<= 1; spi_delay(spi_drv->spi_delay); // HAL_GPIO_TogglePin(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin); // GPIO_WriteBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin, // (GPIO_ReadOutputDataBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin) ? 0 : 1)); spi_drv->config->sclk_pin.GPIOx->OUTDR ^= spi_drv->config->sclk_pin.GPIO_Pin; recv_buff[dataIndex] <<= 1; // if (HAL_GPIO_ReadPin(spi_drv->config->miso_pin.GPIOx, spi_drv->config->miso_pin.GPIO_Pin)) if (GPIO_ReadInputDataBit(spi_drv->config->miso_pin.GPIOx, spi_drv->config->miso_pin.GPIO_Pin)) recv_buff[dataIndex] |= 0x01; spi_delay(spi_drv->spi_delay); // if(time != 0 || j != 7){ if(time != 0 || j != 7 || spi_drv->cpha == 0){ // HAL_GPIO_TogglePin(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin); // GPIO_WriteBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin, // (GPIO_ReadOutputDataBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin) ? 0 : 1)); spi_drv->config->sclk_pin.GPIOx->OUTDR ^= spi_drv->config->sclk_pin.GPIO_Pin; } } dataIndex++; }while(time--); spi_delay(spi_drv->spi_delay); } return len; } static rt_uint32_t soft_spi_write_bytes(struct ch32_soft_spi *spi_drv, uint8_t* send_buff, uint32_t len){ uint8_t recv_buff = 0; uint32_t dataIndex = 0; uint8_t time = 0; for(uint32_t i = 0; i
cpha){ //CPHA=1 // HAL_GPIO_TogglePin(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin); // GPIO_WriteBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin, // (GPIO_ReadOutputDataBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin) ? 0 : 1)); spi_drv->config->sclk_pin.GPIOx->OUTDR ^= spi_drv->config->sclk_pin.GPIO_Pin; } if(spi_drv->data_width == 16) time = 1; else time = 0; do{ for(uint8_t j = 0; j < 8; j++){ if ((send_buff[dataIndex] & 0x80) != 0){ // HAL_GPIO_WritePin(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,GPIO_PIN_SET); GPIO_WriteBit(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,1); }else{ // HAL_GPIO_WritePin(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,GPIO_PIN_RESET); GPIO_WriteBit(spi_drv->config->mosi_pin.GPIOx,spi_drv->config->mosi_pin.GPIO_Pin,0); } send_buff[dataIndex] <<= 1; spi_delay(spi_drv->spi_delay); // HAL_GPIO_TogglePin(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin); // GPIO_WriteBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin, // (GPIO_ReadOutputDataBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin) ? 0 : 1)); spi_drv->config->sclk_pin.GPIOx->OUTDR ^= spi_drv->config->sclk_pin.GPIO_Pin; recv_buff <<= 1; // if (HAL_GPIO_ReadPin(spi_drv->config->miso_pin.GPIOx, spi_drv->config->miso_pin.GPIO_Pin)) if (GPIO_ReadInputDataBit(spi_drv->config->miso_pin.GPIOx, spi_drv->config->miso_pin.GPIO_Pin)) recv_buff |= 0x01; spi_delay(spi_drv->spi_delay); // if(time != 0 || j != 7){ if(time != 0 || j != 7 || spi_drv->cpha == 0){ // HAL_GPIO_TogglePin(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin); // GPIO_WriteBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin, // (GPIO_ReadOutputDataBit(spi_drv->config->sclk_pin.GPIOx, spi_drv->config->sclk_pin.GPIO_Pin) ? 0 : 1)); spi_drv->config->sclk_pin.GPIOx->OUTDR ^= spi_drv->config->sclk_pin.GPIO_Pin; } } dataIndex++; }while(time--); spi_delay(spi_drv->spi_delay); } return len; } static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message){ rt_uint32_t state; rt_size_t message_length; rt_uint8_t *recv_buf; const rt_uint8_t *send_buf; RT_ASSERT(device != RT_NULL); RT_ASSERT(device->bus != RT_NULL); RT_ASSERT(device->bus->parent.user_data != RT_NULL); RT_ASSERT(message != RT_NULL); struct ch32_soft_spi *spi_drv = rt_container_of(device->bus, struct ch32_soft_spi, spi_bus); struct ch32_soft_spi_pin *cs = device->parent.user_data; if (message->cs_take){ // HAL_GPIO_WritePin(cs->GPIOx, cs->GPIO_Pin, GPIO_PIN_RESET); GPIO_WriteBit(cs->GPIOx, cs->GPIO_Pin, 0); } LOG_D("%s transfer prepare and start", spi_drv->config->bus_name); LOG_D("%s sendbuf: %X, recvbuf: %X, length: %d", spi_drv->config->bus_name, (uint32_t)message->send_buf, (uint32_t)message->recv_buf, message->length); message_length = message->length; recv_buf = message->recv_buf; send_buf = message->send_buf; if(message_length){ if (message->send_buf && message->recv_buf){ state = soft_spi_read_write_bytes(spi_drv, (uint8_t *)send_buf, (uint8_t *)recv_buf, message_length); } else if (message->send_buf){ state = soft_spi_write_bytes(spi_drv, (uint8_t *)send_buf, message_length); } else{ memset((uint8_t *)recv_buf, 0xff, message_length); state = soft_spi_read_bytes(spi_drv, (uint8_t *)recv_buf, message_length); } if (state != message_length){ LOG_I("spi transfer error : %d", state); message->length = 0; } else{ LOG_D("%s transfer done", spi_drv->config->bus_name); } } if (message->cs_release){ // HAL_GPIO_WritePin(cs->GPIOx, cs->GPIO_Pin, GPIO_PIN_SET); GPIO_WriteBit(cs->GPIOx, cs->GPIO_Pin, 1); } return message->length; } static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration){ RT_ASSERT(device != RT_NULL); RT_ASSERT(configuration != RT_NULL); struct ch32_soft_spi *spi_drv = rt_container_of(device->bus, struct ch32_soft_spi, spi_bus); spi_drv->cfg = configuration; return ch32_spi_init(spi_drv, configuration); } static const struct rt_spi_ops ch_spi_ops ={ .configure = spi_configure, .xfer = spixfer, }; static int rt_soft_spi_bus_init(void){ rt_err_t result; for (int i = 0; i < sizeof(soft_spi_config) / sizeof(soft_spi_config[0]); i++){ soft_spi_bus_obj[i].config = &soft_spi_config[i]; soft_spi_bus_obj[i].spi_bus.parent.user_data = &soft_spi_config[i]; result = rt_spi_bus_register(&soft_spi_bus_obj[i].spi_bus, soft_spi_config[i].bus_name, &ch_spi_ops); RT_ASSERT(result == RT_EOK); LOG_D("%s bus init done", soft_spi_config[i].bus_name); } return result; } /** * Attach the spi device to SPI bus, this function must be used after initialization. */ rt_err_t rt_soft_spi_device_attach(const char *bus_name, const char *device_name, GPIO_TypeDef *cs_gpiox, uint16_t cs_gpio_pin){ RT_ASSERT(bus_name != RT_NULL); RT_ASSERT(device_name != RT_NULL); rt_err_t result; struct rt_spi_device *spi_device; struct ch32_soft_spi_pin *cs_pin; /* initialize the cs pin && select the slave*/ GPIO_InitTypeDef GPIO_InitStruct; // GPIO_Initure.Pin = cs_gpio_pin; // GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; // GPIO_Initure.Pull = GPIO_PULLUP; // GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH; // HAL_GPIO_Init(cs_gpiox, &GPIO_Initure); // HAL_GPIO_WritePin(cs_gpiox, cs_gpio_pin, GPIO_PIN_SET); GPIO_InitStruct.GPIO_Pin = cs_gpio_pin; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(cs_gpiox, &GPIO_InitStruct); /* attach the device to spi bus*/ spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); RT_ASSERT(spi_device != RT_NULL); cs_pin = (struct ch32_soft_spi_pin *)rt_malloc(sizeof(struct ch32_soft_spi_pin)); RT_ASSERT(cs_pin != RT_NULL); cs_pin->GPIOx = cs_gpiox; cs_pin->GPIO_Pin = cs_gpio_pin; result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin); if (result != RT_EOK){ LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result); } RT_ASSERT(result == RT_EOK); LOG_D("%s attach to %s done", device_name, bus_name); return result; } int rt_soft_spi_init(void){ return rt_soft_spi_bus_init(); } INIT_PREV_EXPORT(rt_soft_spi_init); #endif /* RT_USING_SPI */ ``` **drv_soft_spi.h:** ```c /* * Change Logs: * Date Author Notes * 2020-05-20 Roy.yu first version * 2022-08-14 MXH fit ch32v307 * Only for MSB */ #ifndef __DRV_SOFT_SPI_H_ #define __DRV_SOFT_SPI_H_ #include
#include "rtdevice.h" #include
#include "ch32v30x.h" rt_err_t rt_soft_spi_device_attach(const char *bus_name, const char *device_name, GPIO_TypeDef* cs_gpiox, uint16_t cs_gpio_pin); struct ch32_soft_spi_pin { GPIO_TypeDef* GPIOx; uint16_t GPIO_Pin; }; struct ch32_soft_spi_config { struct ch32_soft_spi_pin mosi_pin; struct ch32_soft_spi_pin miso_pin; struct ch32_soft_spi_pin sclk_pin; char *bus_name; }; struct ch32_soft_spi_device { rt_uint8_t cs_pin; char *bus_name; char *device_name; }; /* stm32 soft spi dirver class */ struct ch32_soft_spi { uint8_t mode; uint8_t cpha; uint8_t cpol; uint8_t data_width; uint8_t msb; uint16_t dummy_data; uint32_t spi_delay; struct ch32_soft_spi_config *config; struct rt_spi_configuration *cfg; struct rt_spi_bus spi_bus; }; #endif /*__DRV_SOFT_SPI_H_ */ ``` ### 1.5 RT-Thread Settings配置 打开相应开关即可 ![screenshot_image-20220814224621654.png](https://oss-club.rt-thread.org/uploads/20220815/5fdb8a957c6fc2492528f042e240a264.png.webp) ### 1.6 效果(图片是最终效果,实际可以看到SPI BUS设备即可) ![screenshot_image-20220814225049710.png](https://oss-club.rt-thread.org/uploads/20220815/b4b4853d6450df90ccaccd00fb05e85b.png) ## 2.挂载片外Flash(GD25Q16) ### 2.1 **soft_spi_flash.c添加以下代码:** ```c /* * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-08-14 MXH the first version */ #include
#include "spi_flash.h" #include "spi_flash_sfud.h" #include "drv_soft_spi.h" #include "fal.h" static int rt_sw_spi_flash_init(void) { /* PB3--->CS */ rt_soft_spi_device_attach(SOFT_SPI_FLASH_BUS_NAME, SOFT_SPI_FLASH_DEVICE_NAME, GPIOB, GPIO_Pin_3); // rt_soft_spi_device_attach(SOFT_SPI_FLASH_BUS_NAME, SOFT_SPI_FLASH_DEVICE_NAME, GPIOA, GPIO_Pin_15); if (RT_NULL == rt_sfud_flash_probe(SOFT_SPI_FLASH_NAME, SOFT_SPI_FLASH_DEVICE_NAME)) { return -RT_ERROR; } return RT_EOK; } INIT_COMPONENT_EXPORT(rt_sw_spi_flash_init); ``` ### 2.2 效果(图片是最终效果,实际可以看到SPI Device、GD25Q16即可) ![screenshot_image-20220814225336114.png](https://oss-club.rt-thread.org/uploads/20220815/a4474a64c7761cd084b51b5227ab0f47.png) ## 3.搭建FAL抽象层 ### 3.1 开启FAL组件 ![screenshot_image-20220814225437239.png](https://oss-club.rt-thread.org/uploads/20220815/ed5691830e2bd77a43131f7a68ec737b.png.webp) ### 3.2 打开fal组件的文件夹,可以看到/samples/porting中可以看到例程 **将fal_cfg.h添加到/fal/inc文件夹下,并进行一定的修改,片内flash好像还有一定问题,暂时删去:** ![screenshot_image-20220814225828051.png](https://oss-club.rt-thread.org/uploads/20220815/0d4d6283dff437895676c973ccebc6a0.png.webp) ```c /* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-05-17 armink the first version */ #ifndef _FAL_CFG_H_ #define _FAL_CFG_H_ #include
#include
/* ===================== Flash device Configuration ========================= */ //extern const struct fal_flash_dev ch32_onchip_flash; extern struct fal_flash_dev gd25q16_flash; /* flash device table */ #define FAL_FLASH_DEV_TABLE \ { \ &gd25q16_flash, \ } /* ====================== Partition Configuration ========================== */ #ifdef FAL_PART_HAS_TABLE_CFG /* partition table */ #define FAL_PART_TABLE \ { \ {FAL_PART_MAGIC_WORD, "flashkv", SOFT_SPI_FLASH_NAME, 0, 8 * 1024, 0},\ {FAL_PART_MAGIC_WORD, "flashts", SOFT_SPI_FLASH_NAME, 8 * 1024, 2040 * 1024, 0},\ } #endif /* FAL_PART_HAS_TABLE_CFG */ #endif /* _FAL_CFG_H_ */ ``` ### 3.3 **soft_spi_flash.c修改为以下内容:** ```c /* * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-07-27 MXH the first version */ #include
#include "spi_flash.h" #include "spi_flash_sfud.h" #include "drv_soft_spi.h" #include "fal.h" #ifdef BSP_USING_SOFT_SPI_FLASH static int rt_sw_spi_flash_init(void) { /* PB3--->CS */ rt_soft_spi_device_attach(SOFT_SPI_FLASH_BUS_NAME, SOFT_SPI_FLASH_DEVICE_NAME, GPIOB, GPIO_Pin_3); // rt_soft_spi_device_attach(SOFT_SPI_FLASH_BUS_NAME, SOFT_SPI_FLASH_DEVICE_NAME, GPIOA, GPIO_Pin_15); if (RT_NULL == rt_sfud_flash_probe(SOFT_SPI_FLASH_NAME, SOFT_SPI_FLASH_DEVICE_NAME)) { return -RT_ERROR; } return RT_EOK; } INIT_COMPONENT_EXPORT(rt_sw_spi_flash_init); static int init(void); static int read(long offset, uint8_t *buf, size_t size); static int write(long offset, const uint8_t *buf, size_t size); static int erase(long offset, size_t size); static sfud_flash_t gd25q16_dev = NULL; struct fal_flash_dev gd25q16_flash = { SOFT_SPI_FLASH_NAME, /* Flash 设备的名字 */ 0, /* 对 Flash 操作的起始地址:0x00000000 */ (2 * 1024 * 1024), /* Flash 的总大小:2 MB */ 4096, /* Flash 块/扇区大小:4096 */ { init, /* init 函数 */ read, /* read 函数 */ write, /* write 函数 */ erase /* erase 函数 */ }, 1 }; static int init(void) { #ifdef RT_USING_SFUD gd25q16_dev = rt_sfud_flash_find_by_dev_name(SOFT_SPI_FLASH_NAME); if(gd25q16_dev) { LOG_D("find flash dev %s.", gd25q16_dev->name); } else { LOG_E("don't find flash dev %s.", gd25q16_dev->name); } #else /* bare metal platform */ extern sfud_flash sfud_norflash0; gd25q16_dev = &sfud_norflash0; #endif if (NULL == gd25q16_dev) { return -RT_ERROR; } /* update the flash chip information */ gd25q16_flash.blk_size = gd25q16_dev->chip.erase_gran; gd25q16_flash.len = gd25q16_dev->chip.capacity; return RT_EOK; } static int read(long offset, uint8_t *buf, size_t size) { assert(gd25q16_dev); assert(gd25q16_dev->init_ok); sfud_read(gd25q16_dev, gd25q16_flash.addr + offset, size, buf); return size; } static int write(long offset, const uint8_t *buf, size_t size) { assert(gd25q16_dev); assert(gd25q16_dev->init_ok); if (sfud_write(gd25q16_dev, gd25q16_flash.addr + offset, size, buf) != SFUD_SUCCESS) { return -RT_ERROR; } return size; } static int erase(long offset, size_t size) { assert(gd25q16_dev); assert(gd25q16_dev->init_ok); if (sfud_erase(gd25q16_dev, gd25q16_flash.addr + offset, size) != SFUD_SUCCESS) { return -RT_ERROR; } return size; } #endif/* end of BSP_USING_SOFT_SPI_FLASH */ ``` ### 3.4 在main.c中添加初始化代码 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220815/acec382fde6dacdf3da685fbb660cc1e.png) ### 3.5 效果 ![screenshot_image-20220814230056016.png](https://oss-club.rt-thread.org/uploads/20220815/e41e28fe7cad5dd900113a01de399b5d.png.webp) ![screenshot_image-20220814230151188.png](https://oss-club.rt-thread.org/uploads/20220815/b0106f9f15fd70f634422c912b6be81f.png) ## 4.对接FlashDB(这一步可以先把main函数里的初始化给删掉,不影响结果) ### 4.1 搜索并添加FlashDB软件包,默认配置如下 ![screenshot_image-20220814230559174.png](https://oss-club.rt-thread.org/uploads/20220815/8bab18c09a5607e282e29d916d07501c.png.webp) ### 4.2 在/applications文件夹下添加database.c,代码内容如下 ```c #include
#include
#include "rtthread.h" #include
#include "drivers/rtc.h" #include "time.h" #define FDB_LOG_TAG "FLASHDB" /* key */ #define KEY_BOOT_COUNT "boot_count" #define KEY_DEVICE_ID "device_id" /* value */ static uint32_t value_boot_count = 0; static char value_device_id[] = "54549921"; /* kvdb & tsdb */ struct fdb_kvdb _global_kvdb = {0}; struct fdb_tsdb _global_tsdb = {0}; /* kvdb table */ static struct fdb_default_kv_node default_kv_table[] = { { KEY_BOOT_COUNT, &value_boot_count, sizeof(value_boot_count) }, { KEY_DEVICE_ID, value_device_id, sizeof(value_device_id) } }; /* int type KV */ static fdb_time_t get_time(void) { return (fdb_time_t)time(RT_NULL); } static int print_system_info(void) { struct fdb_blob blob; { /* GET the KV value */ /* get the "device_id" KV value */ fdb_kv_get_blob(&_global_kvdb, KEY_DEVICE_ID, fdb_blob_make(&blob, value_device_id, sizeof(value_device_id))); /* the blob.saved.len is more than 0 when get the value successful */ if (blob.saved.len > 0) { FDB_INFO("get the 'device_id' value is %s\n", value_device_id); } else { FDB_INFO("get the 'device_id' failed\n"); { /* CHANGE the KV value */ /* change the "boot_count" KV's value */ fdb_kv_set_blob(&_global_kvdb, KEY_DEVICE_ID, fdb_blob_make(&blob, value_device_id, sizeof(value_device_id))); FDB_INFO("set the 'device_id' value to %s\n", value_device_id); } } } { /* GET the KV value */ /* get the "boot_count" KV value */ fdb_kv_get_blob(&_global_kvdb, KEY_BOOT_COUNT, fdb_blob_make(&blob, &value_boot_count, sizeof(value_boot_count))); /* the blob.saved.len is more than 0 when get the value successful */ if (blob.saved.len > 0) { FDB_INFO("get the 'boot_count' value is %d\n", value_boot_count); } else { FDB_INFO("get the 'boot_count' failed\n"); } } { /* CHANGE the KV value */ /* increase the boot count */ value_boot_count ++; /* change the "boot_count" KV's value */ fdb_kv_set_blob(&_global_kvdb, KEY_BOOT_COUNT, fdb_blob_make(&blob, &value_boot_count, sizeof(value_boot_count))); FDB_INFO("set the 'boot_count' value to %d\n", value_boot_count); } FDB_INFO("===========================================================\n"); } static int datbase_init(void) { fdb_err_t result; struct fdb_default_kv default_kv; default_kv.kvs = default_kv_table; default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]); //init函数的第三个参数,是用于存储数据的fal分区,根据自己的情况选择 result = fdb_kvdb_init(&_global_kvdb, "sys_info", "flashkv", &default_kv, NULL); if (result != FDB_NO_ERR) { return -RT_ERROR; } else { print_system_info(); } result = fdb_tsdb_init(&_global_tsdb, "storage_data", "flashts", get_time, 128, RT_NULL); if (result != FDB_NO_ERR) { return -RT_ERROR; } else { extern void tsdb_sample(fdb_tsdb_t tsdb); tsdb_sample(&_global_tsdb); FDB_INFO("init tsdb success.\n"); } return RT_EOK; } INIT_ENV_EXPORT(datbase_init); ``` ### 4.3 效果 ![screenshot_image-20220814230802207.png](https://oss-club.rt-thread.org/uploads/20220815/9cffd5a44c6a83fa144466d1da0c1e45.png.webp) ![screenshot_image-20220814230814461.png](https://oss-club.rt-thread.org/uploads/20220815/136e991821939ed366c7ebcd6397efb8.png.webp) ## 5.总结 主要是初始化操作,网上百度的内容好像有点旧,更新一下,主要内容就是抄参考链接的内容,感谢大佬们分享那么牛逼的内容,侵权删。 ## 参考链接 [FlashDB快速开始 (gitee.io)](http://armink.gitee.io/flashdb/#/zh-cn/quick-started) [RT-Thread-【12月】RT-Thread Studio学习笔记之部署FlashDBRT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/349aa10c2052cd40.html) [RT-Thread-STM32模拟SPI设备驱动RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/question/28018d441c51d4a1.html) ## 碎碎念 - 呜呜呜,真心希望沁恒推动RTT的驱动编写啊,自己写驱动快写吐了; - FlashDB的移植教程很好,大家可以参考; - FlashDB的初始化例程好像不是很详细,我也没找到,大家有的话可以分享以下。
3
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
喵小黑
这家伙很懒,什么也没写!
文章
5
回答
3
被采纳
0
关注TA
发私信
相关文章
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
线程
RT-Thread Nano
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
807
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部