TI中文支持网
TI专业的中文技术问题搜集分享网站

linux操作系统下的upp驱动 如何使用

        最近,项目要使用upp与FPGA进行数据传输,同样的配置,裸核运行没有问题,但是在linux操作系统下以功能模块的方式进行添加,接收到的数据全为零,怀疑跟开启MMU有关,但是在linux操作系统下必会开启MMU,求解决方案,以下是我的驱动模块代码,大神们,帮忙看看:

#include <linux/module.h> /* 包含LICENSE的宏 */
#include <linux/init.h>   /* 包含module_init module_exit */
#include <linux/kernel.h>
#include <linux/io.h>    /* 包含ioremap之类 */
#include <linux/fs.h>  /* 包含file_operation结构体 */
#include <asm/uaccess.h> /*包含copy_to_user*/
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <mach/psc.h>
#include "hw_upp.h"
 
#define SOC_SYSCFG_0_REGS     (0x01C14120)
#define UPP_BASE_REGS         (0x01E16000)
#define UPP_LOOPBACK            
#define UPP_VERSION           (2)
#define UPP_BUFF_SIZE (128U)
#define UPP_RECV_LEN  (140U)
#define UPP_INT_NUM   (91U)

typedef unsigned int UINT32;typedef unsigned short UINT16;
typedef unsigned char UINT8;

typedef int INT32;
typedef short INT16;
typedef char INT8;

typedef float REAL32;
typedef double REAL64;

typedef void VOID;

static VOID bsp_upp_Send(const UINT16 sendData_aU16[], UINT32 sendBytes_U32);
static VOID bsp_upp_InitRecv(VOID);

/*设置s_bufferRecv_aU16变量的存储地址为64字节对齐*/
//#pragma DATA_ALIGN(s_bufferRecv_aU16, 64)
static UINT16 __attribute__((aligned(64))) s_bufferRecv_aU16[UPP_BUFF_SIZE];
/*设置s_bufferRecv_aU16变量的存储地址为64字节对齐*/
//#pragma DATA_ALIGN(s_bufferSend_aU16, 64)
static UINT16 __attribute__((aligned(64))) s_bufferSend_aU16[UPP_BUFF_SIZE];
/*UPP寄存器结构体定义*/

typedef struct UPP_REG_STRUCT{
    UINT32 ID_U32;    /*UPP ID 寄存器*/
    UINT32 Ctrl_U32;/*UPP Control 寄存器*/
    UINT32 DLB_U32;/*UPP Digital LoopBack 寄存器*/
    UINT32 Reserved5_U32;/*Reserved*/
    UINT32 CHCtrl_U32;/*UPP Channal Control 寄存器*/
    UINT32 ICfg_U32;/*Interface Configuration 寄存器*/
    UINT32 IVR_U32;/*Interface Idle Value 寄存器*/
    UINT32 ThCfg_U32;/*Threshold Configuration  寄存器*/
    UINT32 IntStat_U32;/*Interrupt Status 寄存器*/
    UINT32 IntEnStat_U32;/*Interrupt Enabled Status  寄存器*/
    UINT32 IntEnSet_U32;/*Interrupt Enabled Set  寄存器*/
    UINT32 IntEnClr_U32;/*Interrupt Enabled Clear 寄存器*/
    UINT32 EndofInt_U32;/*End-of-Interrupt 寄存器*/
    UINT32 Reserved_aU32[3];/*Reserved*/
    UINT32 DMACHNID0_U32;/*DMA Channel I Descriptor 0 寄存器*/
    UINT32 DMACHNID1_U32;/*DMA Channel I Descriptor 1 寄存器*/
    UINT32 DMACHNID2_U32;/*DMA Channel I Descriptor 2 寄存器*/
    UINT32 Reserved1_U32;/*Reserved*/
    UINT32 DMACHNIS0_U32;/*DMA Channel I Status 0 寄存器*/
    UINT32 DMACHNIS1_U32;/*DMA Channel I Status 1 寄存器*/
    UINT32 DMACHNIS2_U32;/*DMA Channel I Status 2 寄存器*/
    UINT32 Reserved2_U32;/*Reserved*/
    UINT32 DMACHNQD0_U32;/*DMA Channel Q Descriptor 0 寄存器*/
    UINT32 DMACHNQD1_U32;/*DMA Channel Q Descriptor 1 寄存器*/
    UINT32 DMACHNQD2_U32;/*DMA Channel Q Descriptor 2 寄存器*/
    UINT32 Reserved3_U32;/*Reserved*/
    UINT32 DMACHNQS0_U32;/*DMA Channel Q Status 0 寄存器*/
    UINT32 DMACHNQS1_U32;/*DMA Channel Q Status 1 寄存器*/
    UINT32 DMACHNQS2_U32;/*DMA Channel Q Status 2 寄存器*/
}UPP_REG;

