For embedded systems, a bootloader is generally needed to download and boot the operating system. Common bootloaders include eboot, uboot, and vivi. The most ideal bootloader for Windows CE is of course eboot (I have also used uboot to download and boot CE, which I will introduce later). Below I will share with you the process of developing eboot. The eboot process can be shown as follows:
1) eboot and nk share a start code fw.s, so we will find fw.s in the arm subfolder under the eboot folder, which contains a sentence: INCLUDE ..\\..\\kernel\\hal\\arm\\fw.s. I will not analyze this start code in detail. It is nothing more than setting up the interrupt vector table, setting the system operating frequency, setting the MMU, etc., and then jumping to the main function of eboot.
2) The main function of eboot is in main.c in the eboot folder. The code is as follows:
void main (void)
{
BootloaderMain();
SPIN_FOREVER;
}
Do you think it is very simple? It seems that nothing is done, but pay attention to the BootloaderMain function. This is the real main function of eboot. This function is in
$(_WINCEROOT)\PUBLIC\COMMON\OAK\DRIVERS\ETHDBG\BLCOMMON\blcommon.c, this function is the common function of Microsoft ce for eboot, it will call some functions written by OEM or yourself in the eboot folder. Now that we know where the real main function is, let's follow BootloaderMain.
3) In the BootloaderMain function, KernelRelocate is first executed to store some global variables into RAM. This function is not very important.
4) The next step is to execute OEMDebugInit. If you see the three letters OEM, it means that this function is for OEM or we need to implement it ourselves. This function can be found in the main function under eboot. It mainly provides some callback functions for blcommon as shown below:
BOOL OEMDebugInit()
{
// Assign callback functions to be used by blcommon.
g_pOEMReportError = OEMReportError; //Error reporting function
g_pOEMVerifyMemory = OEMVerifyMemory; // Check if the memory is normal when downloading the image
g_pOEMMultiBINNotify = OEMMultiBINNotify; //Notify all bin files that need to be downloaded
OEMInitDebugSerial(); //Initialize serial port debugging output
return TRUE;
}
These called functions are also written by OEMs or ourselves. The first three functions can be found in main.c. The code is rather verbose and basically has little to do with the hardware. Let's look at the last function that initializes the serial port debug output. This file is in D:\WINCE420\PLATFORM\smdk2410eboot+rtc\KERNEL\HAL\debug.c. I set serial port 0 as the debug output port. Samsung's built-in serial port 1 is used, and the baud rate is set to 115200. If you need to use serial port 0 as the debug output port, you can refer to my modification:
#define UART0BaudRate 115200
void OEMInitDebugSerial(void)
{
volatile UART1reg *s2410UART0 = (UART0reg *)UART0_BASE;
volatile IOPreg *s2410IOP = (IOPreg *)IOP_BASE;
s2410IOP->rGPHCON &= ~((3 << 8) | (3 << 10));
s2410IOP->rGPHCON |= ((2 << 4) | (2 << 6)); //
s2410IOP->rGPHUP |= (1 << 2) | (1 << 3);
s2410UART0->rUFCON = 0x0; // Disable the FIFO
s2410UART0->rUMCON = 0x0; // Disable AFC.
s2410UART0->rULCON = 0x3; // Normal mode, N81.
s2410UART0->rUCON = 0x245;
s2410UART0->rUBRDIV = ( (int)(S2410PCLK/16.0/UART0BaudRate + 0.5) -1 );
}
After calling this debug output initialization function, the debugging information of eboot will come out from serial port 0 (of course, the debugging information of nk will also come out from this serial port, because this part is multiplexed with nk^_^)
5) After BootloaderMain calls OEMDebugInit, it calls the next function - OEMPlatformInit. This function can also be found in main.c of eboot. It mainly initializes your hardware platform, including setting the RTC clock, initializing your NANDflash, and then reading TOC (table of contents). Generally, TOC will be burned into block1 of nand. If reading TOC fails, TOC will be rewritten with default parameters. The code for reading TOC is relatively simple. It is in fmd.cpp and you can study it yourself. Then it enters the countdown. If you press the keyboard within the delay time you set, you will enter the BootMonitor function. This function mainly outputs the eboot selection menu and performs operations based on your selection. If you do not press the keyboard at the end of the delay time, the next step will be performed based on whether you set it to Download new (download a new image) or Launch existing (load the image in nand). Let's first look at the BootMonitor function. Although this function has a lot of code, it is actually very simple. It sets and changes some global variables based on your input, and eboot will perform corresponding operations based on these variables later.
If you choose to download the image, the OEMPlatformInit function will call InitEthDevice to initialize the network card and then return true. The InitEthDevice function is in ether.c. You need to provide some interfaces to eboot according to the network card you use. The following is my InitEthDevice function. I use the DM9000 network card:
BOOL InitEthDevice(PBOOT_CFG pBootCfg)
{
USHORT wMAC[3];
PBYTE pBaseIOAddress = NULL;
DWORD dwMultiplier = 0;
// Boot CS8900.
//
if (!pBaseIOAddress)
{
// Use the MAC address programmed into flash by the user.
//
memcpy(wMAC, pBootCfg->EdbgAddr.wMAC, 6);
pfnEDbgInit = DM9000DBG_Init;
pfnEDbgGetFrame = DM9000DBG_GetFrame;
pfnEDbgSendFrame = DM9000DBG_SendFrame;
pBaseIOAddress = (PBYTE)CS8900DBG_IOBASE;
dwMultiplier = CS8900DBG_MEMBASE;
memcpy(pDriverGlobals->eth.TargetAddr.wMAC, pBootCfg->EdbgAddr.wMAC, 6);
pDriverGlobals->misc.EbootDevice = (UCHAR)DOWNLOAD_DEVICE_CS8900;
}
// Initialize the built-in Ethenet controller.
//
if (!pfnEDbgInit((PBYTE)pBaseIOAddress, dwMultiplier, wMAC))
{
EdbgOutputDebugString("ERROR: InitEthDevice: Failed to initialize Ethernet controller.\r\n");
return(FALSE);
}
// Make sure MAC address has been programmed.
//
if (!wMAC[0] && !wMAC[1] && !wMAC[2])
{
EdbgOutputDebugString("ERROR: InitEthDevice: Invalid MAC address read from NIC.\r\n");
return(FALSE); }
memcpy(&pDriverGlobals->eth.TargetAddr.wMAC, &wMAC, (3 * sizeof(USHORT)));
return(TRUE);
}
DM9000DBG_Init; DM9000DBG_GetFrame; DM9000DBG_SendFrame; These functions need to be implemented in your network card driver. Here you only need to provide these functions to eboot.
6) BootloaderMain calls OEMPreDownload to do some pre-download preparations, then calls DownloadImage to download the kernel. After downloading, OEMLaunch is called to start the kernel in RAM. Note that OEMLaunch needs to establish a connection with PB. If we want to bypass PB to download nk (I have introduced the implementation method in previous articles), we need to block this code (between #ifndef SIMULATOR #endif).
7) If we choose to Launch existing image, in OEMPlatformInit of eboot, ReadRamImageFromBootMedia or ReadKernelRegionFromBootMedia function will be used to read nk from nand to ram, and then start the kernel. The first function is to directly copy the kernel from nand to RAM, and the second function must choose to support binfs file format, it will format nand into binfs, these functions for nand operation are in fmd.cpp, and the specific implementation can refer to the code inside.
8) The above are all the more important parts of eboot. In fact, in the eboot selection menu, you can also choose to format nand, set ip, mac address, etc. In general, the functions of eboot are still very powerful, but compared with uboot, it is still far behind, because it does not do well in human-computer interaction and is not as powerful as uboot.
Previous article:Analysis of mini2440 LED driver
Next article:Porting 2.6 kernel on s3c2410 board
- Popular Resources
- Popular amplifiers
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Design considerations for automotive battery wiring harness
- Do you know all the various motors commonly used in automotive electronics?
- How to select the parameters of the RCD circuit resistor in the power supply circuit?
- TI Industrial Month Season 2 - Deep Learning of Technical Solutions
- C55x C and Assembly Language Mixed Programming
- UPS Uninterruptible Power Supply
- How to buy MSP430 development boards on TI.com
- 【LuatOS-ESP32】Light up the LED
- Is your company greatly affected by the chip shortage? How do you deal with it?
- [NXP Rapid IoT Review] Week 5: DIY BLE_APP for NXP IoT: RGB Dimming Control
- TI C6000 Data Storage Processing and Performance Optimization
- Porting OpenCV on DSP_6748