NBOOT 基于VS2005的编程与编译(二)

四、增加串口功能

       串口在调试时,打印调试信息是很有用的;在nboot过程中,打印些信息,若是发生crash,也可判断是否在nboot阶段。

       串口采用UART0,115200波特率。

      1、Clone过来的bsp默认是采用UART1,修改"\SRC\INC\bsp_cfg.h"文件

1 //------------------------------------------------------------------------------
2 // Debug UART0
3 //------------------------------------------------------------------------------
4
5 #define BSP_UART0_ULCON 0x03 // 8 bits, 1 stop, no parity
6 #define BSP_UART0_UCON 0x0005 // pool mode, PCLK for UART
7 #define BSP_UART0_UFCON 0x00 // disable FIFO
8 #define BSP_UART0_UMCON 0x00 // disable auto flow control
9 #define BSP_UART0_UBRDIV (S3C2410X_PCLK/(115200*16) - 1)

2、在nboot目录下新建debug.c文件,并加入工程。debug.c文件完成串口的初始化和字符串输出功能,其代码可copy 

"\SRC\OAL\OALLIB\debug.c"文件,稍微修改即可,包括两个函数
VOID OEMInitDebugSerial()和VOID OEMWriteDebugString(LPWSTR string)
1 #include <bsp.h>
2
3
4
5 VOID OEMInitDebugSerial()
6 {
7
8 volatile S3C2410X_IOPORT_REG *pIOPortReg = (S3C2410X_IOPORT_REG*)(S3C2410X_BASE_REG_PA_IOPORT);
9 volatile S3C2410X_UART_REG *pUARTReg = (S3C2410X_UART_REG *)(S3C2410X_BASE_REG_PA_UART0);
10
11 // GPH2 and GHP3 are UART0 Tx and Rx, respectively.
12 //
13
14 pIOPortReg->GPHCON &= ~((3 << 4)|(3 << 6));
15 pIOPortReg->GPHCON |= (2 << 4)|(2 << 6);
16
17 // Disable pull-up on TXD0 and RXD0.
18 pIOPortReg->GPHUP |= (1 << 2)|(1 << 3);
19
20 // Configure the UART.
21 pUARTReg->UFCON = BSP_UART0_UFCON; // FIFO disable
22 pUARTReg->UMCON = BSP_UART0_UMCON; // AFC disable
23
24 pUARTReg->ULCON = BSP_UART0_ULCON; // Normal,No parity,1 stop,8 bits
25 pUARTReg->UCON = BSP_UART0_UCON;
26
27 pUARTReg->UBRDIV= BSP_UART0_UBRDIV;
28
29
30 }
31
32 //------------------------------------------------------------------------------
33 //
34 // Function: OEMWriteDebugByte
35 //
36 // Transmits a character out the debug serial port.
37 //
38 static VOID OEMWriteDebugByte(UINT8 ch)
39 {
40 volatile S3C2410X_UART_REG *pUARTReg = (S3C2410X_UART_REG *)(S3C2410X_BASE_REG_PA_UART0);
41
42 // Wait for transmit buffer to be empty
43 while (((pUARTReg->UTRSTAT) & 0x02) == 0);
44
45 // Send character
46 pUARTReg->UTXH = ch;
47
48 }
49
50
51
52 //------------------------------------------------------------------------------
53 //
54 // Function: OEMWriteDebugString
55 //
56 // Output unicode string to debug serial port
57 //
58 VOID OEMWriteDebugString(LPWSTR string)
59 {
60 while (*string != L'\0')
61 OEMWriteDebugByte((UINT8)*string++);
62 }

3、以上两步已将串口功能实现,通过OEMWriteDebugString(TEXT("Hello World!\r\n"))这样的语句来打印debug信息了。

五、NAND FLASH部分

      NAND FLASH 读代码复杂,不过在BSP都基本有现成代码,拷贝过来修改即可。主要包含两个函数,初始化NANDFLASH和读NANDFLASH。

      1、nboot目录新建个Flash.c文件并加入工程,copy"\SRC\COMMON\SMARTMEDIA\FMD\ARM\nand.s"到nboot目录并加入工程;

           copy"\SRC\COMMON\SMARTMEDIA\FMD\nand.h"文件到目录下,并include到Flash.c文件。

      2、Flash_Iint ()函数实现。Flash.c

