davinci 6446 UART1 rs485驱动

linux UART(RS232/485)驱动实验 文章目录一、linux下的UART驱动框架1. uart_driver 注册与注销2. uart_port 的添加与移除3. uart_ops 实现二、6u UART驱动分析1. UART 的 的 platform 驱动框架2. uart_driver 初始化3. uart_port 初始化与添加4. imx_pops 结构体变量三、原理图分析四、RS232驱动编写1. UART3 IO 节点创建2. 添加 uart3 节点五、移植minicom1. 移植ncurses2. 移植 minicom六、RS 阅读详情

原文地址:http://blog.sina.com.cn/s/blog_87f8cc4e01019zfd.html

自己写的DM6446中uart1驱动来实现485通信。在linux-2.6.18_pro500中uart驱动在8250.c中。这里贴出自己的实现的驱动。

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include<linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include<linux/mtd/partitions.h>
#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
#include <linux/mtd/physmap.h>
#endif
#include <linux/serial.h>
#include <linux/serial_8250.h>

#include <asm/setup.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/flash.h>

#include <asm/arch/common.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/clock.h>
#include <asm/arch/nand.h>
#include <asm/arch/mmc.h>
#include <asm/arch/edma.h>
#include <asm/arch/i2c-client.h>

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
#include<linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_reg.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/nmi.h>
#include <linux/mutex.h>

#include <asm/io.h>
#include <asm/irq.h>


#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/delay.h>


#include <linux/videodev.h>
#include <linux/device.h>

#include <linux/cdev.h>
#include <linux/types.h>
#include <asm/uaccess.h>

#define davinci_readb(a) (*(volatile unsignedchar  *)IO_ADDRESS(a))
#define davinci_readw(a) (*(volatile unsignedshort *)IO_ADDRESS(a))
#define davinci_readl(a) (*(volatile unsignedint   *)IO_ADDRESS(a))

#define davinci_writeb(v,a) (*(volatileunsigned char  *)IO_ADDRESS(a) = (v))
#define davinci_writew(v,a) (*(volatile unsignedshort *)IO_ADDRESS(a) = (v))
#define davinci_writel(v,a) (*(volatile unsignedint   *)IO_ADDRESS(a) = (v))

#undef DEV_485_BUG
#define DEV_485_BUG

#ifdef DEV_485_BUG
#define debug_print3(fmt, args...) printk( "dev_485: " fmt, ##args)
#else
#define  debug_print3(x...)
#endif


static int  Opened=0;

static int Major=0;

#define DRIVER_NAME "max485"

struct max485_chip_info {
    struct cdevcdev;
    struct mutexupdate_lock;
};

 struct class *max485_class;

//static unsigned int kuart1_base;

//static unsigned int kpsc_epcpr;
//static unsigned int kpsc_ptcmd;
//static unsigned int kpsc_ptstat;
//static unsigned int kpsc_pdstat;
//static unsigned int kpsc_pdctl;
//static unsigned int kpsc_mdctl_uart1;

//static unsigned int kgpio_base;
//static unsigned int kpinmux_base;

//static unsigned int kpsc_mdstat_uart1;
//static unsigned int kpsc_mdctl_gpio;
//static unsigned int kpsc_mdstat_gpio;

#define UART1_BASE_  (0x01c00000 +0x20400)//

#define PSC_EPCPR (0x01C40000 +0x1070)
#define PSC_PTCMD (0x01C40000 +0x1120)
#define PSC_PTSTAT (0x01C40000 +0x1128)
#define PSC_PDSTAT (0x01C40000 +0x1200)
#define PSC_PDCTL (0x01C40000 +0x1300)
#define PSC_MDCTL_UART1 (0x01C40000 +0x1200)

#define GPIO_BASE (0x01C67000)
#define PINMUX_BASE (0x01C40000)

#define PSC_MDSTAT_UART1 (0x01C41850)
#define PSC_MDCTL_GPIO (0x01C41A68)
#define PSC_MDSTAT_GPIO (0x01C41868)


#define kuart1_base UART1_BASE_
#define kpsc_epcpr PSC_EPCPR
#define kpsc_ptcmd PSC_PTCMD
#define kpsc_ptstat PSC_PTSTAT
#define kpsc_pdstat PSC_PDSTAT
#define kpsc_pdctl  PSC_PDCTL
#define kpsc_mdctl_uart1 PSC_MDCTL_UART1
#define kpsc_mdstat_uart1 PSC_MDSTAT_UART1
#define kpsc_mdctl_gpio PSC_MDCTL_GPIO
#define kpsc_mdstat_gpio PSC_MDSTAT_GPIO
#define kpinmux_base PINMUX_BASE

 

 

//static inline void
static void
serial_out(unsigned int value, unsigned int reg)
{
 davinci_writel(value, reg );
}

//static inline unsigned int
static unsigned int
serial_in(unsigned int reg)
{
 unsigned int value;
 value = davinci_readl(reg);
 return value;
}

unsigned int serial_in_pwr (unsigned int offset)
{
 // FIXME read procedure to set
 return davinci_readl(offset);
}

unsigned int serial_out_pwr (unsigned int value, unsigned intoffset)
{
 return davinci_writel(value, offset);
}

