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  添加驱动模块

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

 3.kernel 重新编译后,将最终的镜像烧录SD卡,通过终端可以在/dev 下看到spidev2.0  spidev2.1  两个设备节点

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

 其中 spidev2.0  spidev2.1 中的数字2 表示bus num ,小数点后的0 和 1 分别表示使用的是选通信号cs0 ,cs1

对应的物理引脚如下所示:

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

使用杜邦线将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 
#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_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

你可能感兴趣的:(RK3288,android,thinker,board)