RK3288 android7.1.2 android studio 用户空间通过spi ioctl读取flash ID(进阶篇五)

28 篇文章 9 订阅
6 篇文章 0 订阅

准备工作:

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 MX25L25645G
RDID 9Fh Manufacturer ID Memory Type Memory Density
            C2              20          19
RES ABh Electronic ID
            18
REMS 90h Manufacturer ID Device ID
            C2              18
QPIID 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 <stdio.h>
#include<stdlib.h>
#include <math.h>

#include <linux/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <jni.h>
#include<android/log.h>

#include <unistd.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#include <linux/gpio.h>

#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_Interface

static 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 MX25L25645G
RDID 9Fh Manufacturer ID Memory Type Memory Density
            C2              20          19
RES ABh Electronic ID
            18
REMS 90h Manufacturer ID Device ID
            C2              18
QPIID 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

Android 7.1.2(也被称为Nougat)是Android操作系统的一个版本,它的源代码是公开可用的。源码包含了构建和运行Android操作系统所需的所有代码文件和资源。 Android操作系统是一个基于Linux内核的开源平台,用于移动设备和嵌入式系统。它提供了一个统一的操作系统环境,使开发者能够轻松地构建和定制自己的Android设备。 Android 7.1.2源码提供了一套开发工具和框架,使开发者能够创建功能丰富、稳定和安全的应用程序。该版本中引入了一些新的功能和改进,例如通知栏的增强、多任务处理的改进、Doze模式的优化等,以提供更好的用户体验。 通过查看源代码,开发者可以深入了解Android操作系统的内部工作原理,并理解其中的各个组件和模块是如何相互协作的。例如,开发者可以研究Android用户界面框架、应用程序生命周期管理、通信和存储机制等。 修复和优化Android 7.1.2源码也是可能的,因为它是开源的。开发者可以根据自己的需求和想法对操作系统进行修改,并参与到Android社区中,与其他开发者分享和贡献代码。 总之,Android 7.1.2源码为开发者提供了一个定制和构建Android应用的平台。通过深入了解源码,开发者能够创建出更加出色和创新的应用程序,同时也有机会参与到Android开源社区中,为整个生态系统的发展做出贡献。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值