- 论坛徽章:
- 0
|
刚刚接触Linux驱动,最近在做一个串口扩展芯片的驱动,现在已经可以在内核挂载驱动模块了,测试代码也可以正常进入ioctl\write函数操作。但是无法对扩展芯片的寄存器进行操作,cpu是ARM的2440,串口扩展芯片连接8位数据总线,地址空间为BANK5。大家帮忙分析下问题,现在自己没什么思路。
//TL16C554 address map
//扩展芯片寄存器物理地址到虚拟地址映射,这个函数在模块加载_init中调用
int tl1A_AddressMap(void)
{
tl1A.vBase = (unsigned char *)ioremap_nocache(tl1A.nAddress, ;
if(tl1A.vBase == NULL)
return -1;
tl1A.RBR = (int)(tl1A.vBase);
tl1A.THR = (int)(tl1A.vBase);
tl1A.LSR = (int)(tl1A.vBase + 5);
tl1A.MSR = (int)(tl1A.vBase + 6);
tl1A.LCR = (int)(tl1A.vBase + 3);
tl1A.FCR = (int)(tl1A.vBase + 2);
tl1A.MCR = (int)(tl1A.vBase + 4);
tl1A.DLL = (int)(tl1A.vBase);
tl1A.DLM = (int)(tl1A.vBase + 1);
tl1A.IER = (int)(tl1A.vBase + 1);
tl1A.SPR = (int)(tl1A.vBase + 7);
tl1A.IIR = (int)(tl1A.vBase + 2);
return 0;
}
//外设芯片的初始化
//TL1A初始化
void Init_TL1A(void)
{
volatile unsigned char byRx = 0;
int i = 0;
//初始化接收缓冲区指针
tl1A.sRecvHead = 0;
tl1A.sRecvTail = 0;
//FIFO控制寄存器
//设置FCR.FIFO使能,RXD复位,TXD复位,mode=1,触发为14;轮询方式触发设置无效
writeb(0xcf, tl1A.FCR);
//*(volatile unsigned char *)(tl1A.FCR) = 0xcf;
for(i=0; i<100; i++);
//set FCR.RXD复位,TXD复位
writeb(0xc9, tl1A.FCR);
printk("FCR = %x\n", readb(tl1A.FCR));
printk("FCR L = %x\n", readl(tl1A.FCR));
printk("FCR * = %x\n",*(volatile unsigned char *)(tl1A.FCR));
// *(volatile unsigned char *)(tl1A.FCR) = 0xc9;
//设置MCR3=0,外部中断使能
writeb(0x08, tl1A.MCR);
//*(volatile unsigned char *)(tl1A.MCR) = 0x08;
//LCR7置位,设置DLL/DLM,选择波特率
writeb(0x80, tl1A.LCR);
//*(volatile unsigned char *)(tl1A.LCR) = 0x80;
// DLM DLL BUADRATE
// 00 0x0C 9600BPS
// 00 0x06 19200BPS
writeb(BAUDBASE, tl1A.DLL);
//*(volatile unsigned char *)(tl1A.DLL) = BAUDBASE;
writeb(0x00, tl1A.DLM);
//LCR7清零,8位数据,无奇偶校验
writeb(0x03, tl1A.LCR);
//设置IER,发送保持、接收中断
writel(0x01, tl1A.IER);
//空读一次
byRx = readl(tl1A.RBR);
//读空
while(1)
{
byRx = readl(tl1A.LSR);
// byRx = *(volatile unsigned char *)(tl1A.LSR);
if(byRx & 0x01) //检查接收状态
{
byRx = readl(tl1A.RBR);
// byRx = *(volatile unsigned char *)(tl1A.RBR);
}
else
break;
//防止死循环
i++;
if(i > 4096) //每个通道最多只能缓存16个字节
break;
}
}
//应用程序调用ioctl进行内存初始化,打印寄存器信息
static int TL1A_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case TL_INIT:
printk("IER = 0x%x \n",readb(tl1A.IER));
printk("LCR = 0x%x \n",readb(tl1A.LCR));
printk("DLL = 0x%x \n",readb(tl1A.DLL));
printk("DLM = 0x%x \n",readb(tl1A.DLM));
Init_TL1A();
printk("IER = 0x%x \n",readb(tl1A.IER));
printk("LCR = 0x%x \n",readb(tl1A.LCR));
printk("DLL = 0x%x \n",readb(tl1A.DLL));
printk("DLM = 0x%x \n",readb(tl1A.DLM));
break;
default:
return -EINVAL;
}
现在的问题就是初始化前后的寄存器和设定值不同,有个疑问:
1.自己做的板子,在内核中没有进行虚拟地址和物理地址的映射设定,程序采用动态映射,是否有影响?
2.刚接触Linux驱动,我现在要操作的是外部设备寄存器,采用动态地址映射是否可以?驱动读写ARM控制寄存器是正常的
初始化代码、读写代码在无OS情况下都验证过了,读写都没有问题。
自己已经调试两天了,有点焦头烂额,只好来论坛求助了~~~,大家帮帮忙 |
|