static volatile UPP_REG *p_Reg = NULL;
static struct class *upp_class;
static struct device *upp_dev;
static unsigned int major;
static struct resource  *io_mem;
static unsigned int count = 0;
static unsigned char time[8];
static UINT16 s_send[25];
static UINT8 devid_I8 = 1;

static irqreturn_t upp_handler(int irq, void *data)
{
    count++;

    bsp_upp_InitRecv();
    p_Reg->IntEnStat_U32 = 0x1F1FU;
    p_Reg->EndofInt_U32 = 0x00000000U;
#ifndef UPP_LOOPBACK
    time[0] = s_bufferRecv_aU16[27] & 0xFF;
    time[1] = (s_bufferRecv_aU16[28] & 0xFF00) >>8;
    time[2] = s_bufferRecv_aU16[28] & 0x00FF;
    time[3] = (s_bufferRecv_aU16[29] & 0xFF00) >>8;
    time[4] = s_bufferRecv_aU16[29] & 0x00FF;
    time[5] = (s_bufferRecv_aU16[30] & 0xFF00) >>8;
    time[6] = s_bufferRecv_aU16[30] & 0x00FF;
#else
    time[0] = s_bufferRecv_aU16[5] & 0xFF;
    time[1] = (s_bufferRecv_aU16[5] & 0xFF00) >>8;
    time[2] = s_bufferRecv_aU16[6] & 0x00FF;
    time[3] = (s_bufferRecv_aU16[6] & 0xFF00) >>8;
    time[4] = s_bufferRecv_aU16[7] & 0x00FF;
    time[5] = (s_bufferRecv_aU16[7] & 0xFF00) >>8;
    time[6] = s_bufferRecv_aU16[8] & 0x00FF;
#endif
    return IRQ_HANDLED;
}

/* 定义一个打开设备的,open函数 */
static int upp_drv_open(struct inode *inode, struct file *filep)
{
    UINT32 iLoop_U32;
    INT32 status_I32;

    printk("upp_drv_open\n");
    status_I32 = request_irq(UPP_INT_NUM, upp_handler, 0,
            "upp_int", (void *)&devid_I8);
 
    if (status_I32 < 0) {
        printk("Open int failed!\n");
    }
    
    for(iLoop_U32=0;iLoop_U32<5;iLoop_U32++)
    {
        s_send[iLoop_U32] = 0x0000;
        s_send[5+iLoop_U32] = 0x0705;
        s_send[10+iLoop_U32] = 0x1501;
        s_send[15+iLoop_U32] = 0x1601;
        s_send[20+iLoop_U32] = 0x1701;
    }

#ifndef UPP_LOOPBACK
    bsp_upp_Send(s_send,50);
#else    bsp_upp_Send(s_send,32);
#endif

    printk("upp_send.\n");
 
    return status_I32;
}

static ssize_t upp_drv_write(struct file *file, const char __user * from, size_t len, loff_t *ppos)
{
//    char buf[10];
//    int ret, val;
//    int minor = 0; 
    return 0;
}

