在freescale mx6DL 平台上添加spi资源

在freescale mx6DL 平台上添加spi资源,通过SPI总线挂载两个SPI设备,APP层通过JNI层访问设备文件,通过设备文件实现 SPI 通信

硬件平台 :freescale mx6DL 

软件平台:Android4.4.2

系统:Ubuntu14.04


1. 打开系统SPI驱动


       



kernel_imx/drivers/spi/spi.c
kernel_imx/drivers/spi/spi_imx.c
kernel_imx/drivers/spi/spidev.c

查看 kernel_imx/drivers/spi/Makefile Kconfig文件,保证上面三个文件参加编译


2. kernel_imx/arch/arm/mach-mx6/board-mx6q_sabresd.c

在函数 static void __init mx6_sabresd_board_init(void) 尾部添加

#ifdef __LFL_SPI_
spi_device_init();
#endif//__LFL_SPI_


在当前文件的上部添加  #define __LFL_SPI_

#ifdef __LFL_SPI_


static iomux_v3_cfg_t mx6dl_sabresd_ecspi_pads[] = {  
#if 1
      /* SPI1 */


MX6DL_PAD_KEY_COL0__ECSPI1_SCLK,
MX6DL_PAD_KEY_ROW0__ECSPI1_MOSI,
MX6DL_PAD_KEY_COL1__ECSPI1_MISO,
MX6DL_PAD_KEY_ROW1__ECSPI1_SS0,
/* SPI2 */
#endif


/* I2C1 
MX6DL_PAD_CSI0_DAT8__I2C1_SDA,
MX6DL_PAD_CSI0_DAT9__I2C1_SCL,
*/
/*
UART1 for debug 
MX6DL_PAD_CSI0_DAT10__UART1_TXD,
MX6DL_PAD_CSI0_DAT11__UART1_RXD,
*/
/*
    MX6DL_PAD_CSI0_DAT8__ECSPI2_SCLK,  
    MX6DL_PAD_CSI0_DAT9__ECSPI2_MOSI,  
    MX6DL_PAD_CSI0_DAT10__ECSPI2_MISO,  
    //MX6DL_PAD_CSI0_DAT11__ECSPI2_SS0,// 如果采用内部片选信号,屏蔽下一行GPIO的声明,打开本处声明  
    MX6DL_PAD_CSI0_DAT11__GPIO_5_29,  
*/  
MX6DL_PAD_EIM_CS0__ECSPI2_SCLK,
MX6DL_PAD_EIM_CS1__ECSPI2_MOSI,
MX6DL_PAD_EIM_OE__ECSPI2_MISO,
MX6DL_PAD_EIM_D24__ECSPI2_SS2,
  
    /* SPI3  
    MX6DL_PAD_DISP0_DAT0__ECSPI3_SCLK,   
    MX6DL_PAD_DISP0_DAT1__ECSPI3_MOSI,   
    MX6DL_PAD_DISP0_DAT2__ECSPI3_MISO,   
    MX6DL_PAD_DISP0_DAT3__ECSPI3_SS0, */  // 如果采用内部片选信号,屏蔽下一行GPIO的声明,打开本处声明
    //MX6DL_PAD_DISP0_DAT3__GPIO_4_24,
};


//如果采用内部片选信号,则不添加GPIO的声明
#define SABRESD_ECSPI2_CS0 IMX_GPIO_NR(5, 29) // spi2 cs0  
#define SABRESD_ECSPI3_CS0 IMX_GPIO_NR(4, 24) // spi3 cs0


static int mx6q_sabresd_spi_cs1[] = {
MXC_SPI_CS(1),
// SABRESD_ECSPI1_CS0,
};


static const struct spi_imx_master mx6q_sabresd_spi_data1 __initconst = {
.chipselect     = mx6q_sabresd_spi_cs1,
.num_chipselect = ARRAY_SIZE(mx6q_sabresd_spi_cs1),
};