#if 0
void phy_to_kern (void)
{
 kuart1_base  =(unsigned int)(ioremap(UART1_BASE_  , 0x22)); //34bytes
 kpsc_epcpr  =(unsigned int)(ioremap(PSC_EPCPR  , 0x04));//new
 kpsc_ptcmd   =(unsigned int)(ioremap(PSC_PTCMD  , 0x04));
 kpsc_ptstat   =(unsigned int)(ioremap(PSC_PTSTAT  , 0x04));
 kpsc_pdstat  =(unsigned int)(ioremap(PSC_PDSTAT  , 0x04));//new
 kpsc_pdctl  =(unsigned int)(ioremap(PSC_PDCTL  , 0x04));//new
 kpsc_mdctl_uart1 = (unsignedint)(ioremap(PSC_MDCTL_UART1, 0x04));
 kgpio_base   =(unsigned int)(ioremap(GPIO_BASE  , 0x20)); //32bytes
 kpinmux_base  = (unsignedint)(ioremap(PINMUX_BASE  , 0x08)); //8bytes
 
 
 kpsc_mdstat_uart1  = (unsignedint)(ioremap(PSC_MDSTAT_UART1, 0x04)); //for
 kpsc_mdctl_gpio   = (unsignedint)(ioremap(PSC_MDCTL_GPIO  , 0x04)); //forgpio
 kpsc_mdstat_gpio = (unsignedint)(ioremap(PSC_MDSTAT_GPIO , 0x04)); //for gpio
 
 debug_print3("kuart1_base 0x%x\n",kuart1_base    );
 debug_print3("kpsc_ptcmd 0x%x\n",kpsc_ptcmd     );
 debug_print3("kpsc_ptsta 0x%x\n",kpsc_ptstat    );
 debug_print3("kpsc_mdctl_uart1 0x%x\n",kpsc_mdctl_uart1);
 debug_print3("kgpio_base 0x%x\n",kgpio_base );
 debug_print3("kpinmux_base 0x%x\n",kpinmux_base );
 debug_print3("kpsc_mdctl_gpio 0x%x\n",kpsc_mdctl_gpio );
 debug_print3("kpsc_epcpr 0x%x\n",kpsc_epcpr     );
 debug_print3("kpsc_pdstat 0x%x\n",kpsc_pdstat    );
 debug_print3("kpsc_pdctl 0x%x\n",kpsc_pdctl     );
}
#endif

void poweron_uart1(void)
{
 unsigned int reg_mdctl_uart1, reg_ptcmd,reg_ptstat;
 unsigned int reg_epcpr, reg_pdstat, reg_pdctl;
 unsigned int reg_mdstat_uart1;
 
 //reg_epcpr    =serial_in(reg_epcpr ); //new
 //reg_pdstat    =serial_in(reg_pdstat);  //new
 //reg_pdctl    =serial_in(reg_pdctl );  //new

 //22Aug updated after finding that uartPWREMU_MGMT is still 0x3 and following values
 //RS485: kpsc_epcpr 0xc4860070
 //RS485: kpsc_pdstat 0xc4866200
 //RS485: kpsc_pdctl 0xc4868300
 
 //already there
 reg_mdctl_uart1  =serial_in(kpsc_mdctl_uart1);
 debug_print3("Before powering on reg_mdctl_uart1= 0x%x\n", reg_mdctl_uart1);
 reg_mdctl_uart1 |=0x03;               //Module Powerenabled                                   
 serial_out(reg_mdctl_uart1,kpsc_mdctl_uart1);                    
 
 //22Aug
 reg_pdstat = serial_in(kpsc_pdstat);
 debug_print3("reg_pdstat in poweron_uart1()s =0x%x\n", reg_pdstat);
 if (!(reg_pdstat & 0x01))
 {
   debug_print3("pdstat- off. Powering on...\n");
   reg_pdctl =serial_in(kpsc_pdstat);
   reg_pdctl |=0x01;
   serial_out(reg_pdctl,kpsc_pdctl);

   reg_ptcmd = serial_in(kpsc_ptcmd);
   reg_ptcmd =0x01;                                                
   serial_out(reg_ptcmd,kpsc_ptcmd);                               

   
   do                                                               
   {                                                                
    reg_epcpr =serial_in(kpsc_epcpr);   
   }                                                                
    while (!((reg_epcpr & 0x01) == 0));
   
   debug_print3("reg_epcpr done...\n");
    
    
    reg_pdctl= serial_in(kpsc_pdctl);   
    reg_pdctl|= 0x100;
    serial_out(reg_pdctl, kpsc_pdctl);
    
    
   do                                                               
   {                                                                
    reg_ptstat =serial_in(kpsc_ptstat);                           
   }                                                                
   while (!((reg_ptstat & 0x01) == 0));
   debug_print3("reg_ptstatdone...\n");
  }
  else
  {
   reg_ptcmd =serial_in(kpsc_ptcmd);                                 
   reg_ptcmd =0x01;                                                    
   serial_out(reg_ptcmd,kpsc_ptcmd);                                  

    
   do                                                               
   {                                                                
    reg_ptstat =serial_in(kpsc_ptstat);                           
   }                                                                
   while (!((reg_ptstat & 0x01) == 0));
   debug_print3("reg_ptstatdone...\n");
  }
  
  
  do
  {
   reg_mdstat_uart1= serial_in(kpsc_mdstat_uart1);
  }
  while (! ((reg_mdstat_uart1& 0x1F) == 0x03));
  debug_print3("reg_mdstat_uart1...\n");
 
   //alreadythere
  // reg_ptcmd = serial_in(kpsc_ptcmd);
  // reg_ptcmd =0x01;                                                
  // serial_out(reg_ptcmd,kpsc_ptcmd);                               
  // do                                                               
  // {                                                                
  //  reg_ptstat =serial_in(kpsc_ptstat);                           
  // }                                                                
  //  while (!((reg_ptstat & 0x01) ==0));                            
  debug_print3("Powering ON theUART1 moduleDone........\n");      
 
}

#if 0
static int enable_tranciver(DIR dir)
{
 unsigned int reg_outdata01;
 unsigned int one = 0x01;
 
 if (dir == TX)
 {
   reg_outdata01 =serial_in(kgpio_base + OUT_DATA01);
   debug_print3("TX:: OUT_DATA01= %x\n",reg_outdata01);
   reg_outdata01|=   (one<< TXRX_CTL_PIN);
   serial_out(reg_outdata01,kgpio_base + OUT_DATA01);
   reg_outdata01 =serial_in(kgpio_base + OUT_DATA01);
   debug_print3("TX:: OUT_DATA01= %x\n",reg_outdata01);
 }
 else if (dir == RX)
 {
   reg_outdata01 =serial_in(kgpio_base + OUT_DATA01);
   debug_print3("RX:: OUT_DATA01= %x\n",reg_outdata01);
   reg_outdata01&= 0xFDFFFFFF;
   //reg_outdata01&=   ~(one<< TXRX_CTL_PIN);
   debug_print3("RX:: regoutdata= %x\n",reg_outdata01);
   serial_out(reg_outdata01,kgpio_base + OUT_DATA01);
   reg_outdata01 =serial_in(kgpio_base + OUT_DATA01);
   debug_print3("RX:: OUT_DATA01= %x\n",reg_outdata01);
 }
 else
 {
  debug_print3("ERROR: wrongdirection %d", dir);
  return -1;
 }
 return 0;
}
#endif


