一路做下来,感觉过程还是满复杂的,特意写一篇文章,方便大家用到类似的外设。
刚开始是想着自己写spi驱动,操作W25Q32的寄存器,本来已经读到芯片的ID了,后来因为cs脚的原因,以为自己写的程序有问题,转而找其他的方法,发现linux驱动中是支持这个系列的,路径在\drivers\mtd\devices\m25p80.c。具体操作为打开CONFIG_MTD_M25P80驱动,打开MTD相关的驱动,在dtd中加入
m25p80{compatible = "m25p80,w25q32";status = "okay";partition@0 {label = "JEDEC";reg = <0x0 0x1000>;read-only;};partition@1000 {label = "user";reg = <0x1000 0x3ff000>;};
};
内容精简掉了一些与平台相关的。
其实linux是把这种存储外设映射成mtd设备,我把它再分区一下,因为第一个块里存储着设备的id,所以设置成只读。
确认spi通信没问题,正常的话,就像下面这样
ls dev/block/mtdblock
ls dev/mtd/mtd
cat proc/mtd                                                 
dev:    size   erasesize  name
mtd0: 00001000 00001000 "JEDEC"
mtd1: 003ff000 00001000 "user"
接下来是在应用中操作/dev/mtd/mtd1节点。linux程序网上有很多,这里只给出android应用如何操作的具体代码
首先是jni里的
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <mtd/mtd-user.h>
#include <jni.h>#include "android/log.h"
static const char *TAG="25q32";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO,  TAG, fmt, ##args)
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)int fd=-1;JNIEXPORT void JNICALL Java_w25q32_open(JNIEnv *env, jclass thiz)
{/* Opening device */const char *path_utf = "/dev/mtd/mtd1";LOGD("Opening %s with flags 0x%x", path_utf, O_SYNC | O_RDWR);fd = open(path_utf, O_SYNC | O_RDWR);LOGD("open() fd = %d", fd);if (fd == -1){/* Throw an exception */LOGE("Cannot open 25q32");/* TODO: throw an exception */}
}JNIEXPORT void JNICALL Java_w25q32_close
(JNIEnv *env, jobject thiz)
{LOGD("close(fd = %d)", fd);if (fd != -1){close(fd);}
}#define BUF_SIZE   (64 * 1024)JNIEXPORT jint JNICALL JNICALL Java_w25q32_eraseFlash
(JNIEnv *env, jclass thiz, jint offset, jint bytes)
{int err;struct erase_info_user erase;erase.start = offset;erase.length = bytes;err = ioctl (fd,MEMERASE,&erase);if (err < 0){LOGE ("MEMERASE");return 1;}LOGD ("Erased %d bytes from address 0x%.8x in flash\n",bytes,offset);return 0;
}JNIEXPORT jbyteArray JNICALL JNICALL Java_w25q32_readFlash(JNIEnv *env, jclass thiz, jint offset, jint len)
{jbyte *buf = NULL;int size = len;int err;jbyteArray result;retry:if ((buf = (jbyte *) malloc (size)) == NULL){LOGD ("%s: malloc(%#x)\n", __FUNCTION__, size);if (size != BUF_SIZE) {size = BUF_SIZE;LOGE ("%s: trying buffer size %#x\n", __FUNCTION__, size);goto retry;}LOGE ("malloc()");goto err0;}if (offset != lseek (fd,offset,SEEK_SET)){LOGE ("lseek()");goto err1;}err = read (fd,buf,len);LOGD ("read %d", err);if (err < 0){goto err1;}result = (*env)->NewByteArray(env, err);if (result == NULL){LOGE ("NewByteArray()");goto err1;}(*env)->SetByteArrayRegion(env, result, 0, err, buf);LOGD ("Copied %zu bytes from address 0x%.8x in flash\n",err,offset);free (buf);return result;err1:if (buf != NULL)free (buf);err0:return NULL;
}JNIEXPORT jint JNICALL JNICALL Java_w25q32_writeFlash
(JNIEnv *env, jclass thiz, jint offset, jbyteArray array, jint len)
{jbyte *buf = NULL;int err;int size = len;if (offset != lseek (fd,offset,SEEK_SET)){LOGE ("lseek()");goto err0;}buf = (*env)->GetByteArrayElements(env, array, NULL);err = write (fd,buf,len);if (err < 0){LOGE ("%s: write, size %#x\n", __FUNCTION__, err);LOGE ("write()");goto err1;}LOGD ("Copied %d bytes to address 0x%.8x in flash\n", err, offset);(*env)->ReleaseByteArrayElements(env, array, buf, 0);return err;err1:(*env)->ReleaseByteArrayElements(env, array, buf, 0);
err0:return -1;
}

