标题:
WinCE6.0 BootloaderMain源码分析之OEMDebugInit
[打印本页]
作者:
samwalton
时间:
2013-9-13 14:12
标题:
WinCE6.0 BootloaderMain源码分析之OEMDebugInit
BootloaderMain在进行全局变量重定位后,执行的便是OEMDebugInit操作,主要完成调试串口的初始化工作,这部分内容比较简单。从函数名OEM可以看出,该函数是需要用户自己开发的,而且与硬件有关。
BOOL OEMDebugInit(void)
{
// Set up function callbacks used by blcommon.
g_pOEMVerifyMemory = OEMVerifyMemory; // Verify RAM.
g_pOEMMultiBINNotify = OEMMultiBINNotify;
// Call serial initialization routine (shared with the OAL).
OEMInitDebugSerial();
return(TRUE);
}
从上面的实现看,前面两条语句定义的是函数指针,在blcommom.c中会调用这两个函数。OEMVerifyMemory函数负责检测某一段虚拟内存地址区域是否映射到用户实际可使用的物理存储,包括Flash和RAM;当BootLoader要下载多区段的操作系统镜像时会调用函数OEMMultiBINNotify向用户发出通知。 OEMInitDebugSerial才是该函数的重点,实现代码在/WINCE600/PLATFORM/<BSP name>/SRC/OAL/OALLIB/debug.c文件中。VOID OEMInitDebugSerial()
{
UINT32 DivSlot;
UINT32 uPCLK;
float Div;
// Map SFR Address
//
if (g_pUARTReg == NULL)
{
#if (DEBUG_PORT == DEBUG_UART0)
// UART0
g_pUARTReg = (S3C6410_UART_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_UART0, FALSE);
#elif (DEBUG_PORT == DEBUG_UART1)
// UART1
g_pUARTReg = (S3C6410_UART_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_UART1, FALSE);
#elif (DEBUG_PORT == DEBUG_UART2)
// UART2
g_pUARTReg = (S3C6410_UART_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_UART2, FALSE);
#elif (DEBUG_PORT == DEBUG_UART3)
// UART3
g_pUARTReg = (S3C6410_UART_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_UART3, FALSE);
#else
INVALID_DEBUG_PORT // Error
#endif
}
if (g_pGPIOReg == NULL)
{
g_pGPIOReg = (S3C6410_GPIO_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_GPIO, FALSE);
}
if (g_pSysConReg == NULL)
{
g_pSysConReg = (S3C6410_SYSCON_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_SYSCON, FALSE);
}
// UART I/O port initialize
#if (DEBUG_PORT == DEBUG_UART0)
// UART0 Clock Enable
g_pSysConReg->PCLK_GATE |= (1<<1); // UART0
g_pSysConReg->SCLK_GATE |= (1<<5); // UART0~3
// UART0 Port Initialize (RXD0 : GPA0, TXD0: GPA1)
g_pGPIOReg->GPACON = (g_pGPIOReg->GPACON & ~(0xff<<0)) | (0x22<<0); // GPA0->RXD0, GPA1->TXD0
g_pGPIOReg->GPAPUD = (g_pGPIOReg->GPAPUD & ~(0xf<<0)) | (0x1<<0); // RXD0: Pull-down, TXD0: pull up/down disable
#elif (DEBUG_PORT == DEBUG_UART1)
// UART1 Clock Enable
g_pSysConReg->PCLK_GATE |= (1<<2); // UART1
g_pSysConReg->SCLK_GATE |= (1<<5); // UART0~3
// UART1 Port Initialize (RXD1 : GPA4, TXD1: GPA5)
g_pGPIOReg->GPACON = (g_pGPIOReg->GPACON & ~(0xff<<16)) | (0x22<<16); // GPA4->RXD1, GPA5->TXD1
g_pGPIOReg->GPAPUD = (g_pGPIOReg->GPAPUD & ~(0xf<<8)) | (0x1<<8); // RXD1: Pull-down, TXD1: pull up/down disable
#elif (DEBUG_PORT == DEBUG_UART2)
// UART2 Clock Enable
g_pSysConReg->PCLK_GATE |= (1<<3); // UART2
g_pSysConReg->SCLK_GATE |= (1<<5); // UART0~3
// UART2 Port Initialize (RXD2 : GPAB0, TXD2: GPB1)
g_pGPIOReg->GPBCON = (g_pGPIOReg->GPBCON & ~(0xff<<0)) | (0x22<<0); // GPB0->RXD2, GPB1->TXD2
g_pGPIOReg->GPBPUD = (g_pGPIOReg->GPBPUD & ~(0xf<<0)) | (0x1<<0); // RXD2: Pull-down, TXD2: pull up/down disable
#elif (DEBUG_PORT == DEBUG_UART3)
// UART3 Clock Enable
g_pSysConReg->PCLK_GATE |= (1<<4); // UART3
g_pSysConReg->SCLK_GATE |= (1<<5); // UART0~3
// UART3 Port Initialize (RXD3 : GPB2, TXD3: GPB3)
g_pGPIOReg->GPBCON = (g_pGPIOReg->GPBCON & ~(0xff<<8)) | (0x22<<8); // GPB2->RXD3, GPB3->TXD3
g_pGPIOReg->GPBPUD = (g_pGPIOReg->GPBPUD & ~(0xf<<4)) | (0x1<<4); // RXD3: Pull-down, TXD3: pull up/down disable
#endif
// Initialize UART
//
g_pUARTReg->ULCON = (0<<6)|(0<<3)|(0<<2)|(3<<0); // Normal Mode, No Parity, 1 Stop Bit, 8 Bit Data
g_pUARTReg->UCON = (0<<10)|(1<<9)|(1<<8)|(0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0); // PCLK divide, Polling Mode
g_pUARTReg->UFCON = (0<<6)|(0<<4)|(0<<2)|(0<<1)|(0<<0); // Disable FIFO
g_pUARTReg->UMCON = (0<<5)|(0<<4)|(0<<0); // Disable Auto Flow Control
uPCLK = System_GetPCLK();
Div = (float)((float)uPCLK/(16.0*(float)DEBUG_BAUDRATE)) - 1; //< S3C6410_PCLK is macro code defined in soc_cfg.h
DivSlot = (UINT32)((Div-(int)Div)*16);
g_pUARTReg->UBRDIV = (UINT32)Div; // Baud rate
g_pUARTReg->UDIVSLOT = aSlotTable[DivSlot];
}
从代码可以看出,里面加了很多编译选项,增强移植性的。当需要更改调试串口时,只需要更改编译选项就可以了。通过OALPAtoVA先将获得调试串口、GPI以及系统控制器的虚拟地址,方便后面的初始化设置。g_pSysConReg->PCLK_GATE为UART1选通PLCK,g_pSysConReg->SCLK_GATE为UART0~3选通特殊时钟。g_pGPIOReg->GPACON设置复用IO端口为UART功能,g_pGPIOReg->GPAPUD设置相应的串口管脚位下拉使能。g_pUARTReg->ULCON设置串口为普通模式、无校验、1个停止位和8个数据位;g_pUARTReg->UCON设置选择PCLK作为UART的波特率时钟,接收和发送中断请求类型为电平模式,而且以中断请求或轮询模式来写发送数据到UART发送缓冲寄存器或者从UART接收缓冲寄存器读数据。最后几条代码是获得PCLK后设置波特率参数。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0