static int poweron_gpio(void)
{
 unsigned int reg_mdctl_gpio, reg_ptcmd,reg_ptstat;
 unsigned int reg_epcpr, reg_pdstat, reg_pdctl;
 unsigned int reg_mdstat_gpio;


 
 
 reg_mdctl_gpio  =serial_in_pwr(kpsc_mdctl_gpio);
 reg_mdctl_gpio =0x03;               //Module Powerenabled                                   
 serial_out_pwr(reg_mdctl_gpio,kpsc_mdctl_gpio);                    
 
 //22Aug
 reg_pdstat = serial_in(kpsc_pdstat);
 debug_print3("reg_pdstat in poweron_gpio()s =0x%x\n", reg_pdstat);
 if (!(reg_pdstat & 0x01))
 {
   debug_print3("pdstat- off. Powering on...\n");
   reg_pdctl =serial_in(kpsc_pdstat);
   reg_pdctl |=0x01;
   serial_out(reg_pdctl,kpsc_pdctl);

   reg_ptcmd = serial_in(kpsc_ptcmd);
   reg_ptcmd =0x01;                                                
   serial_out(reg_ptcmd,kpsc_ptcmd);                               

   
   do                                                               
   {                                                                
    reg_epcpr =serial_in(kpsc_epcpr);   
   }                                                                
    while (!((reg_epcpr & 0x01) == 0));
   
   debug_print3("reg_epcpr done...\n");
    
    
    reg_pdctl= serial_in(kpsc_pdctl);   
    reg_pdctl|= 0x100;
    serial_out(reg_pdctl, kpsc_pdctl);
    
    
   do                                                               
   {                                                                
    reg_ptstat =serial_in(kpsc_ptstat);                           
   }                                                                
   while (!((reg_ptstat & 0x01) == 0));
   debug_print3("reg_ptstatdone...\n");
  }
  else
  {
   reg_ptcmd =serial_in(kpsc_ptcmd);                                 
   reg_ptcmd =0x01;                                                    
   serial_out(reg_ptcmd,kpsc_ptcmd);                                  

    
   do                                                               
   {                                                                
    reg_ptstat =serial_in(kpsc_ptstat);                           
   }                                                                
   while (!((reg_ptstat & 0x01) == 0));
   debug_print3("reg_ptstatdone...\n");
  }
  
  
  do
  {
   reg_mdstat_gpio= serial_in(kpsc_mdstat_gpio);
  }
  while (! ((reg_mdstat_gpio& 0x1F) == 0x03));
  debug_print3("reg_mdstat_gpio...\n");

                                                                   
  debug_print3("Powering ON the GPIO moduleDone........\n");      
 
   
 
  return 0;
}

#definePINMUX0  ( 0x00)
#define PINMUX1  ( 0x04)


void config_gpio (void)
{
 unsigned int reg_pinmux0,reg_pinmux1;//reg_dir01, reg_outdata01;
 
 debug_print3("Config GPIOEntered....\n");      
 
 
  reg_pinmux0 = serial_in(kpinmux_base +PINMUX0);   //PINMUX 0
   debug_print3("PINMUX0 =%x\n",reg_pinmux0);
  reg_pinmux0 &=0xFFFCFFFF; //Disable ATA and HDIREN
  serial_out(reg_pinmux0,kpinmux_base +PINMUX0);
  reg_pinmux0 = serial_in(kpinmux_base +PINMUX0); 
   debug_print3("set PINMUX0 =%x\n",reg_pinmux0);
  reg_pinmux1 = serial_in(kpinmux_base +PINMUX1); 
   debug_print3("PINMUX1 =%x\n",reg_pinmux1);// PINMUX 1
  reg_pinmux1 |= 0x00000063; //Enable I2C, UART1 and UART0
  serial_out(reg_pinmux1, kpinmux_base +PINMUX1);           

   reg_pinmux1 =serial_in(kpinmux_base + PINMUX1); 
   debug_print3("set PINMUX1 =%x\n",reg_pinmux1);// PINMUX 1

#if 0
 
  reg_dir01 = serial_in(kgpio_base +DIR01);   
  debug_print2("DIR01 = %x\n",reg_dir01);
  reg_dir01 &=0xF9FFFFFF;     
  serial_out(reg_dir01, kgpio_base + DIR01);
  reg_dir01 = serial_in(kgpio_base +DIR01);   
  debug_print2("DIR01 = %x\n",reg_dir01);
 
 
 
  reg_outdata01 = serial_in(kgpio_base +OUT_DATA01);
  debug_print2("OUT_DATA01 =%x\n",reg_outdata01);
  reg_outdata01&=  0xFBFFFFFF;
  reg_outdata01|=  0x02000000;  
  serial_out(reg_outdata01 ,kgpio_base +OUT_DATA01);
  reg_outdata01 = serial_in(kgpio_base +OUT_DATA01);
  debug_print2("OUT_DATA01 =%x\n",reg_outdata01);

  debug_print1("Configuring GPIODone........\n");      
#endif


}

