16C2550串口芯片在at91sam9263板上的linux驱动移植 .

本文详细介绍了如何使用经典8250驱动来驱动16C2550串口芯片,通过添加初始化代码和对外设读写时序的正确配置,实现双串口独立运行。文章提供了关键代码片段和配置步骤,帮助开发者在实际应用中顺利部署。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

16C2550串口芯片可以扩展两个串口。它的操作方法和寄存器用法与8250完全相同,因此我们可以用linux内经典的8250驱动来驱动st16c2550。
8250驱动完全不变,需要添加16C2550的初始化代码。初始化代码中要对16C2550进行片选和IRQ的管脚设置,并且要对16c2550外设的读写时序配置(setup,pulse,cycle),同时将驱动和设备挂钩。
对外设空间读写时序的配置十分重要。如果不配置或配置错误,则cpu无法识别串口芯片,或识别为16450。所以这一步十分关键。很多人都在这一步犯过错误。比如,用了cs3空间,但是配置时却配置的是cs4的寄存器。读写时序的配置参见at91sam9263 SMC章节,与之对应的是16C2550的读写时序图。
16C2550是将两个异步串口集成到一个芯片中,彼此独立。本文A口片选CS2,中断管脚AT91_PIN_PA10,B口片选CS3,中断管脚AT91_PIN_PA8。主时钟频率为198MHz(10.101ns一个时钟周期)。
Board_at91sam9263ek.c中添加的代码如下:
  1. #define ST16C2550_BASE          0x30000000  //  NCS2    //A口   
  2. #define NCSx_PIN                AT91_PIN_PD11   //NCS2   
  3. #define IRQ_PIN                 AT91_PIN_PA10   // IRQ3   
  4. #define ST16C2550_BASE_B            0x40000000  //  NCS3    //B口   
  5. #define NCSx_PIN_B              AT91_PIN_PD15   //NCS3   
  6. #define IRQ_PIN_B                   AT91_PIN_PA8    // IRQ2   
  7.   
  8.   
  9. static struct plat_serial8250_port st16c2550_data[] = {  
  10.         {  
  11.             .mapbase    =   ST16C2550_BASE,  
  12.             .irq            =   IRQ_PIN,  
  13.             .uartclk        =   18432000,  
  14.             .regshift       =   0,  
  15.             .iotype     =   UPIO_MEM,  
  16.             .flags      =   UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST,  
  17.         },  
  18.         {  
  19.             .mapbase    =   ST16C2550_BASE_B,  
  20.             .irq            =   IRQ_PIN_B,  
  21.             .uartclk        =   18432000,  
  22.             .regshift       =   0,  
  23.             .iotype     =   UPIO_MEM,  
  24.             .flags      =   UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST,  
  25.         },  
  26.         {},  
  27. };  
  28.   
  29.   
  30. static struct platform_device st16c2550_device = {  
  31.     .name   = "serial8250",  
  32.     .id         = PLAT8250_DEV_PLATFORM,  
  33.     .dev        = {  
  34.         .dma_mask = &st16c2550_dmamask,  
  35.         .coherent_dma_mask  =   DMA_BIT_MASK(32),  
  36.         .platform_data = &st16c2550_data,  
  37.     },  
  38. };  
  39.   
  40.   
  41. void __init at91_add_st16c2550(void)  
  42. {  
  43.     static void __iomem *smc_base;  
  44.     /*A NCS2*/  
  45.       
  46.     // setup NCSx pin   
  47.     at91_set_A_periph(NCSx_PIN, 0);  
  48.     // setup irq pin   
  49.     at91_set_gpio_input(IRQ_PIN, 0);  
  50.       
  51.     at91_sys_write(AT91_SMC_MODE(2),(AT91_SMC_READMODE | AT91_SMC_WRITEMODE  
  52.             | AT91_SMC_EXNWMODE_DISABLE  
  53.             | AT91_SMC_BAT_SELECT  
  54.             | AT91_SMC_DBW_8));  
  55.     at91_sys_write(AT91_SMC_CYCLE(2),0x000e000f);  
  56.     at91_sys_write(AT91_SMC_SETUP(2),0x03040304);  
  57.     at91_sys_write(AT91_SMC_PULSE(2),0x07060807);  
  58.   
  59.   
  60.     /*B NCS3*/  
  61.       
  62.         // setup NCSx pin   
  63.     at91_set_A_periph(NCSx_PIN_B, 0);  
  64.     // setup irq pin   
  65.     at91_set_gpio_input(IRQ_PIN_B, 0);  
  66.       
  67.     at91_sys_write(AT91_SMC_MODE(3),(AT91_SMC_READMODE | AT91_SMC_WRITEMODE  
  68.             | AT91_SMC_EXNWMODE_DISABLE  
  69.             | AT91_SMC_BAT_SELECT  
  70.             | AT91_SMC_DBW_8));  
  71.     at91_sys_write(AT91_SMC_CYCLE(3),0x000e000f);  
  72.     at91_sys_write(AT91_SMC_SETUP(3),0x03040304);  
  73.     at91_sys_write(AT91_SMC_PULSE(3),0x07060807);  
  74.   
  75.   
  76.   
  77.   
  78.     platform_device_register(&st16c2550_device);  
  79. }  
