RK3288 android7.1.2 android studio 用户空间通过spi ioctl读取flash ID(进阶篇五)
准备工作:
1.搭建adbwireless 环境
参考:https://blog.csdn.net/Chhjnavy/article/details/97643584
https://blog.csdn.net/Chhjnavy/article/details/98845930
2.熟悉使用jni 将C与java互通
参考:https://blog.csdn.net/Chhjnavy/article/details/94721080
目标板:rk3288 android
系统:android7.1.2
1.源码根目录:/kernel/arch\arm/boot/dts 在rk3288-miniarm.dts 文件中添加spi 设备节点
&spi2 {status = "okay";max-freq = <50000000>;spidev@0 {compatible = "rockchip,spi_tinker";reg = <0>;spi-max-frequency = <50000000>;spi-cpha = <1>;};spidev@1 {compatible = "rockchip,spi_tinker";reg = <1>;spi-max-frequency = <50000000>;spi-cpha = <1>;};};
2.make menuconfig 添加驱动模块
3.kernel 重新编译后,将最终的镜像烧录SD卡,通过终端可以在/dev 下看到spidev2.0 spidev2.1 两个设备节点
其中 spidev2.0 spidev2.1 中的数字2 表示bus num ,小数点后的0 和 1 分别表示使用的是选通信号cs0 ,cs1
对应的物理引脚如下所示:
使用杜邦线将rk3288 的spi 引脚与flash spi引脚对接 : GP8B1_SPI2TXD = DI 、 GP8B0_SPI2RXD = DO
GP8A6_SPI2CLK = CLK 、 GP8A7_SPI2CSN0 = CS 、 GND = GND
4.通过open 打开spidev2.0 设备(CS 连接的是GP8A7_SPI2CSN0 )获取设备号
/* * unsigned char u8BusIndex 是从UI 中获取的使用spidev2.x 表示使用0 还是 1 * 这里cs 硬件连接的是0 * */int SPI_open(unsigned char u8BusIndex){ char szDev[16] = {0}; int fd,ret; sprintf(szDev, "/dev/spidev2.%d", u8BusIndex); fd = open(szDev, O_RDWR); LOGD("*************************************************fd = %d", fd); if (fd < 0) { perror( "can not open SPI device\n" ); } ret = ioctl(fd, SPI_IOC_WR_MODE,&mode); if (ret == -1) LOGD("can't set spi mode"); ret = ioctl(fd, SPI_IOC_RD_MODE,&mode); if (ret == -1) LOGD("can't get spi mode"); ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); if (ret == -1) LOGD("can't set bits per word"); ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); if (ret == -1) LOGD("can't get bits per word"); ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); if (ret == -1) LOGD("can't set max speed hz"); ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); if (ret == -1) LOGD("can't get max speed hz"); LOGD("spi mode: %d\n", mode); LOGD("bits per word: %d\n", bits); LOGD("max speed: %d Hz (%d MHz)\n", speed, speed/1000000); return fd;}
5.通过 spi 提供的结构体 struct spi_ioc_transfer xfer[7]; 来配置spi 发送时序
/*Command Type MX25L25645GRDID 9Fh Manufacturer ID Memory Type Memory Density C2 20 19RES ABh Electronic ID 18REMS 90h Manufacturer ID Device ID C2 18QPIID AFh Manufacturer ID Memory Type Memory Density C2 20 19*/int SPI_readFlashID(unsigned int u8BusIndex){ int ret; int fd; uint8_t readIDCmd[1]; uint8_t readDummy[1]; uint8_t readDummy2[1]; uint8_t readADD[1]; uint8_t dataID[3] = {0}; fd = SPI_open(u8BusIndex); if(fd < 0){ LOGD("fail open device ==================fd = %d", fd); return -1; } struct spi_ioc_transfer xfer[7]; memset(xfer, 0, sizeof(xfer)); readIDCmd[0]=0x9F; xfer[0].tx_buf =(unsigned long)readIDCmd; xfer[0].len = 1; readDummy[0]=0x00; xfer[1].tx_buf =(unsigned long)readDummy; xfer[1].len = 1; readDummy2[0]=0x00; xfer[2].tx_buf =(unsigned long)readDummy2; xfer[2].len = 1; readADD[0]=0x00; xfer[3].tx_buf =(unsigned long)readADD; xfer[3].len = 1; xfer[4].rx_buf = (unsigned long)dataID; xfer[4].len = 1; xfer[5].rx_buf = (unsigned long)(dataID+1); xfer[5].len = 1; xfer[6].rx_buf = (unsigned long)(dataID+2); xfer[6].len = 1; ret = ioctl(fd, SPI_IOC_MESSAGE(7), xfer); if (ret < 0) { LOGD("********************Error: SPI_IOC_MESSAGE\n"); return -1; } LOGD("dataID[0]************************************************* = %x", dataID[0]); LOGD("dataID[1]************************************************* = %x", dataID[1]); LOGD("dataID[2]************************************************* = %x", dataID[2]); return ret;}
6.在jni 中直接调用 函数 int SPI_readFlashID(unsigned int u8BusIndex) 即可打印看到spi ID ,完整code 如下:
#include #include#include #include #include #include #include #include #include #include #include #include #include #include#include #include #include #include #include #include #include #define TAG "myDemo-jni" // 这个是自定义的LOG的标识#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型#define TAG "myDemo-jni" // 这个是自定义的LOG的标识#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型#define _Included_com_example_t613_spi_Java_Interfacestatic unsigned char mode=SPI_MODE_0;static unsigned char bits = 8;static unsigned char delay = 10;static unsigned int speed = 2200000;#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))/* * unsigned char u8BusIndex 是从UI 中获取的使用spidev2.x 表示使用0 还是 1 * 这里cs 硬件连接的是0 * */int SPI_open(unsigned char u8BusIndex){ char szDev[16] = {0}; int fd,ret; sprintf(szDev, "/dev/spidev2.%d", u8BusIndex); fd = open(szDev, O_RDWR); LOGD("*************************************************fd = %d", fd); if (fd < 0) { perror( "can not open SPI device\n" ); } ret = ioctl(fd, SPI_IOC_WR_MODE,&mode); if (ret == -1) LOGD("can't set spi mode"); ret = ioctl(fd, SPI_IOC_RD_MODE,&mode); if (ret == -1) LOGD("can't get spi mode"); ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); if (ret == -1) LOGD("can't set bits per word"); ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); if (ret == -1) LOGD("can't get bits per word"); ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); if (ret == -1) LOGD("can't set max speed hz"); ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); if (ret == -1) LOGD("can't get max speed hz"); LOGD("spi mode: %d\n", mode); LOGD("bits per word: %d\n", bits); LOGD("max speed: %d Hz (%d MHz)\n", speed, speed/1000000); return fd;}int SPI_close(int dev_fh){ return close(dev_fh);}/*Command Type MX25L25645GRDID 9Fh Manufacturer ID Memory Type Memory Density C2 20 19RES ABh Electronic ID 18REMS 90h Manufacturer ID Device ID C2 18QPIID AFh Manufacturer ID Memory Type Memory Density C2 20 19*/int SPI_readFlashID(unsigned int u8BusIndex){ int ret; int fd; uint8_t readIDCmd[1]; uint8_t readDummy[1]; uint8_t readDummy2[1]; uint8_t readADD[1]; uint8_t dataID[3] = {0}; fd = SPI_open(u8BusIndex); if(fd < 0){ LOGD("fail open device ==================fd = %d", fd); return -1; } struct spi_ioc_transfer xfer[7]; memset(xfer, 0, sizeof(xfer)); readIDCmd[0]=0x9F; xfer[0].tx_buf =(unsigned long)readIDCmd; xfer[0].len = 1; readDummy[0]=0x00; xfer[1].tx_buf =(unsigned long)readDummy; xfer[1].len = 1; readDummy2[0]=0x00; xfer[2].tx_buf =(unsigned long)readDummy2; xfer[2].len = 1; readADD[0]=0x00; xfer[3].tx_buf =(unsigned long)readADD; xfer[3].len = 1; xfer[4].rx_buf = (unsigned long)dataID; xfer[4].len = 1; xfer[5].rx_buf = (unsigned long)(dataID+1); xfer[5].len = 1; xfer[6].rx_buf = (unsigned long)(dataID+2); xfer[6].len = 1; ret = ioctl(fd, SPI_IOC_MESSAGE(7), xfer); if (ret < 0) { LOGD("********************Error: SPI_IOC_MESSAGE\n"); return -1; } LOGD("dataID[0]************************************************* = %x", dataID[0]); LOGD("dataID[1]************************************************* = %x", dataID[1]); LOGD("dataID[2]************************************************* = %x", dataID[2]); return ret;}extern "C"{JNIEXPORT jbyteArray JNICALL Java_com_example_t613_1spi_Java_1Interface_SPI_1read(JNIEnv *env, jobject instance, jbyte u8BusIndex, jint u32RegStart, jint nLen){ int nRet; unsigned char u8Read[2] = {0}; int szTmp[1] = {-1}; jbyteArray jResult = env->NewByteArray(nLen + 1); unsigned char *pTmp = (unsigned char*)malloc(nLen + 1); if(!pTmp) { env->SetByteArrayRegion(jResult, 0, 1, (jbyte*)szTmp); }else { nRet = SPI_readFlashID((unsigned char)u8BusIndex); for(int i = 0; i < nLen; i++) { pTmp[i + 1] = u8Read[i]; } pTmp[0] = nRet; if(nRet) { env->SetByteArrayRegion(jResult, 0, 1, (jbyte*)pTmp); } else { env->SetByteArrayRegion(jResult, 0, nLen + 1, (jbyte*)pTmp); } free(pTmp); } LOGD("================================================================="); return jResult;}JNIEXPORT jint JNICALL Java_com_example_t613_1spi_Java_1Interface_SPI_1write(JNIEnv *env, jobject instance, jbyte u8BusIndex, jint u32RegStart, jbyteArray _szBufWrite){ jint nRet; jint nLen = env->GetArrayLength(_szBufWrite); jbyte *pszWrite = env->GetByteArrayElements(_szBufWrite, NULL); for(int i = 0; i < nLen; i++) { if(nRet) break; } env->ReleaseByteArrayElements(_szBufWrite, pszWrite, 0); return nRet;}}
注意:
1)通过终端给/dev/spidev2.0 可执行权限
chmod 777 /dev/spidev2.0
2)jni code 中只是调用一下,UI 中并没有显示出ID, ID 通过logcat 打印看到。
完整app code 链接如下(点击read 即可在android studio logcat 下看到打印的flash ID):https://download.csdn.net/download/chhjnavy/11644546
更多相关文章
- Ubuntu 10.04不能连接到HTC G1设备
- XML 常见符号的实体定义:用在 Android(安卓)的 strings.xml 中
- Android中自定义组件及自定义属性
- Android获取定位权限,获取设备所在的经纬度
- Android(安卓)RoboGuice2 使用指南(3): Inject 自定义View
- mac 下android开发 eclipse中找不到设备
- android-自定义Seekbar
- Android训练课程)快三如何快速回本稳赢81512073
- android之自定义渐变颜色(一)