static ssize_t upp_drv_read(struct file *file, char __user * from, size_t len, loff_t *ppos)
{
//    char buf[10];
//    int ret, val;
//    int minor = 0;
    printk("Read Control Register!\n");
    printk("ID_U32 = 0x%x\tCtrl_U32 = 0x%x\tDLB_U32 = 0x%x\n",p_Reg->ID_U32,p_Reg->Ctrl_U32,p_Reg->DLB_U32);
    printk("CHCtrl_U32 = 0x%x\tICfg_U32 = 0x%x\tIVR_U32 = 0x%x\n",p_Reg->CHCtrl_U32,p_Reg->ICfg_U32,p_Reg->IVR_U32);
    printk("ThCfg_U32 = 0x%x\tIntStat_U32 = 0x%x\tIntEnSet_U32 = 0x%x\n",p_Reg->ThCfg_U32,p_Reg->IntStat_U32,p_Reg->IntEnSet_U32);  
    printk("IntEnClr_U32 = 0x%x\tEndofInt_U32 = 0x%x\tDMACHNID0_U32 = 0x%x\n",p_Reg->IntEnClr_U32,p_Reg->EndofInt_U32,p_Reg->DMACHNID0_U32);  
    printk("DMACHNID0_U32 = 0x%x\tDMACHNID1_U32 = 0x%x\tDMACHNID2_U32 = 0x%x\n",p_Reg->DMACHNID0_U32,p_Reg->DMACHNID1_U32,p_Reg->DMACHNID2_U32);
    printk("DMACHNIS0_U32 = 0x%x\tDMACHNIS1_U32 = 0x%x\tDMACHNIS2_U32 = 0x%x\n",p_Reg->DMACHNIS0_U32,p_Reg->DMACHNIS1_U32,p_Reg->DMACHNIS2_U32);
    printk("DMACHNQD0_U32 = 0x%x\tDMACHNQD1_U32 = 0x%x\tDMACHNQD2_U32 = 0x%x\n",p_Reg->DMACHNQD0_U32,p_Reg->DMACHNQD1_U32,p_Reg->DMACHNQD2_U32);        
    printk("DMACHNQS0_U32 = 0x%x\tDMACHNQS1_U32 = 0x%x\tDMACHNQS2_U32 = 0x%x\n",p_Reg->DMACHNQS0_U32,p_Reg->DMACHNQS1_U32,p_Reg->DMACHNQS2_U32);     
           
    
    printk("IntCount = 0x%x\n",count);
    printk("Current Time is:\n");
    printk("%d-%d-%d %d:%d:%d\n",((s_bufferRecv_aU16[28]&0xFF00)>>8),(s_bufferRecv_aU16[28]&0x00FF),\
                                 ((s_bufferRecv_aU16[29]&0xFF00)>>8),(s_bufferRecv_aU16[29]&0x00FF),\
                                 ((s_bufferRecv_aU16[30]&0xFF00)>>8),(s_bufferRecv_aU16[30]&0x00FF));
    printk("%d-%d-%d %d:%d:%d\n",time[1],time[2],time[3],time[4],time[5],time[6]);
    printk("%d\t%d\t%d\t%d\t%d\n",s_bufferRecv_aU16[0],s_bufferRecv_aU16[1],s_bufferRecv_aU16[2],s_bufferRecv_aU16[3],s_bufferRecv_aU16[4]);    printk("%d\t%d\t%d\t%d\t%d\n",s_bufferRecv_aU16[25],s_bufferRecv_aU16[26],s_bufferRecv_aU16[27],s_bufferRecv_aU16[28],s_bufferRecv_aU16[29]);
    printk("%d\t%d\t%d\t%d\t%d\n",s_bufferRecv_aU16[30],s_bufferRecv_aU16[31],s_bufferRecv_aU16[32],s_bufferRecv_aU16[33],s_bufferRecv_aU16[34]);
    printk("%d\t%d\t%d\t%d\t%d\n",s_bufferRecv_aU16[35],s_bufferRecv_aU16[36],s_bufferRecv_aU16[37],s_bufferRecv_aU16[38],s_bufferRecv_aU16[39]);

    printk("%d-%d-%d %d:%d:%d\n",((s_bufferSend_aU16[5]&0xFF00)>>8),(s_bufferSend_aU16[5]&0x00FF),\
                                 ((s_bufferSend_aU16[6]&0xFF00)>>8),(s_bufferSend_aU16[6]&0x00FF),\
                                 ((s_bufferSend_aU16[7]&0xFF00)>>8),(s_bufferSend_aU16[7]&0x00FF));
#ifdef UPP_LOOPBACK
    printk("%d\t\t%d\t%d\t%d\t%d\n",s_bufferRecv_aU16[5],s_bufferRecv_aU16[6],s_bufferRecv_aU16[7],s_bufferRecv_aU16[8],s_bufferRecv_aU16[9]);    bsp_upp_Send(s_send,32);
#endif
    return 0;
}