void reset_dlab (void)
{
 unsigned int reg_lcr;
 //reg_lcr = 0x00;
 //serial_out(reg_lcr, kuart1_base + LCR);
  
 
  reg_lcr = serial_in(kuart1_base +0xc);  // For R/W of IERregister
  debug_print3("LCR = %x\n",reg_lcr);
  reg_lcr &= 0x7F;
  serial_out(reg_lcr, kuart1_base +0xc);   
  reg_lcr = serial_in(kuart1_base +0xc);  // For R/W of IERregister
  debug_print3("LCR = %x\n",reg_lcr);
}


void disable_interrupt (void)
{
 unsigned int reg_IER;
 
 
 reset_dlab();
 
 
  reg_IER = 0x0;
  serial_out(reg_IER , kuart1_base + 0x4);
 
}

void set_dlab (void)
{
 unsigned int reg_lcr;
 
 //reg_lcr = 0x80;
 //serial_out(reg_lcr, kuart1_base + LCR);
 
  reg_lcr = serial_in(kuart1_base +0xc);  // For R/W of DLL...registers
  debug_print3("LCR = %x\n",reg_lcr);
  reg_lcr |=(1<<7);
  serial_out(reg_lcr, kuart1_base + 0xc);
  reg_lcr = serial_in(kuart1_base +0xc);  // For R/W of DLL...registers
  debug_print3("LCR = %x\n",reg_lcr);
   
 
}

void set_baud_rate (void)
{
 unsigned int reg_dll, reg_dlh;
 
 
 set_dlab();
 
 
 reg_dll =0x0F;   
 serial_out(reg_dll, kuart1_base + 0x20);
 
 reg_dlh = 0x00;
 serial_out(reg_dlh , kuart1_base +0x24); 
}

 

void config_fifo(unsigned int enable)
{
 //FCR (RO) and IIR (WO) share address : DLAB =x
 unsigned int reg_fcr;
 
 
  reg_fcr = serial_in(kuart1_base + 0x8);
  if(enable)
   reg_fcr |=0x00000001;  // Enable FIFO
  else
   reg_fcr &=0xFFFFFFFE;  // DisableFIFO
  serial_out(reg_fcr, kuart1_base + 0x8);
  
}


void set_protocol(void)
{
 unsigned int reg_lcr, reg_mcr;

 //If loopback is enabled TX,RX data can beverified
#ifdef LOOPBACK
 reg_mcr = 0x00000010;
  serial_out(reg_mcr, kuart1_base + 0x10);
#else
 reg_mcr = 0x00000000;
  serial_out(reg_mcr, kuart1_base + 0x10);
#endif 

 
  reg_lcr =0x00000003;  // No Parity, 1 stopbit, 8-bit data.
  serial_out(reg_lcr, kuart1_base + 0xc);
 
}



void reset_uart1(void)
{
  unsigned int reg_pwremu_mgmt;//, delay;
 
  reg_pwremu_mgmt = 0x0001;  //Reset
  serial_out(reg_pwremu_mgmt, kuart1_base +0x30);      //UTRST = 1 - tx is active
 
  reg_pwremu_mgmt |=(1<<14 |1<<13 |1<<0);  // Enable txand rx and FREE
  serial_out(reg_pwremu_mgmt, kuart1_base +0x30);      //UTRST = 1 - tx is active
 
}


void enable_interrupt(void)
{
 unsigned int reg_IER;
 
 
 reset_dlab();
 
 
  reg_IER = 0x3;
  serial_out(reg_IER , kuart1_base + 0x4); 
  debug_print3("Enabling InterruptDone...\n");

}

 

