最近,项目要使用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:
看出我程序的问题了吗,有解决方案吗?