/* SPI2 cs0 */  
static int mx6q_sabresd_spi_cs2[] = {  
    MXC_SPI_CS(2),// 如果采用内部片选信号,屏蔽下一行GPIO的声明,打开本处声明  
//    SABRESD_ECSPI2_CS0,  
};  
  
static const struct spi_imx_master mx6q_sabresd_spi_data2 __initconst = {  
    .chipselect     = mx6q_sabresd_spi_cs2,  
    .num_chipselect = ARRAY_SIZE(mx6q_sabresd_spi_cs2),  
};  
  
/* SPI3 cs0 */  
static int mx6q_sabresd_spi_cs3[] = {  
    MXC_SPI_CS(3),// 如果采用内部片选信号,屏蔽下一行GPIO的声明,打开本处声明  
//    SABRESD_ECSPI3_CS0,  
};  
  
static const struct spi_imx_master mx6q_sabresd_spi_data3 __initconst = {  
    .chipselect     = mx6q_sabresd_spi_cs3,  
    .num_chipselect = ARRAY_SIZE(mx6q_sabresd_spi_cs3),  
};  


//spi.h
//#define SPI_CPHA 0x01 /* clock phase */
//#define SPI_CPOL 0x02 /* clock polarity */
//#define SPI_MODE_0 (0|0) /* (original MicroWire) */
//#define SPI_MODE_1 (0|SPI_CPHA)
//#define SPI_MODE_2 (SPI_CPOL|0)
//#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
static struct spi_board_info imx6_sabresd_spi_device[] __initdata = {  
#if 1
    /* SPI1 */  
    {  
        .modalias = "spidev",  
        .max_speed_hz = 8000000, /* max spi clock (SCK) speed in HZ */  
        .bus_num = 0,  
        .chip_select = 0,  
        .mode = SPI_MODE_1  ,  // | SPI_CS_HIGH,  
    }, 
#endif
    /* SPI2 */  
    {  
        .modalias = "spidev",  
        .max_speed_hz = 8000000, /* max spi clock (SCK) speed in HZ */  
        .bus_num = 1,  
        .chip_select = 0,  
        .mode = SPI_MODE_1  ,  // | SPI_CS_HIGH,  
    }, 
#if 0 
    /* SPI3 */  
    {  
        .modalias = "spi_imx",  
        .max_speed_hz = 8000000, /* max spi clock (SCK) speed in HZ */  
        .bus_num = 2,  
        .chip_select = 0,  
        .mode = SPI_MODE_1 ,  // | SPI_CS_HIGH,
    },  
#endif
};  




static void spi_device_init(void)
{


printk("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spi_device_init\n");


#if 1
printk("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spi_device_init  000\n");
    // 先初始化管脚  
    mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_ecspi_pads,  
            ARRAY_SIZE(mx6dl_sabresd_ecspi_pads));  
printk("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spi_device_init  001\n");
    // 添加片选信号  
    imx6q_add_ecspi(0, &mx6q_sabresd_spi_data1);  
    imx6q_add_ecspi(1, &mx6q_sabresd_spi_data2);  
//    imx6q_add_ecspi(2, &mx6q_sabresd_spi_data3);  
printk("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spi_device_init  002\n");
    // 注册设备  
    spi_register_board_info(imx6_sabresd_spi_device, ARRAY_SIZE(imx6_sabresd_spi_device));
printk("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spi_device_init  003\n");
#else


spi_register_board_info(imx6_sabresd_spi_nor_device,
ARRAY_SIZE(imx6_sabresd_spi_nor_device));


#endif
printk("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spi_device_init  end\n");
}


#endif



3.修改设备权限,否则应用程序无法访问设备

参考: http://blog.csdn.net/richu123/article/details/51204036

/system/core/init/device.c 


注意最后的返回值 0666

编译 ./mk_15_6.sh


4.烧写镜像


5.启动系统之后会在  /dev/ 目录生成如下两个设备