void check_reg(void)
{
 unsigned intreg_mdctl_uart1,reg_ptstat,reg_mdctl_gpio,reg_ptcmd,reg_pinmux0,reg_pinmux1,reg_dir01,reg_outdata01,reg_dll;
 
 unsigned int reg_dlh,reg_mcr,reg_lcr,reg_pwremu_mgmt,reg_mdstat_uart1,reg_mdstat_gpio,reg_lsr;//reg_fcr,
 
 unsigned int reg_epcpr, reg_pdstat, reg_pdctl;
 

 reg_mdctl_uart1  =serial_in(kpsc_mdctl_uart1);
 reg_epcpr    =serial_in(kpsc_epcpr ); //new
 reg_pdstat    =serial_in(kpsc_pdstat);  //new
 reg_pdctl    =serial_in(kpsc_pdctl );  //new
 reg_ptstat    =serial_in(kpsc_ptstat);
 reg_mdctl_gpio  = serial_in_pwr(kpsc_mdctl_gpio);
 reg_ptcmd     =serial_in_pwr(kpsc_ptcmd);
 reg_ptstat    =serial_in_pwr(kpsc_ptstat);
 reg_pinmux0   =serial_in(kpinmux_base +0);   // PINMUX0
 reg_pinmux1   =serial_in(kpinmux_base +0x04);   //PINMUX 1
 //reg_dir01    =serial_in(kgpio_base + 0x10);
 //reg_outdata01  = serial_in(kgpio_base +0x14);
 reg_mdstat_uart1 =serial_in(kpsc_mdstat_uart1);
 reg_mdstat_gpio =serial_in(kpsc_mdstat_gpio);
 
 //reg_fcr = serial_in(kuart1_base + FCR);
 reg_mcr = serial_in(kuart1_base + 0x10);
 reg_lcr = serial_in(kuart1_base + 0xc);
 reg_pwremu_mgmt  =serial_in(kuart1_base + 0x30); 
 
 //set_dlab();
 reg_dll = serial_in(kuart1_base +0x20); // Low byte
 reg_dlh = serial_in(kuart1_base +0x24); // High byte
 reg_lsr = serial_in((volatile unsignedint)kuart1_base + 0x14);
 
 debug_print3("reg_mdctl_uart1 =0x%x\n",reg_mdctl_uart1  );
 debug_print3("reg_epcpr    =0x%x\n",reg_epcpr     );
 debug_print3("reg_pdstat   =0x%x\n",reg_pdstat    );
 debug_print3("reg_pdctl    =0x%x\n",reg_pdctl     );
 debug_print3("reg_ptstat   =0x%x\n",reg_ptstat    );
 debug_print3("reg_mdctl_gpio  = 0x%x\n",reg_mdctl_gpio  );
 debug_print3("reg_ptcmd    =0x%x\n",reg_ptcmd     );
 debug_print3("reg_pinmux0    =0x%x\n",reg_pinmux0    );
 debug_print3("reg_pinmux1    =0x%x\n",reg_pinmux1    );
 debug_print3("reg_dir01    = 0x%x\n",reg_dir01    );
 debug_print3("reg_outdata01   = 0x%x\n",reg_outdata01  );
 debug_print3("reg_dll = 0x%x\n", reg_dll);
 debug_print3("reg_dlh = 0x%x\n", reg_dlh);
 //debug_print1("reg_fcr = 0x%x\n",reg_fcr);
 debug_print3("reg_mcr = 0x%x\n", reg_mcr);
 debug_print3("reg_lcr = 0x%x\n", reg_lcr);
 debug_print3(" reg_pwremu_mgmt =0x%x\n", reg_pwremu_mgmt);
 debug_print3(" reg_mdstat_uart1= 0x%x\n", reg_mdstat_uart1);
 debug_print3(" reg_mdstat_gpio =0x%x\n", reg_mdstat_gpio);
 debug_print3(" LSR = 0x%x\n",reg_lsr);
 
 

}

 
static ssize_t device_read(struct file *fp, char *buffer, size_tlen, loff_t *offset)
{
  unsigned int reg_lsr,reg_iir, reg_ier;
  unsigned char byte = 0x42;//=*(int*)buffer;
  unsigned int count = 0;
  int retval;
  //TODO: get no. of byte to be read from user dorelated stuffs.
 
 
 reset_dlab();

#ifdef BOARD_DVPB
 enable_tranciver(RX);
#endif
 
 
 //do
  //{
  // reg_iir =serial_in(kuart1_base + IIR);
  // //mdelay(1000);
  //}
 //while (((reg_iir & 0x0000000E)!= 0x04));
 //while (((reg_iir & 0x0000000E)!= 0x02));
 
 // Wait till the transmit FIFO isempty                                  
 do
  {
   // Read the Status Register tocheck if the Transmit FIFO isempty    
   reg_lsr = serial_in((volatileunsigned int)kuart1_base + 0x14);
   //debug_print3("Kernellsr...0x%x\n",reg_lsr);
    reg_lsr =reg_lsr & 0x01;
   count++;
  }
  while((reg_lsr != 0x01) || (count< 10000));

 
 reg_ier = serial_in(kuart1_base + 0x04);
 reg_iir = serial_in(kuart1_base + 0x08);
 debug_print3("IIR 0x%x, IER0x%x\n",reg_iir,reg_ier);
  
  byte = serial_in(kuart1_base + 0);
  debug_print3("KERNEL: byte read =%x\n\n\n",byte);
 
  
 if ( ( retval = copy_to_user ( (void __user*)buffer,&byte, sizeof(char) ) ) == -1)
  debug_print3("ERROR: incopy_to_user inside device_write\n" );
 

  return 1;
}



static ssize_t device_write(struct file *file, const char __user*buff,size_t count, loff_t *offp)
{
  unsigned char byte,reg_lsr ;//=*(int*)buffer;
 unsigned int count1 = 0;
  int retval;
 
 reset_dlab();
 
#ifdef BOARD_DVPB
 //enable_tranciver(TX);
#endif

 
 if(( retval = copy_from_user (&byte, (void __user *) buff, count ) ) == -1)
 debug_print3("ERROR: in copy_from_user insidedevice_write\n" );

 //unsigned long copy_from_user(void *to,constvoid __user *from,unsigned long count);
 debug_print3("anger To be sentbyte:%c\n",byte);
 
 // Wait till the transmit FIFO isempty                                  
 do
   {
    // Read the Status Registerto check if the Transmit FIFO isempty    
  reg_lsr = serial_in((volatile unsignedint)kuart1_base + 0x14);
  //debug_print3("Kernellsr...0x%x\n",reg_lsr);
     reg_lsr = reg_lsr & 0x20;
    count1++;
   }
   while(reg_lsr!=0x20);
 
 debug_print3("Count afterlsr!=0x20...0x%x\n",count1);
 serial_out(byte, kuart1_base + 0);
  return 1;
}


static int device_open(struct inode *inod, struct file *fp)
{
 
  printk("device_openentered...\n" );  
 
  //  If devie is opened returnbusy status
 // if (Opened)
 //   return-EBUSY;
  //else
  {
   Opened=1;


 
  // Remapping physical adress tokernel space
   //phy_to_kern();
 
   
  poweron_gpio();  
 
 
 poweron_uart1();
   
   
   config_gpio();

 
   
 disable_interrupt ();
 
   
 set_baud_rate();
  
   
   //in fops...
   
   
  config_fifo(0);//DISABLE
    
   
   set_protocol();
   
   
   reset_uart1();
   
   
   enable_interrupt();
   
   
   check_reg();
   
  }
 
 return 0;
}


static struct file_operations uart1_fops = {
   .owner  = THIS_MODULE,
   .read  =device_read,  
   .write  = device_write,
   .open  =device_open, 
 .release  = NULL,
};

static void max485_setup_cdev(struct max485_chip_info *dev,intindex)
{
      int err,max485_dev=MKDEV(Major,index);
      cdev_init(&dev->cdev,&uart1_fops);
      dev->cdev.owner=THIS_MODULE;
      err=cdev_add(&dev->cdev,max485_dev,1);
      if(err)
             printk(KERN_NOTICE "error %d adding max485 %d/n",err,index);
}