然后是java里的
public class w25q32 {/** Do not remove or rename the field mFd: it is used by native method* close();*/final int ROM_SIZE = 4190208;//0x3ff000final int PAGE_SIZE = 4096;//0x1000public w25q32() throws SecurityException{open();}public int w25q32_erase(String addr, int len){String hex = addr.replace("0x", "");int offset = Integer.parseInt(hex, 16);if(offset+len > ROM_SIZE)return -1;int times = len/PAGE_SIZE + (len%PAGE_SIZE>0?1:0);int erase_size = times*PAGE_SIZE;return eraseFlash(offset, erase_size);}public byte[] w25q32_read(String addr, int len){if(len<1)return null;String hex = addr.replace("0x", "");int offset = Integer.parseInt(hex, 16);int size = len;if(offset+size > ROM_SIZE) {size = ROM_SIZE - offset;}return readFlash(offset, size);}public int w25q32_write(String addr, byte[] buf, int len){if(buf == null)return -1;int ret = w25q32_erase(addr, len);if(ret != 0)return ret;String hex = addr.replace("0x", "");int offset = Integer.parseInt(hex, 16);return writeFlash(offset, buf, len);}public void releasePort(){close();}// JNIprivate native void open();private native void close();private native int eraseFlash(int offset, int bytes);private native byte[] readFlash(int offset, int len);private native int writeFlash(int offset, byte[] buf, int len);static {System.loadLibrary("xx");}
}
在应用中使用
w25q32 w25qxx = new w25q32();
w25qxx.w25q32_erase("0x0", 0x3ff000);
byte[] BUFFER1 = {0x0c,0x00,0x29,0x0b,0x01,0x00,(byte)0xfc,(byte)0xff,(byte)0xfa,0x00,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,0x0d,0x0a};
w25qxx.w25q32_write("0x1000", BUFFER1, BUFFER1.length);
byte[] BUFFER2 = w25qxx.w25q32_read("0x1000", BUFFER1.length);
w25qxx.releasePort();

以上。

Android下使用W25Q32相关推荐

  1. Android下实现数据绑定功能

    在编写Android应用的时候经常需要做的事情就是对View的数据进行设置,在Android下设置控件相对.net来说是件麻烦的事情,首先根据ID从view把控件找出来然后才能设置相应属性值:如果数据 ...

  2. Android下的动画

    ------你需要努力,你还没资格休息----- Android下的动画有三种: tween补间动画.frame帧动画.property属性动画(Android3.0后提出来的).补间动画: Tran ...

  3. android 按下home键执行什么,Android下得到Home键按下的消息

    在Android下,并不能通过onKeyDown这样的事件来截获Home键的消息,其原因在Android的文档中已经明确的说过了 翻译就不做了,总之就是App无法截获Home键的事件(曾经有高人在2. ...

  4. Android下的Linux

    1. Android目录结构 data app:用户安装的应用 data:应用的专属文件夹 system:系统的配置信息,注册表文件 anr:anr异常的记录信息 dev:devices的缩写 存放设 ...

  5. Android下NDK开发环境搭建

    Android下NDK开发环境搭建 1.     AndroidNDK安装与配置 1.1  NDK简介 Android NDK是一套允许开发人员使用本地代码(如C/C++)进行Android APP部 ...

  6. Android下拉刷新开源库对比(转)

    安卓下拉刷新开源库对比 作者:desmond1121 目前仅比对github上star数>1500的下拉刷新开源库,在比较完成之后可能会加入其它有代表性的库. Repo Repo Owner S ...

  7. Android下/data/data/package_name/files读写权限

    今天将更新模块拿到android上面测试的时候,发现在创建writablepath.."upd/"目录的时候出现Permission Denied提示 BTW:我使用的是lfs来创 ...

  8. android下拉刷新和上拉加载的一个简单库

    介绍一个android下拉刷新.上拉加载的库: https://github.com/chrisbanes/Android-PullToRefresh 使用方式,创建好一个Android项目,导入li ...

  9. Android 下 APK 捆绑器的实现

    Android 下 APK 捆绑器的实现                    作者: 海东青 利用捆绑器向正常程序捆绑病毒.木马等恶意程序,以达到隐蔽安装.运行的目的,这 在 Windows 平台下 ...

最新文章

  1. 当文员学计算机二级,二本学生毕业后在干什么?多半做3种工作,过来人深有同感...
  2. 23种设计模式C++源码与UML实现--组合模式
  3. 20162325金立清第三周作业
  4. 大数据集群搭建之节点的网络配置过程(二)
  5. python泰坦尼克号数据预测_使用python预测泰坦尼克号生还
  6. kobject_create_and_add解析
  7. win10删除开机密码_取消WIN10开机密码的方法
  8. 如何构建一个县的shp图?R语言和Global mapper
  9. select count(*) ,count() , select *
  10. Ubuntu——虚拟显示器的配置、卸载、修改分辨率
  11. java 本地连接状态_本地连接受限制
  12. 还记得愤怒的小鸟嘛?今天用Python给大家安排一波!
  13. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
  14. P4322 [JSOI2016]最佳团体(分数规划树上背包)
  15. 10、spss做最优尺度分析
  16. ipad好用的思维导图软件有哪些
  17. 验证google webrtc服务器demo(apprtc)使用的turn/stun服务器
  18. 全球自然奇迹Top50,中国上榜了3个
  19. 尚学堂Java学习笔记
  20. C++计算圆的面积和周长

热门文章

  1. 安装两个Mysql错误 ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)”
  2. 某公司盗用我的名字做虚假宣传
  3. 应用分发是什么意思?APP内测分发步骤
  4. 获取各大电商平台,item_get_app - 获得淘宝app商品详情原数据API返回数据说明
  5. Android应用内展示office文件--腾讯浏览服务(TBS)
  6. 输入框添加Emoje表情demo
  7. Python学习之道-烤机测试日志Log分析统计
  8. 多线程采集表情包,下一届斗图王者属于你
  9. 牛与马的把表情包(带有改进)
  10. 遮天、斗破苍穹、凡人修仙传、雪中悍刀行争第四届橙瓜网络文学奖