1
2 void Flash_Init()
3 {
4 // Caller should have specified NAND controller address.
5 //
6 s2410NAND = (S3C2410X_NAND_REG *)NAND_BASE;
7
8 // Set up initial flash controller configuration.
9 //
10 s2410NAND->NFCONF = (1 << 15) | /* Enable/Disable */
11 (1 << 14) | /* Page Size : 512Bytes */
12 (1 << 13) | /* 4 Step Address */
13 (1 << 12) | /* Initialize ECC */
14 (1 << 11) | /* nFCE control nFCE = HIGH */
15 (TACLS << 0) | /* CLE & ALE = HCLK * (TACLS + 1) */
16 (TWRPH0 << 3) | /* TWRPH0 = HCLK * (TWRPH0 + 1) */
17 (TWRPH1 << 0); /* TWRPH1 = HCLK * (TWRPH1 + 1) */
18
19 NF_nFCE_L(); // Select the flash chip.
20 NF_CMD(CMD_RESET); // Send reset command.
21 NF_WAITRB(); // Wait for flash to complete command.
22 // Get manufacturer and device codes.
23
24 NF_nFCE_H(); // Deselect the flash chip.
25 }

3、Flash读函数,Flash_ReadSector()函数实现。Flash.c

1
2 /*
3 @func BOOL | FMD_ReadSector | Reads the specified sector(s) from NAND flash.
4 @rdesc TRUE = Success, FALSE = Failure.
5 @comm
6 @xref
7
*/
8 BOOL Flash_ReadSector(DWORD startSectorAddr, LPBYTE pSectorBuff, DWORD dwNumSectors)
9 {
10 ULONG SectorAddr = (ULONG)startSectorAddr;
11 ULONG blockPage;
12
13 NF_RSTECC(); // Initialize ECC.
14 NF_nFCE_L(); // Select the flash chip.
15 NF_CMD(CMD_RESET); // Send reset command.
16
17 while (dwNumSectors--)
18 {
19 blockPage = (((SectorAddr / NAND_PAGE_CNT) * NAND_PAGE_CNT) | (SectorAddr % NAND_PAGE_CNT));
20
21 NF_WAITRB(); // Wait for flash to complete command.
22
23 if (pSectorBuff)
24 {
25 NF_CMD(CMD_READ); // Send read command.
26 NF_ADDR(0); // Column = 0.
27 NF_ADDR(blockPage & 0xff); // Page address.
28 NF_ADDR((blockPage >> 8) & 0xff);
29 NF_ADDR((blockPage >> 16) & 0xff);
30 NF_WAITRB(); // Wait for command to complete.
31
32 // Handle unaligned buffer pointer
33 RdPage512(pSectorBuff); // Read page/sector data.
34
35 NF_RDDATA(); // Read/clear status.
36 NF_RDDATA(); //
37 }
38
39 ++SectorAddr;
40 pSectorBuff += NAND_PAGE_SIZE;
41 }
42
43 NF_nFCE_H(); // Deselect the flash chip.
44
45 return(TRUE);
46 }

4、修改Flash Controller的寄存器地址,#define NAND_BASE 0x4e000000。另外nand.s文件内,也要改过来(NFDATA)。nand.s文件内除了Rdpage512()之外函数都可以删除。

      这样,NAND FLASH 部分也就完成了。

 六、main文件,完成

      经过以上工作,nboot差不多就完成了,在main函数中调用就可了

      1、在main函数内,按顺序调用下面的函数

    OEMInitDebugSerial();
    Flash_Init();
    Flash_ReadSector(0x30021000,32,0x00040000/512));   
            //0x3002_1000是EBOOT的ram地址,0x00040000的大小,
           //32是FlashPage Bloack-1的地址(也即Eboot烧到block-0)

      2、运行EBOOT。copy eboot目录下的ulit.s文件,删除两句语句,

       ;       ldr     r3, = (VIR_RAM_START - PHY_RAM_START)
      ;       sub     r2, r2, r3

       然后再main函数内调用Launch(0x300021000)即可启动EBOOT了。

 七、完结

       将nboot编译,烧进Flash,并烧录eboot,上电,看到EBOOT启动了。

转自:http://www.cnblogs.com/wincee/articles/1689139.html

原文地址:https://www.cnblogs.com/wenziqi/p/1814660.html