int __init init_module(void)
{
  //Registering device
 
 int err=0;
 int result;
  dev_t max485_dev;
  struct max485_chip_info*chip; 

    if(!(chip = kzalloc(sizeof(struct max485_chip_info), GFP_KERNEL))){
           err = -ENOMEM;
          return err;
     }
   
  if(Major)
               {
                       result=register_chrdev_region(max485_dev,1,DRIVER_NAME);
               }
               else{
                       result=alloc_chrdev_region(&max485_dev,0,1,DRIVER_NAME);
                       Major=MAJOR(max485_dev);
                    debug_print3( "Major %d\n", Major);
               }
               if (result < 0) {
                       debug_print3( "Unable to get Major region, error %d\n",result);
                err=result;
                 
               }
              max485_setup_cdev(chip,0);
   max485_class =class_create(THIS_MODULE, "max485");
        if(IS_ERR(max485_class))
       {
           printk("Err: failed in creating max485_class\n");
  kfree(chip);
           return -1;
       }
        debug_print3("start device_class for max485\n");
        class_device_create( max485_class, NULL, max485_dev, 0,"max485""%d",0);
         debug_print3 (KERN_INFO "Registered character driverpcf8574a  sensor\n");

   return err;
}

void __exit cleanup_module(void)
{
 //int ret;
 
  //iounmap((void *)kuart1_base  );
 //iounmap((void *) kpsc_ptcmd );
 //iounmap((void *) kpsc_ptstat );
 //iounmap((void *)kpsc_mdctl_uart1  );
 //iounmap((void *) kgpio_base );
 //iounmap((void *) kpinmux_base );
 //iounmap((void *) kpsc_mdctl_gpio);
  //  Unregister device
  
   device_destroy(max485_class, MKDEV(Major, 0));
   class_destroy(max485_class);
       unregister_chrdev_region(MKDEV(Major, 0), 1);

}

module_init(init_module);
module_exit(cleanup_module);

MODULE_DESCRIPTION("PCF8574A erternal IO");
MODULE_AUTHOR("Wang, <@.com>");
MODULE_LICENSE("GPL");

 

应用程序:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include "ioport-pcf8574a.h"
#include <sys/ioctl.h>

static int set_opt(int fd,int nSpeed, int nBits, char nEvent,int nStop)
{
 struct termios newtio,oldtio;
 if ( tcgetattr( fd,&oldtio) != 0)//取属性(termios结构);
 {
  perror("SetupSerial1\n\r");
  return -1;
 }
 
 bzero( &newtio, sizeof( newtio ));
 newtio.c_cflag |= CLOCAL | CREAD;
 newtio.c_cflag &= ~CSIZE;

 switch( nBits )
 {
  case 7:
  newtio.c_cflag |= CS7;
  break;
  case 8:
  newtio.c_cflag |= CS8;
  break;
 }

 switch( nEvent )
 {
  case 'O':
  newtio.c_cflag |= PARENB;
  newtio.c_cflag |= PARODD;
  newtio.c_iflag |= (INPCK |ISTRIP);
  break;
  case 'E':
  newtio.c_iflag |= (INPCK |ISTRIP);
  newtio.c_cflag |= PARENB;
  newtio.c_cflag&= ~PARODD;
  break;
  case 'N':
  newtio.c_cflag&= ~PARENB;
  break;
 }

 switch( nSpeed )
 {
  case 1200:
   cfsetispeed(&newtio,B1200);
   cfsetospeed(&newtio,B1200); 
   break;
  case 2400:
   cfsetispeed(&newtio,B2400);//设置输入速度
   cfsetospeed(&newtio,B2400);//设置输出速度
   break;
  case 4800:
   cfsetispeed(&newtio,B4800);
   cfsetospeed(&newtio,B4800);
   break;
  case 9600:
   cfsetispeed(&newtio,B9600);
   cfsetospeed(&newtio,B9600);
   break;
  case 19200:
   cfsetispeed(&newtio,B19200);
   cfsetospeed(&newtio,B19200);
   break;
  case 38400:
   cfsetispeed(&newtio,B38400);
   cfsetospeed(&newtio,B38400);
   break;
  case 57600:
   cfsetispeed(&newtio,B57600);
   cfsetospeed(&newtio,B57600);
   break;
  case 115200:
   cfsetispeed(&newtio,B115200);
   cfsetospeed(&newtio,B115200);
   break;
  default:
   cfsetispeed(&newtio,B9600);
   cfsetospeed(&newtio,B9600);
   break;
 }

 if( nStop== 1 )
  newtio.c_cflag&= ~CSTOPB;
 else if ( nStop == 2 )
  newtio.c_cflag |= CSTOPB;
 newtio.c_cc[VTIME] = 0;
 newtio.c_cc[VMIN] = 0;
 tcflush(fd,TCIFLUSH);//刷清未决输入和/或输出;
 if((tcsetattr(fd,TCSANOW,&newtio))!=0)//设置属性(termios结构);
 {
  printf("com set error=%d\n\r",(tcsetattr(fd,TCSANOW,&newtio)));
  return -1;
 }
 printf("set done!\n");

 return 0;
}


static int open_port(int fd,int comport)
{
 char*dev[]={"/dev/tts/0","/dev/tts/1","/dev/ttyS2"};
 long vdisable;
 if (comport==1)
 {
  fd = open( "/dev/ttyS0",O_RDWR|O_NOCTTY|O_NDELAY);
  if (-1 == fd){
  perror("Can't Open SerialPort");
  return(-1);
  }
  else
  printf("open ttyS0.....\n");
 }
 else if(comport==2)
 {
  fd = open( "/dev/ttyS1",O_RDWR|O_NOCTTY|O_NDELAY);
  //fd = open( "/dev/ttyS1",O_RDWR);
  if (-1 == fd){
  perror("Can't Open SerialPort");
  return(-1);
  }
  else
  printf("open ttyS1.....\n");
 }
 else if (comport==3)
 {
  fd = open( "/dev/ttyS2",O_RDWR|O_NOCTTY|O_NDELAY);
  if (-1 == fd){
  perror("Can't Open SerialPort");
  return(-1);
  }
  else
  printf("open ttyS2.....\n");
 }
 //
 if(fcntl(fd, F_SETFL, 0)<0)
  printf("fcntlfailed!\n");
 else
  printf("fcntl=%d\n",fcntl(fd,F_SETFL,0));
 if(isatty(STDIN_FILENO)==0)
  printf("standard input is not aterminal device\n");
 else
  printf("isattysuccess!\n");
 printf("fd-open=%d\n",fd);
 return fd;
}