6. 编写测试程序

static const char *deviceSpi0 = "/dev/spidev0.0";
static const char *deviceSpi1 = "/dev/spidev1.0";
static U8 mode;
static U8 bits = 8;
static U32 speed = 7000000;
static U16 delay = 0;


static void setAddr(void)
{
    int ret;
    U8 tx[] = {
        0x05, 0x08,
    };
/*
    U8 tx[] = {
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
            0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
            0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,
            0xF0, 0x0D,
        };
*/
    U8 rx[ARRAY_SIZE(tx)] = {0};
    struct spi_ioc_transfer tr = {
        .tx_buf = /* NULL,// */(unsigned long)tx,
        .rx_buf = /* NULL,// */ (unsigned long)rx,
        .len = ARRAY_SIZE(tx),
        .delay_usecs = delay,
        .speed_hz = speed,
        .bits_per_word = bits,
    };




//    ret = read(fd,rx,ARRAY_SIZE(tx));


    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1)
        pabort("can't send spi message");








    for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
        if (!(ret % 6))
        cyVoiceE_SysPrintf("");
        cyVoiceE_SysPrintf("%.2X ", rx[ret]);
    }
    cyVoiceE_SysPrintf("");
}




int testSpi(void)
{
    int ret = 0;


    //parse_opts(argc, argv); /* for what ,unknow*/


    fd = open(deviceSpi0, O_RDWR);
    if (fd < 0)
        pabort("can't open device");


    /*
     * spi mode
     */
    ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    if (ret == -1)
        pabort("can't set spi mode");


    ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
    if (ret == -1)
        pabort("can't get spi mode");


    /*
     * bits per word
     */
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)
        pabort("can't set bits per word");


    ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
    if (ret == -1)
        pabort("can't get bits per word");


    /*
     * max speed hz
     */
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        pabort("can't set max speed hz");


    ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        pabort("can't get max speed hz");


    cyVoiceE_SysPrintf("spi mode: %d\n", mode);
    cyVoiceE_SysPrintf("bits per word: %d\n", bits);
    cyVoiceE_SysPrintf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);


    setAddr();


 //   close(fd);


    return ret;
}


7. 添加 JNI层接口


JNIEXPORT void JNICALL Java_com_philisense_flxPrsmBusLib_prsmEngine_testSpi(JNIEnv* env,jobject thiz)
{




cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmJNI_testSpi");


testSpi();




}




JNIEXPORT jlong JNICALL Java_com_philisense_flxPrsmBusLib_prsmEngine_createInstJNI(JNIEnv* env,jobject thiz,jint addr)
{
ST_FLX_PRSM_BUS *flxBus = NULL;
int ret = 0;
cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_createInstJNI env =0x%x",env);






ret = flxPrsmBusCreateInst(&flxBus,addr);
if(ret >= 0)
{
cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_createInstJNI  success");
}
else
{
cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_createInstJNI  fail ret = %d",ret);
}


return (jlong)flxBus;




}


JNIEXPORT jint JNICALL Java_com_philisense_flxPrsmBusLib_prsmEngine_processKeyJNI(JNIEnv* env,jobject thiz,jlong ptr,jint key)
{
ST_FLX_PRSM_BUS *flxBus = (ST_FLX_PRSM_BUS *)ptr;
int ret = 0;




// cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_processKeyJNI env =0x%x",env);


ret = flxPrsmBusSetKey(flxBus,key);
if(ret >= 0)
{
// cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_processKeyJNI  success");
}
else
{
cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_processKeyJNI  fail");
}


return ret;
}


JNIEXPORT jint JNICALL Java_com_philisense_flxPrsmBusLib_prsmEngine_processInstJNI(JNIEnv* env,jobject thiz,jlong ptr)
{
ST_FLX_PRSM_BUS *flxBus = (ST_FLX_PRSM_BUS *)ptr;
int ret = 0;


pSTprsmEngineEnvJni = env;
cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_processInstJNI env =0x%x",env);


//test
readCMD();


while(0)
{
ret = flxPrsmBusProcess(flxBus);
if(ret >= 0)
{
// cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_processInstJNI  success");
}
else
{
cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_processInstJNI  fail");
}
}


return ret;
}





