1.1 概述
TI針對DM6467提供的UBOOT和內核默認都是串口0作為調試串口輸出的,但現在我需要使用DM6467的UART0的modem功能,所以修改代碼,改變調試串口為串口2。
需要修改的主要有幾部分內容:
1. UBL 代碼(這部分代碼在剛上電的時候,初始化CPU和拷貝UBOOT到DDR,打印信息只有很少,所以不做修改)。
2. UBOOT代碼。
3. linux內核驅動。
? ? ? 使用的代碼及版本請參考:http://processors.wiki.ti.com/index.php/DaVinci_PSP_03.01_Beta_(r31)_Release_Notes
?
2.1 修改UBOOT代碼
? ? ?因為DM6467的串口是符合TL16C550標準的,所以驅動也是使用16550的驅動,默認情況下,我們只需要提供需要配置的串口的基地址和中斷號等資源給16550的驅動就可以了,寄存器的配置不需要我們去關心。
? ? 要用起DM6467的串口有幾個地方的配置一定要注意:
1. 引腳復用寄存器(PINMUX0/1);
2.?VDD3P3V_PWDN寄存器,需要使能UART的相關引腳(bit4~bit9置零)
3.CLKCTL,bit24/25置零。
? ? 在UBOOT里涉及到上面幾個寄存器的配置的是在dm6467_evm.c的初始化部分
? ? 我的修改如下:
1 static void davinci_hd_psc_enable ( void ) 2 { 3 unsigned int alwaysonpdnum = 0; 4 5 /* Note this function assumes that the Power Domains are alread on */ 6 REG(PSC_ADDR+0xA00+4*14) |= 0x03; /* EMAC */ 7 REG(PSC_ADDR+0xA00+4*15) |= 0x03; /* VDCE */ 8 REG(PSC_ADDR+0xA00+4*16) |= 0x03; /* Video Port */ 9 REG(PSC_ADDR+0xA00+4*17) |= 0x03; /* Video Port */ 10 REG(PSC_ADDR+0xA00+4*20) |= 0x03; /* DDR2 */ 11 REG(PSC_ADDR+0xA00+4*21) |= 0x03; /* EMIFA */ 12 REG(PSC_ADDR+0xA00+4*26) |= 0x03; /* UART0 */ 13 REG(PSC_ADDR+0xA00+4*27) |= 0x03; /* UART1 */ 14 REG(PSC_ADDR+0xA00+4*28) |= 0x03; /* UART2 */ 15 REG(PSC_ADDR+0xA00+4*31) |= 0x03; /* I2C */ 16 REG(PSC_ADDR+0xA00+4*33) |= 0x03; /* GPIO */ 17 REG(PSC_ADDR+0xA00+4*34) |= 0x03; /* TIMER0 */ 18 REG(PSC_ADDR+0xA00+4*35) |= 0x03; /* TIMER1 */ 19 20 /* Set PTCMD.GO to 0x1 to initiate the state transtion for Modules in 21 * the ALWAYSON Power Domain 22 */ 23 REG(PSC_PTCMD) = (1<<alwaysonpdnum); 24 25 /* Wait for PTSTAT.GOSTAT0 to clear to 0x0 */ 26 while(! (((REG(PSC_PTSTAT) >> alwaysonpdnum) & 0x00000001) == 0)); 27 28 /* Enable GIO3.3V cells used for EMAC (???) */ 29 REG(VDD3P3V_PWDN) = (1<<27); //disable clkout0 30 31 /* Select UART function on UART0 */ 32 REG(PINMUX0) &= ~(0x0000003f << 18); 34 REG(PINMUX1) = ((1<<4)|(1<<2)|(1<<0)); 35 36 /* Enable USB */ 37 REG(PINMUX0) &= ~(0x80000000); 38 39 /* Set the Bus Priority Register to appropriate value */ 40 REG(VBPR) = 0x20; 41 }
接下來還有一個比較重要的地方需要修改,因為DM6467的串口是支持多種模式的,但16550的驅動是默認設備是工作在UART模式的,它沒有去配置設備串口的工作模式,所以我們需要去配置一下串口的工作模式。配置DM6467的需要修改寄存器去MDR1。只部分的代碼在UBOOT的driver目錄下的ns16550.c文件中。
? ? ?修改如下:
1 void NS16550_init (NS16550_t com_port, int baud_divisor) 2 { 3 com_port->ier = 0x00; 4 #if defined(CFG_DM6467_EVM) 5 com_port->mdr1 = 0x00; /* select mode */ 6 #endif 7 #if defined(CONFIG_OMAP) && !defined(CONFIG_OMAP3_ZOOM2) 8 com_port->mdr1 = 0x7; /* mode select reset TL16C750*/ 9 #endif 10 com_port->lcr = UART_LCR_BKSE | UART_LCRVAL; 11 com_port->dll = 0; 12 com_port->dlm = 0; 13 com_port->lcr = UART_LCRVAL; 14 com_port->mcr = UART_MCRVAL; 15 com_port->fcr = UART_FCRVAL; 16 com_port->lcr = UART_LCR_BKSE | UART_LCRVAL; 17 com_port->dll = baud_divisor & 0xff; 18 com_port->dlm = (baud_divisor >> 8) & 0xff; 19 com_port->lcr = UART_LCRVAL; 20 #if defined(CONFIG_OMAP) && !defined(CONFIG_OMAP3_ZOOM2) 21 #if defined(CONFIG_APTIX) 22 com_port->mdr1 = 3; /* /13 mode so Aptix 6MHz can hit 115200 */ 23 #else 24 com_port->mdr1 = 0; /* /16 is proper to hit 115200 with 48MHz */ 25 #endif 26 #endif /* CONFIG_OMAP */ 27 }
? ? 修改完上面的代碼后,就可以在配置文件里添加配置信息,并修改調試調試串口號了。打開/include/configs/davinci_dm6467_evm.c,找到串口配置部分,修改如下:
1 /*====================*/ 2 /* Serial Driver info */ 3 /*====================*/ 4 #define CONFIG_SYS_NS16550 5 #define CONFIG_SYS_NS16550_SERIAL 6 #define CONFIG_SYS_NS16550_REG_SIZE 4 /* NS16550 register size, byteorder */ 7 //#define CONFIG_SYS_NS16550_COM1 0x01c20000 /* Base address of UART0 */ 8 //#define CONFIG_CONS_INDEX 1 /* use UART0 for console */ 9 //#define CONFIG_SYS_NS16550_COM2 0x01c20400 /* Base address of UART1 */ 10 //#define CONFIG_CONS_INDEX 2 /* use UART1 for console */ 11 #define CONFIG_SYS_NS16550_COM3 0x01c20800 /* Base address of UART2 */ 12 #define CONFIG_CONS_INDEX 3 /* use UART2 for console */ 13 #define CONFIG_SYS_NS16550_CLK 24000000 /* Input clock to NS16550 */ 14 #define CONFIG_BAUDRATE 115200 /* Default baud rate */ 15 #define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
? ? 重新編譯UBOOT,下載測試,這時候UBOOT的打印信息應該從串口2輸出了。
? ? 正常情況下可以輸出到下面的內容:
Starting kernel ...
?
3.1 修改內核調試串口
? ?3.1.1 內核解壓輸出信息
? ? ? ? 內核解壓時使用的串口驅動是獨立于UBOOT或內核的串口驅動的,解壓時輸出的打印信息的相關的代碼在/arch/arm/mach_davinci/include/mach/uncompress.h內。這里的串口輸出代碼很簡單,只是往數據寄存器寫數據,并沒有對串口進行相關的配置,所以這里串口的正常輸出需要依賴UBOOT對串口的正確配置。uncompress.h文件修改如下:
1 static u32 *get_uart_base(void) 2 { 3 if (__machine_arch_type == MACH_TYPE_DAVINCI_DA830_EVM || 4 __machine_arch_type == MACH_TYPE_DAVINCI_DA850_EVM) 5 return (u32 *)DA8XX_UART2_BASE; 6 else 7 //return (u32 *)DAVINCI_UART0_BASE; 8 return (u32 *)DAVINCI_UART2_BASE; /* 這里修改為對應的寄存器基地址 */ 9 }
? ? ? 編譯內核,通過剛才更新的UBOOT下載內核,并啟動應該就可以看到熟悉的解壓信息了:
1 Uncompressing Linux................................................................................................................................................................done, booting the kernel.
?
? ? 3.1.2 修改內核驅動,改變內核調試串口
? ? 因為內核啟動時會對上面提到的幾個寄存器作修改,所以需要修改/arch/arm/mach_davinci/board_dm646x_evm.c文件來確認2.1提到的寄存器的配置,同時需要使能UART1或UART2的時鐘,默認情況下是只使能UART0的時鐘。內核串口驅動就不需要修改了,因為也是16550的驅動,這份驅動也沒有去配置串口的工作模式,所以UBOOT里配置了寄存器就行了,除非你想確認寄存器的配置,防止啟動內核時寄存器被修改了或想控制串口的工作模式。
? ?使能UART1/2時鐘:
1 static struct davinci_uart_config uart_config __initdata = { 2 3 .enabled_uarts = (1 << 0)|(1 << 1)|(1 << 2), 4 5 };
? 重新編譯內核,啟動UBOOT,修改內核啟動參數:
console=ttyS2,115200n8
下載內核,啟動~~順利的話就可以在UART2上輸出系統的調試信息了:
Uncompressing Linux.......................................................................................................................... done, booting the kernel. Linux version 2.6.32-rc2-davinci1 (root@ubuntuSv) (gcc version 4.3.3 (Sourcery G++ Lite 2009q1-203) ) #107 PREEMPT Tue Oct 25 08:04:49 UTC 2011 CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177 CPU: VIVT data cache, VIVT instruction cache Machine: ZMV-6467 Memory policy: ECC disabled, Data cache writeback DaVinci dm6467_rev3.x variant 0x1