int main(int argc, char *argv[])
{
 int fd;
 int fdio;
 int nread,i;
 unsigned char iord;
 char buff[]="Hello anger\n";
 char rbuff[128];
 int rs485_dev;
 printf("test uart\n\r");
 
 if((fd=open_port(fd,2))<0)
 {
  printf("open_porterror\n\r");
  return -1;
 } 
 
 printf("start set\n\r");
 if((i=set_opt(fd,57600,8,'N',1))<0)
 {
  printf("set_opterror\n\r");
  return;
 }
 printf("fd=%d\n\r",fd);


 fdio = open("/dev/exioport0",O_RDWR);
 if (-1 == fdio){
  perror("Can't Open ioPort");
  return(-1);
  }
 

 ioctl(fdio,EX_GPIO_CONTROL_MAX485_HIGH);
 ioctl(fdio,EX_GPIO_READ_PORT,&iord);
 printf("ioctl read data=0x%x\n\r",iord);

 ioctl(fdio,EX_GPIO_CONTROL_MAX485_LOW);
 ioctl(fdio,EX_GPIO_READ_PORT,&iord);
 printf("ioctl read data=0x%x\n\r",iord);
 
 
 while(1)
 {
  nread =0;
  nread=read(fd,rbuff,128);
  if(nread)
  {
   printf("read=%d,%s\n\r",nread,rbuff);
   
   ioctl(fdio,EX_GPIO_CONTROL_MAX485_HIGH);
   write(fd,buff,12);
   usleep(100000);
   usleep(100000);
   usleep(100000);
   ioctl(fdio,EX_GPIO_CONTROL_MAX485_LOW);
  }
 
 }

 //close(fd);
 //close(fdio);
 return;
}