JNIEXPORT jint JNICALL Java_com_philisense_flxPrsmBusLib_prsmEngine_destroyInstJNI(JNIEnv* env,jobject thiz,jlong ptr)
{
ST_FLX_PRSM_BUS *flxBus = (ST_FLX_PRSM_BUS *)ptr;
int ret = 0;




cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_destroyInstJNI");


ret = flxPrsmBusDestroyInst(flxBus);
if(ret >= 0)
{
cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_destroyInstJNI  success");
}
else
{
cyVoiceE_SysPrintf("\n Java_com_philisense_flxPrsmBusLib_prsmEngine_destroyInstJNI  fail");
}


return ret;
}


JNIEXPORT jstring JNICALL Java_com_philisense_flxPrsmBusLib_prsmEngine_getVersionJNI(JNIEnv* env,jobject thiz)
{
jstring jresult = 0 ;
char result[128] = {0};
int ret;


ret  = flxPrsmBusGetVersion(result,sizeof(result));


jresult = (*env)->NewStringUTF(env, (const char *)result);


cyVoiceE_SysPrintf("\n Java_com_vcyber_dtw_dtwEngine_getVersionJNI result = %s",result);


return jresult;




}



8.  添加对应的JAVA层接口 


package com.philisense.flxPrsmBusLib;


public class prsmEngine {

private long CPtr = 0;
private prsmUiListener pl = null;

/**
* @see 释放相关资源
*/
public synchronized void delete() {
   if (CPtr != 0) {
    prsmEngine.destroyInstJNI(CPtr);
     CPtr = 0;
   }
 }

/**
* @see 创建实例
* @param p UI消息监控接口
* @param addr 本机地址
*/
public prsmEngine(prsmUiListener p,int addr)
{
pl = p;

if(CPtr == 0)
CPtr = prsmEngine.createInstJNI(addr);
}

/**
* 检查引擎句柄是否为空
* @return 如果为空 返回  true
*/
public boolean isEmpty()
{
boolean ret = false;
if(CPtr == 0)
ret = true;
else
ret = false;

return ret;
}





/**
* @see 处理数据
*/
public void process()
{
prsmEngine.processInstJNI(CPtr);
}

/**
* @see 处理数据
*/
public void processKey(int key)
{
prsmEngine.processKeyJNI(CPtr,key);
}




/**
* @see 获得引擎版本
* @return 引擎版本
*/
public String getVersion()
{
return prsmEngine.getVersionJNI();
}


public void processUIinfo(final int msgID,final byte msg[],final int arg0)
{
if(this.pl != null)
{
this.pl.onDisplayUI(msgID, msg, arg0);
}
}


private final static native long createInstJNI(int addr);
private final static native int  destroyInstJNI(long ptr);
private final static native int  processKeyJNI(long ptr,int key);
private final static native int  processInstJNI(long ptr);
private final static native String getVersionJNI();


public final static native void testSpi();

static {
System.loadLibrary("flxPrsmBus");
}

}

9. 至此 j就可以通过JAVA层接口访问 SPI 设备了

public class prsmTask implements Runnable{
private prsmEngine prsm = null;


public prsmTask(prsmUiListener p)
{
//获得本机的地址
int addr  = 100;

//
prsm = new prsmEngine(p,addr);
}



public void processKey(int k)
{
prsm.processKey(k);
}


@Override
public void run() {
// TODO Auto-generated method stub

// prsmEngine.testSpi();


if(prsm.isEmpty() == false)
{
prsm.process();

}
}


}



10, 最后做个简单的总结,1,2,3,4,5部在Android源码里面,6,7,8,9部是在Android的APP中

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值