rt-thread之w25q128驱动编写记录(未使用sfud通用串行库)

2024-04-01 10:28

本文主要是介绍rt-thread之w25q128驱动编写记录(未使用sfud通用串行库),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

  1. 未使用sfud的方式,自己编写驱动的方式记录
  2. 使用的是spi1

硬件驱动IO初始化

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-3-31     shchl   first version*/
#include "board.h"void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) {GPIO_InitTypeDef GPIO_InitStruct = {0};
#ifdef BSP_USING_SPI1if (hspi->Instance == SPI1) {__HAL_RCC_SPI1_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/**SPI1 GPIO ConfigurationPB3     ------> SPI1_SCKPB4     ------> SPI1_MISOPB5     ------> SPI1_MOSI*/GPIO_InitStruct.Pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);return;}
#endif}

w25q128

头文件

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-3-31     shchl   first version*/#ifndef EXAMPLE_W25Q128_FLASH_W25Q128_H
#define EXAMPLE_W25Q128_FLASH_W25Q128_H#include "board.h"#define W25Q128_DEVICE_ID 0x6817  /*根据实际情况(厂商的ID可能不是EF开头)*/#define W25Q128_CS_PIN GET_PIN(B,14)
#define W25Q128_SPI_NO "spi10"void w25q128_init(const char *bus_name, const char *dev_no);uint16_t w25q128_read_deviceID();uint32_t w25q128_read_JEDECID();uint8_t w25q128_read_status_reg1();uint8_t w25q128_read_status_reg2();rt_err_t w25q128_device_check();rt_err_t w25q128_write_enable();rt_err_t w25q128_write_disable();void w25q128_erase_4k(uint32_t addr);void w25q128_erase_32k(uint32_t addr);void w25q128_erase_63k(uint32_t addr);rt_err_t w25q128_write_page(uint32_t addr, uint8_t *buf, uint16_t len);rt_err_t w25q128_read_data(uint32_t addr, uint8_t *dst, uint16_t len);rt_err_t w25q128_wake_up();rt_err_t w25q128_power_down();#endif //EXAMPLE_W25Q128_FLASH_W25Q128_H

源文件

/** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2024-3-31     shchl   first version*/#include "Flash_W25Q128.h"#define DBG_ENABLE
#define DBG_TAG "w25q128"
#ifndef APP_LOG_LVL
#define DBG_LVL DBG_LOG
#else
#define DBG_LVL APP_LOG_LVL
#endif#include "rtdbg.h"struct rt_spi_device *spi_device = RT_NULL;void w25q128_init(const char *bus_name, const char *dev_no) {spi_device = (struct rt_spi_device *) rt_malloc(sizeof(struct rt_spi_device));if (!spi_device) {LOG_E("Failed to malloc the spi device.");return;}if (RT_EOK != rt_spi_bus_attach_device_cspin(spi_device, dev_no, bus_name, W25Q128_CS_PIN, RT_NULL)) {LOG_E("Failed to attach the spi device.");return;}/*spi 配置*/struct rt_spi_configuration spi_conf;{spi_conf.mode = RT_SPI_MASTER | RT_SPI_MSB | RT_SPI_MODE_0;spi_conf.data_width = 8;spi_conf.max_hz = 40 * 1000 * 1000;rt_spi_configure(spi_device, &spi_conf);}/*设备校验*/if (w25q128_device_check() != RT_EOK) {LOG_E("w25q128 device id is different set(%#x)", W25Q128_DEVICE_ID);}}static rt_err_t w25q128_tx_rx(uint8_t *send, uint16_t send_len, uint8_t *rec, uint16_t rec_len) {if (send && rec) {return rt_spi_send_then_recv(spi_device, send, send_len, rec, rec_len);} else if (send) {return rt_spi_send(spi_device, (const void *) send, send_len) == send_len ? RT_EOK : RT_EIO;}return rt_spi_recv(spi_device, rec, rec_len) == rec_len ? RT_EOK : RT_EIO;
}static rt_err_t w25q128_tx_tx(uint8_t *cmd, uint16_t cmd_len, uint8_t *data, uint16_t data_len) {return rt_spi_send_then_send(spi_device, cmd, cmd_len, data, data_len);
}uint16_t w25q128_read_deviceID() {uint8_t cmd[4] = {0x90, 00, 00, 00};uint8_t rec[2];if (w25q128_tx_rx(cmd, 4, rec, 2) != RT_EOK) return 0;return (uint16_t) (rec[0] << 8 | rec[1]);
}uint32_t w25q128_read_JEDECID() {uint8_t cmd[1] = {0x9f};uint8_t rec[3];if (w25q128_tx_rx(cmd, 1, rec, 3) != RT_EOK) return 0;return (uint32_t) (rec[0] << 16 | rec[1] << 8 | rec[2]);
}static inline void w25q128_wait_busy() {while (w25q128_read_status_reg1() & 0x1) {rt_hw_us_delay(100);}
}/*** @brief 读取状态寄存器 1* @return (S7--S0)*/
uint8_t w25q128_read_status_reg1() {uint8_t cmd[1] = {0x05};uint8_t rec[1];return w25q128_tx_rx(cmd, 1, rec, 1) == RT_EOK ? rec[0] : UINT8_MAX;
}/*** @brief 读取状态寄存器 2* @return (S15--S8)*/
uint8_t w25q128_read_status_reg2() {uint8_t cmd[1] = {0x35};uint8_t rec[1];return w25q128_tx_rx(cmd, 1, rec, 1) == RT_EOK ? rec[0] : UINT8_MAX;
}/*** @brief 写使能* @return*/
rt_err_t w25q128_write_enable() {uint8_t cmd[1] = {0x06};return w25q128_tx_rx(cmd, 1, NULL, 0);}/*** @brief 写保护* @return*/
rt_err_t w25q128_write_disable() {uint8_t cmd[1] = {0x04};return w25q128_tx_rx(cmd, 1, NULL, 0);
}/*** 从掉电模式下唤醒* @return*/
rt_err_t w25q128_wake_up() {uint8_t cmd[1] = {0xAB};return w25q128_tx_rx(cmd, 1, NULL, 0);
}/*** 进入掉电模式* @return*/
rt_err_t w25q128_power_down() {uint8_t cmd[1] = {0xB9};return w25q128_tx_rx(cmd, 1, NULL, 0);
}rt_err_t w25q128_device_check() {return w25q128_read_deviceID() == W25Q128_DEVICE_ID ? RT_EOK : RT_ERROR;
}static inline rt_err_t w25q128_erase(uint32_t addr, uint8_t cmd) {w25q128_write_enable();uint8_t page_wr[4] = {cmd, ((addr >> 16) & 0xFF), ((addr >> 8) & 0xFF), addr & 0xFF};return w25q128_tx_rx(page_wr, 4, NULL, 0);
}void w25q128_erase_4k(uint32_t addr) {w25q128_erase(addr, 0x20);w25q128_wait_busy();}void w25q128_erase_32k(uint32_t addr) {w25q128_erase(addr, 0x52);w25q128_wait_busy();
}void w25q128_erase_63k(uint32_t addr) {w25q128_erase(addr, 0xD8);w25q128_wait_busy();
}rt_err_t w25q128_write_page(uint32_t addr, uint8_t *buf, uint16_t len) {/*写使能*/w25q128_write_enable();uint8_t page_wr[4] = {0x02, ((addr >> 16) & 0xFF), ((addr >> 8) & 0xFF), addr & 0xFF};if (w25q128_tx_tx(page_wr, 4, buf, len) != RT_EOK) return RT_ERROR;w25q128_wait_busy();return RT_EOK;
}rt_err_t w25q128_read_data(uint32_t addr, uint8_t *dst, uint16_t len) {uint8_t rd[4] = {0x03, ((addr >> 16) & 0xFF), ((addr >> 8) & 0xFF), addr & 0xFF};return w25q128_tx_rx(rd, 4, dst, len);
}#if 1int w25q128_test() {w25q128_init("spi1", "spi10");if (!spi_device) {rt_kprintf("spi init err\r\n");return -1;}
//    w25q128_wake_up();
#define BUF_SZ sizeof(buf)/ sizeof(buf[0])uint8_t buf[10];for (int i = 0; i < BUF_SZ; ++i) {buf[i] = i * 5;}w25q128_erase_4k(0x0);
//    rt_thread_mdelay(20);if (w25q128_write_page(0x0, buf, BUF_SZ) == RT_EOK) {rt_kprintf("w25q128_write_page ok\r\n");rt_memset(buf, 0, BUF_SZ);rt_thread_mdelay(10);if (w25q128_read_data(0x0, buf, BUF_SZ) == RT_EOK) {rt_kprintf("read data from w25q128: ");for (int i = 0; i < BUF_SZ; ++i) {rt_kprintf("%d ", buf[i]);}rt_kprintf("\r\n");} else {rt_kprintf("w25q128 read data err\r\n");}} else {rt_kprintf("w25q128_write_page err\r\n");}return 0;
}INIT_DEVICE_EXPORT(w25q128_test);#endif

这篇关于rt-thread之w25q128驱动编写记录(未使用sfud通用串行库)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/866920

相关文章

在Android中使用WebView在线查看PDF文件的方法示例

《在Android中使用WebView在线查看PDF文件的方法示例》在Android应用开发中,有时我们需要在客户端展示PDF文件,以便用户可以阅读或交互,:本文主要介绍在Android中使用We... 目录简介:1. WebView组件介绍2. 在androidManifest.XML中添加Interne

Java Stream流与使用操作指南

《JavaStream流与使用操作指南》Stream不是数据结构,而是一种高级的数据处理工具,允许你以声明式的方式处理数据集合,类似于SQL语句操作数据库,本文给大家介绍JavaStream流与使用... 目录一、什么是stream流二、创建stream流1.单列集合创建stream流2.双列集合创建str

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有