static const struct file_operations upp_drv_file_operation = {
    .owner = THIS_MODULE,
    .open  = upp_drv_open,
    .write = upp_drv_write,
    .read  = upp_drv_read,
};

/******************************************************************************
*函数名: bsp_upp_Send
*功能说明: upp发送函数.
*参数说明: sendData_pU16:发送数据的首地址
*          sendBytes_U32:发送数据长度
*返回值 : VOID
******************************************************************************/

static VOID bsp_upp_Send(const UINT16 sendData_aU16[], UINT32 sendBytes_U32)

{
    UINT32 i = 0U;
    UINT32 sendWords_U32 = sendBytes_U32 >> 1;

    if(sendWords_U32 <= UPP_BUFF_SIZE)
    {
        for(i = 0U; i< sendWords_U32; i++)
        {
            s_bufferSend_aU16[i] = sendData_aU16[i];
        }

        p_Reg->DMACHNID0_U32 = (UINT32)&s_bufferSend_aU16[0];
        p_Reg->DMACHNID1_U32 = 0x00010000 | sendBytes_U32;
        p_Reg->DMACHNID2_U32 = 0x00000000U;
    }
}

/******************************************************************************
*函数名: bsp_upp_InitRecv
*功能说明: 初始化化接收配置,设置接收长度和接收首地址.
*参数说明: VOID
*返回值 : VOID
******************************************************************************/

static VOID bsp_upp_InitRecv(VOID)

{
    p_Reg->DMACHNQD0_U32 = (UINT32)&s_bufferRecv_aU16[0];

#ifndef UPP_LOOPBACK
    p_Reg->DMACHNQD1_U32 = /*0x00010000 | */UPP_RECV_LEN;   /*数据接收长度为140个字节*/
#else    p_Reg->DMACHNQD1_U32 = 0x00010020;
#endif

    p_Reg->DMACHNQD2_U32 = 0x00000000U;
}