#define ST16C2550_BASE			0x30000000	//	NCS2	//A口
#define NCSx_PIN				AT91_PIN_PD11	//NCS2
#define IRQ_PIN					AT91_PIN_PA10	// IRQ3
#define ST16C2550_BASE_B			0x40000000	//	NCS3	//B口
#define NCSx_PIN_B				AT91_PIN_PD15	//NCS3
#define IRQ_PIN_B					AT91_PIN_PA8	// IRQ2


static struct plat_serial8250_port st16c2550_data[] = {
		{
			.mapbase	=	ST16C2550_BASE,
			.irq			=	IRQ_PIN,
			.uartclk		=	18432000,
			.regshift		=	0,
			.iotype		= 	UPIO_MEM,
			.flags		=	UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST,
		},
		{
			.mapbase	=	ST16C2550_BASE_B,
			.irq			=	IRQ_PIN_B,
			.uartclk		=	18432000,
			.regshift		=	0,
			.iotype		= 	UPIO_MEM,
			.flags		=	UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST,
		},
		{},
};


static struct platform_device st16c2550_device = {
	.name	= "serial8250",
	.id 		= PLAT8250_DEV_PLATFORM,
	.dev		= {
		.dma_mask = &st16c2550_dmamask,
		.coherent_dma_mask	=	DMA_BIT_MASK(32),
		.platform_data = &st16c2550_data,
	},
};


void __init at91_add_st16c2550(void)
{
	static void __iomem *smc_base;
	/*A NCS2*/
	
	// setup NCSx pin
	at91_set_A_periph(NCSx_PIN, 0);
	// setup irq pin
	at91_set_gpio_input(IRQ_PIN, 0);
	
	at91_sys_write(AT91_SMC_MODE(2),(AT91_SMC_READMODE | AT91_SMC_WRITEMODE
			| AT91_SMC_EXNWMODE_DISABLE
			| AT91_SMC_BAT_SELECT
			| AT91_SMC_DBW_8));
	at91_sys_write(AT91_SMC_CYCLE(2),0x000e000f);
	at91_sys_write(AT91_SMC_SETUP(2),0x03040304);
	at91_sys_write(AT91_SMC_PULSE(2),0x07060807);


	/*B NCS3*/
	
		// setup NCSx pin
	at91_set_A_periph(NCSx_PIN_B, 0);
	// setup irq pin
	at91_set_gpio_input(IRQ_PIN_B, 0);
	
	at91_sys_write(AT91_SMC_MODE(3),(AT91_SMC_READMODE | AT91_SMC_WRITEMODE
			| AT91_SMC_EXNWMODE_DISABLE
			| AT91_SMC_BAT_SELECT
			| AT91_SMC_DBW_8));
	at91_sys_write(AT91_SMC_CYCLE(3),0x000e000f);
	at91_sys_write(AT91_SMC_SETUP(3),0x03040304);
	at91_sys_write(AT91_SMC_PULSE(3),0x07060807);




	platform_device_register(&st16c2550_device);
}




在ek_board_init()初始化代码中,添加 at91_add_st16c2550()即可。


在移植驱动时,特别注意CS片选空间是否被其他外设用过。若不注意,则配置时序时后一配置覆盖了前一配置,导致读写时序不正确。

 

转载地址:http://blog.youkuaiyun.com/e0sys1/article/details/7892554


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值