FPGA学习笔记—UART,RS485串口通信(verilog) 串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口(SerialInterface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。...... 阅读详情

相关推荐

Automotive > CAN通信知识 > Controller 和 Transceiver介绍

CAN通信的基本组成主要包含Controller和Transceiver两部分,大体介绍这两部分

DL_62532的专栏 3248

AUTOSAR CAN Transceiver

本文主要以普及CAN通信基本原理为目的,如有从事相关领域或者有意从事车载嵌入式开发的读友们欢迎留言探讨。 本文含有关键字如下。 CANTransceiver Hardware,CANTrcv 图1 CAN通信组件图 Can Transceiver Hardware主要功能 CAN收发器(CAN Transceiver Hardware)是一种硬件设备,可将CAN总线上使用的信号电平调整为微控制器识别的逻辑(数字)信号电平。此外,收发器还能够检测电气故...

weixin_45576679的博客 4934

RK3568/RK3588之修改8250驱动实现RS485收发的自动切换

在串口发送前,若为485,则将控制引脚拉为发送状态,在发送后,循环查看是否发送完成,若发送完成则将引脚置回读状态,如此一来,就能实现在内核测控制方向切换,而不会因为延时造成数据丢失,经过测试此办法可行。全部修改完成后,重新编译生成内核文件和设备树文件,烧写到板子上即可。

哒宰的博客 3112

linux串口驱动支持485,修改2410的linux串口驱动,使其支持RS485

2410自带有三个串口,但mizi linux中自带的驱动均为RS232的,因为485是半双工的,比232多了一个方向控制信号,所以linux的自带驱动并不适合485,需要进行一定的修改,步骤如下。1. 首先硬件方面肯定要改动,假设我们要改的串口为串口2,电路原理图如下:有图可知,485与232相比多了一个方向控制信号nRTS0,当其为低电平时,MAX485处于接收状态,反正为发送状态。因此我们在...

weixin_35996612的博客 1386

RS485驱动代码

#include "sys.h"      #include "rs485.h"  #include "delay.h" //////////////////////////////////////////////////////////////////////////////////  //RS485驱动代码     /////////////////////////////

zongguo的专栏 5095

RS485串口驱动源代码

1、前言 串口驱动是最简单的一种驱动了,在Linux下一切设备都认为是文件,打开设备就像打开文件一样简单,直接上代码 2、RS485.c //-------------------------------------------------------------------------------------------------- // Include head files //---------------------------------------------------...

Linux/Windows、C/C++、嵌入式开发、物联网、消费电子领域的技术博客 5944

RS232与RS485谁才是UART中的高速公路

origin: http://www.eepw.com.cn/article/201606/292407.htm 串口通讯是电子工程师面对的最基本的一个通讯方式,RS-232是其中最简单的一种。然而,很多初学者往往搞不清楚UART和RS-232、RS-422、RS-485的联系和区别,本文将谈谈我对这几个概念的理解,帮助大家理清它们之间的关系。 本文引用地址:http://www.eepw

yazhouren的专栏 907

8250驱动使用workqueue加入RS485控制逻辑

项目中使用了RS485,主控是PX30 查看资料,有些前辈的帖子写了用了tasklet 中断服务来做,占资源比较多,而且无法在内部执行一段udelay (看有人这么操作,但是我的系统源码编译出来后会产生互斥锁递归导致系统崩溃)。 于是使用了workqueue来进行延迟检测操作,主要是为了检查是否数据发送完毕,数据发送完后就拉低IO口。 在结构体中新增定义: diff --git a/kernel/include/linux/serial_8250.h b/kernel/include/linu.

tianlai1009的博客 2809

21_RS485简单讲解

RS485简单讲解 参考代码 Linux 4.9.88 arch\arm\kernel\early_printk.c drivers\tty\serial\earlycon.c Linux 5.4 arch\arm\kernel\early_printk.c drivers\tty\serial\earlycon.c 1. 回顾printk的使用 2. 内核信息的早期打印 在上节视频里我们实现了console驱动,它属于uart_driver的一部分。 注册了uart_drive

韦东山嵌入式专栏 1371

【经验总结】ECU休眠后通过一帧NM报文唤醒ECU后在要求时间内通过第二帧NM报文需要唤醒网络

ECU休眠后通过一帧NM报文唤醒ECU后在要求时间内通过第二帧NM报文需要唤醒网络

qq_36056498的博客 1779

RS485云台驱动上位机和C++源代码

RS485云台驱动上位机和C++源代码,包括了RS485云台驱动, 上位机,C++驱动代码,使用Pelco-D协议的PTZ云台控制器。

UART和RS232、RS485的基础知识

UART和RS232、RS485的关系:   通讯问题,和交通是一样的。串口通信,我们这里可以用公交来类比。         公交运行可以简单分成两个部分:        1、车站        2、公路        其中车站决定了车上装什么(人),怎么发送(班次)等。        当汽车跑在路上,就要遵守公路交通的规则,过桥有过桥的规则,高速有高速的规则,和车站没有关系

chunlovenan的专栏 2万+

CAN总线协议,汽车总线协议

CAN总线协议:CANopen协议,我国CAN总线汽车协议,CANbus协议等。学习总线协议,更有利于程序的编写,以及与大众化产品接轨!

CanTrcv (CAN Tranceiver Driver)

AUTOSAR的CAN Transceiver Driver(CanTrcv)模块为汽车电子系统提供了一套高效、可靠的CAN收发器控制和管理解决方案。通过标准化的接口和配置选项,CanTrcv模块实现了收发器控制、模式管理、唤醒管理、错误检测和报告及诊断支持等功能,确保数据通信的稳定性和可靠性。在CAN总线通信、功耗管理、总线唤醒、错误检测和诊断及安全通信等应用场景中,CanTrcv模块发挥着至关重要的作用。理解并有效利用AUTOSAR CanTrcv功能,对于开发高效、安全的汽车电子系统具有重大意义。

erroror的专栏 1766

使用c语言开发的rs485驱动源码

开发的rs485源码,使用c语言开发 The source files: ----------------- Q_TEST.C Quick test of the driver (shows how to use it!) RS485NT.C Windows NT 4.0 RS485 driver source code RS485NT.H Device extension structure for source code COM8250.H Standard 8250 UART defines RS485IOC.H IOCTL codes (used in both Q_TEST and RS485NT) RS485NT.LNR Linker "Release" command file RS485NT.LND Linker "Debug" command file MAKEFILE NMAKE compatibile make file SETENV.BAT Sets the necessary PATHS for compiling

当NetApp 7-mode遇到单控制器故障:HA模式手动修复全记录

本文详细记录了NetApp 7-mode存储系统在单控制器故障时的应急修复过程,包括HA配置重建、磁盘初始化和业务恢复等关键步骤。通过实战案例解析如何解决`VIA Interconnect is down`等典型问题,为企业级存储系统的高可用保障提供实用指南。

yolo5detector的博客 246

RS485/RS232串口通信实现源码

之前贴出了代码,但是源码已经找不到了;鉴于很多同学私信想要参考,找时间重新写了一个工程 一、参考代码 1.不方便下载的同学可以参考贴出来的源代码链接:RS485 二、基本知识 1.RS485通信讲解: 读30001、30002两个寄存器,假设从机地址为1 上位机(主机)发送下行报文:01 03 00 03 00 02 34 0B 从机地址 功能码 寄存器起始地址 读取寄存器个数 CRC校验 01 03 00 03 00 02 85 ca 01 03 00 04 00 02 85 ca 上

weixin_42176639的博客 1万+

BambuStudio学习笔记:OpenCSG - 实时构造实体几何(CSG)渲染的 OpenGL 方案

**OpenCSG** 是一个基于 **OpenGL** 的 **构造实体几何(CSG)** 实时渲染库,通过 **深度剥离算法** 实现布尔运算(并集、交集、差集)的可视化。其核心目标是简化复杂几何体的交互式建模,适用于 CAD 原型设计、3D 打印预览、教育工具等场景。

zzzkk2009的专栏 928

串口+RS485驱动

其实RS485不算什么协议,只是物理层做了差分传输,AB两线的电压差来表示0,1,0,1,可靠性和距离更加好,因此,一个串口外设只能作为半双工使用,而RS232是可以全双工的。 max485模块可以直接与stm的串口外设相连,但需要一个发送和接收的一个引脚作为控制。(抛开三极管驱动等电路) stm32作为master段,一般默认状态是接受的,如果要发送,可以改变控制引脚,发送完立即改为接收即可。...

liming0931的专栏 2545

7.7 数据分析助手:用AI洞察业务数据价值

摘要:AI数据分析助手构建指南 本文介绍了如何构建AI数据分析助手,帮助企业从业务数据中提取价值。系统包含四大核心模块:自然语言理解模块解析用户查询意图,查询规划模块转换为SQL语句,数据可视化模块生成图表,以及洞察生成模块提供深度分析。文章通过销售数据分析助手案例,展示了从数据库准备到自然语言处理的完整实现流程,包括示例代码和系统架构图。该解决方案可降低数据分析门槛,让业务人员直接参与数据探索,提升决策效率。

yonggeit的博客 4092

西门子G120变频器在立体仓库堆垛机应用参数设置

本文详细介绍了G120 CU240E及CU250S变频器的参数设置流程。主要内容包括:1)快速调试步骤,从新建项目、扫描节点到设置电机类型、负载类型等参数;2)抱闸参数设置方法;3)参数下载异常时的处理方案。重点说明了通过STARTER软件进行向导式调试的完整过程,包括电机铭牌参数输入、识别方式选择等关键环节,并提示了通讯连接注意事项。当下载失败时,提供了通过导入导出项目文件解决问题的具体方法。

xdpcxq的专栏 863
上一篇: 混淆的概念:SIF、CIF、4CIF、D1
下一篇: davinci 644X中UART1使用8250.c驱动注意
July_Yang
博客等级 码龄15年 46粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值