static int __init omapl138_upp_init(VOID)
{
    volatile unsigned long *p_Temp = NULL;
    UINT32 Delay_U32 = 2000U;

    printk("Load upp module function!\n");
    printk("Current Version is V%d.0\n",UPP_VERSION);
    printk("Author:Ben Date:2019-04-01\n");
    
    //register_chrdev(GPIO_LED_MAJOR,"omapl138gpio",&leds_drv_file_operation);
    major = register_chrdev(0,"omapl138upp",&upp_drv_file_operation);/*Alloc Major Num auto*/
   
    io_mem = request_region(SOC_SYSCFG_0_REGS, 0x100, "io");
    if (io_mem == NULL)    {
      printk("failed to get memory region\n");
    }

    /*Set upp gpio mux*/    p_Temp = ioremap(SOC_SYSCFG_0_REGS, 0x100);
    if(NULL == p_Temp)
    {   
        release_resource(io_mem);
        kfree(io_mem);
        printk("ioremap1 fail\n");
        return -1;    }
    
    *(p_Temp + 13) &= 0x0000FFFF;
    *(p_Temp + 13) |= 0x44440000;/*GPIO6[8]~GPIO6[11]*/

    *(p_Temp + 14) &= 0x000000FF;
    *(p_Temp + 14) |= 0x44444400;/*UPP_D10~UPP_D15*/
    *(p_Temp + 15) = 0x44444444;
    *(p_Temp + 16) = 0x44444444;
    *(p_Temp + 17) = 0x44444444;

    *(p_Temp + 18) &= 0xFF000000;
    *(p_Temp + 18) |= 0x00444444;
    iounmap(p_Temp);

    /* 使能upp时钟 */
    //davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, 1,
    //        19, 1);
    /* 映射io寄存器 */
    p_Reg =  ioremap(UPP_BASE_REGS, 0x100);
    if(NULL == p_Reg)
    {   
        printk("ioremap2 fail\n");
        return -1;    }   

    p_Reg->Ctrl_U32 &= ~UPP_UPPCR_EN;
    while((p_Reg->Ctrl_U32 & UPP_UPPCR_DB) != 0U)
    {
    }
    p_Reg->Ctrl_U32 |= UPP_UPPCR_SWRST;

    while(Delay_U32 > 0U)
    {
    Delay_U32 –;
    }

    p_Reg->Ctrl_U32 &= ~UPP_UPPCR_SWRST;
    p_Reg->Ctrl_U32 |= UPP_UPPCR_SOFT | UPP_UPPCR_RTEMU;

    p_Reg->CHCtrl_U32 = 0x02020007U;
#ifndef UPP_LOOPBACK
    p_Reg->DLB_U32 &= ~0x1000U;  
    p_Reg->ICfg_U32 = 0x00180F18U;
#else    p_Reg->DLB_U32 |= 0x1000U;  //开启A->B回环测试
    p_Reg->ICfg_U32 = 0x0F180F18U;
#endif
    p_Reg->ThCfg_U32 = 0x000000U;
    p_Reg->IntEnClr_U32 = 0x0001F1FU;
    p_Reg->IntEnSet_U32 = 0x0001000U;   
    p_Reg->Ctrl_U32 |= UPP_UPPCR_EN;

    bsp_upp_InitRecv();

    upp_class = class_create(THIS_MODULE,"upp class");
    if(!upp_class)
    {
         if(IS_ERR(upp_class))
         {
            return PTR_ERR(upp_class);
         }
    }    

    upp_dev = device_create(upp_class,NULL,MKDEV(major,0),NULL,"upp");
    if(!upp_dev)
    {
         if(IS_ERR(upp_dev))
         {
            return PTR_ERR(upp_dev);
         }
    }
    return 0;
}

 static VOID __exit omapl138_upp_exit(VOID)
{
    p_Reg->Ctrl_U32 |= UPP_UPPCR_SWRST;  //复位upp

    free_irq(UPP_INT_NUM,(void *)&devid_I8);
    release_resource(io_mem);
    kfree(io_mem);
    iounmap(p_Reg);    unregister_chrdev(major,"omapl138upp");
    device_unregister(upp_dev);
    class_destroy(upp_class);
    printk("Unload upp function module.\n ");
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("xxxxxxxxx");
MODULE_VERSION ("V1.1");
MODULE_DESCRIPTION ("description");

module_init(omapl138_upp_init);   //..模块初始化
module_exit(omapl138_upp_exit);  //..模块初退出

Yansheng bao:

补充一点:接收中断可以被触发,在回环模式下,发送2次触发一次中断

Shine:

回复 Yansheng bao:

请问用的是哪款器件?

Yansheng bao:

回复 Shine:

用的是OMAPL138BGWTA3R

Yansheng bao:

回复 Shine:

看出我程序的问题了吗,有解决方案吗?

赞(0)
未经允许不得转载:TI中文支持网 » linux操作系统下的upp驱动 如何使用
分享到: 更多 (0)