Tuesday, December 1, 2009
Usual Arm Boot Sequence
the boot pins. The MMU is off when the processor is reset.
Following is the typical sequence of initialization: (assuming that
the bootloader is burned on and is running from a non-volatile memory
like NOR flash.)
1. Initialize the SDRAM controller.
2. Set up the stacks for various (ARM) processor modes. (undef, irq,
fiq ... )
3. Clear up the BSS space. (uninitialized variables)
4. Relocate the code to run from RAM (not always necessary).
5. Copy the .data section (initialized variables) to RAM.
6. Jump to C code.
7. Initialize the external bus controller for various address spaces
(chip selects). This depends on what devices you have connected to the
bus and what are their timing parameters.
8. Initialize various devices. (by calling their init functions)
9. Load the filesystem driver.
10. Search for the kernel.
11. Copy kernel to RAM. Set up command line parameters for the
kernel.
12 Jump to kernel entry point.
Wednesday, October 28, 2009
Porting U-boot to Powerpc processor
Understand the anatomy & flow of processor & its core.
- MPC 8548 is based on E500
- General Overview of E500(User point of view):-
- 32 bit processor based on Powerpc BOOKE (i.e uses lower 32 bit of 64 bit)
- 5 stage pipeline; Instruction fetch, Decode,Execution,Writeback and completion
- Execution unit is further subdivided in 3 stage pipeline and has Simple Units (SU1 & SU2),Multiple unit(MU) and Branch Perdiction units.
- Also has Instruction fetch queues, Branch target Buffers, Completion Queues etc.,
- Internal bus is CCB (Complex Core Bus; Both data & address)
- At maximum 2 Instruction/Cycle can be completed.
- E500, does have MMU:-
- -32 Kbyte Instruction & Data L1 Cache.
- -64 (4kpage)/4 entry Instruction & Data L1 MMU
- -256/16 entry Instruction & Data L2 MMU.
- E500, On reset fetches the instruction from specific location 0xFFFF_FFFC.
- Default entry for 4K Boot Page.
- ->Pipeline Flow: IF->DEC->EXEC->WB->COM
- E500 core has two modes for programming-Supervisor and General programming mode.
- Register groups of GP - 32 GPR, 7 SPRs, Condition Registers(CR), Count Registers (CTR), Link Registers(LR), otherslike (Performance registers etc).
- Register groups of Supervisor mode- Reg group of GP, Memory Address Select Registrs(MAS0-7), Interrupt vector Offset Register(IVOR0-IVOR35), Tnterrupt Prefix registers(IVPR), Timer Registers, Machine state Reg(MSR), Hardware implementation Registers(HID0&1).
- Significant Interupts - critical, machine check, Data storage, External input, alignment, programm interrupt offset, floating point, syscall, decrementer, fixed interval timer, watch dog timer, Data&Instruction TLB, and Debug interrupt.
- MMU address translation:-
- -41 bit virt address(1AS+8PiD+20EP+12BYTE ADDRESS)->L1 MMU->[if L1 missed, L2-MMU]->32bit Real_address(20 RPN + 12 Byte Address).
- Ofcourse, e500 core.
- DDR controller
- Local Bus Controller
- eTsecs.
- UARTS
- PICs
- 1 MB CCSRBAR (Internal memory mapped registers)
- PCI Xpress, Pci 66Mhx, Pci-x 133 Mhz controllers
- Rapid I/Os.
- 4 channel DMA controllers.
- 512K L2 Cache/SRAM.
Uboot is organised as boards and CPU on which the board is based, so following is the important
folders that has to be taken care while porting
1. board/freesacle/
- init.s (lowlevel initialization)
- *,lds file (Loader Script)
- Config macros for boot and hardware configurations
- start.S (startup- Core initialization and stack creation)
- resetvector.S(Jump to 4k boot page)
4. lib_ppc/
- board.c (all controller initialization, console buffers & inits, driver inits & relocations )
Important Data Structure:-
1. gd_t (Global data structure) in include/asm-
- has bd_t (board_descriptor structure).
- Fields to hold clocks of various controller(pci_clk, mem_clk, bus_Clk, cpu_clk...).
- Fields to hold baud rate etc...
- Fileds for env_address, check_sum fild (env_valid), have_Console(condition byte)
- Jump table pointers.
- Usually has the fields for start of DRAM memory, flash_start, flash_size, immr_base address, bootflags, clock freq of controllers,etc.,
1. Jump from reset vector(FFFF_FFFC) to 4K boot page (start.S) with in the FLASH
2. start.s (goal is to setup the initial stack and jump to c routine for flexible initialization)
[Code is in flash.]
- enable/invalidate the caches.
- set the Interrupt vectors to fall with in the 4k page.
- Increase the boot window to 4M(0xFFC0_0000) with in the flash by adding an entry to TLB.
- Allocate initial RAM in Dcache.
- Jump to the new address in flash.
- Create an initial stack in Dcache. (Till here assembly code)
- Jump to c routine(cpu_early_init_f).
- Initialize the clock, LAWBARS, DDRControllers, Local Bus Controllers.
- Add entries to TLBs for all DRAM, PCI, FLASH, etc...
- returns back to start.s from where board initialization is called.
4. board initialization from FLASH
- see lib_ppc/board.c.
- Routines in init_sequence array are called. Most commonly env_init, console_buufer, serial_init, dpram_init , init_time_base etc...
- Now SDRAM is available.
- Reserve area for u-boot, data & bss, IVPR, Global descriptor,and malloc (Top down approach)
- Create a bigger stack
- Relocate the u-boot code, data, bss,ivpr to RAM
- Clear the bss, initialize the data pointer and call board_initialization from RAM (board_init_r)
- all driver initialization takes place like pci_init, ethernet_init, etc.,
- also, command table is relocated manually to ram.
- Jump_table is initialized.
- u-boot prompt is displayed.
- bootm command is used to boot linux which is in common/cmd_bootm.c.
- bootm command format is
- bootm
- command uncompresses and validates the images by process the headers
- After validation uboot jumps to the kernel, its wortnoting to see the sequence before jumping to kernel(I am using linux) in function do_bootm_linux() in [cmdline, bd_t... are handled].
- R1: stack pointer
- R2: reserved for system use
- R3-R4: parameter passing and return values
- R5-R10: parameter passing
- R13: small data area pointer
- R30: GOT pointer
- R31: frame pointer
Wednesday, October 21, 2009
Useful Powerpc Instructions
- Here are some of Powerpc instructions. Good articles on PPC assembly in the following link; I got this listing from this article ....
- http://www.ibm.com/developerworks/library/l-powasm1.html
- li REG, VALUE
loads register REG with the number VALUE
- add REGA, REGB, REGC
adds REGB with REGC and stores the result in REGA
- addi REGA, REGB, VALUE
add the number VALUE to REGB and stores the result in REGA
- mr REGA, REGB
copies the value in REGB into REGA
- or REGA, REGB, REGC
performs a logical "or" between REGB and REGC, and stores the result in REGA
- ori REGA, REGB, VALUE
performs a logical "or" between REGB and VALUE, and stores the result in REGA
- and, andi, xor, xori, nand, nand, and nor
all of these follow the same pattern as "or" and "ori" for the other logical operations
- ld REGA, 0(REGB)
use the contents of REGB as the memory address of the value to load into REGA
- lbz, lhz, and lwz
all of these follow the same format, but operate on bytes, halfwords, and words, respectively (the "z" indicates that they also zero-out the rest of the register)
- b ADDRESS
jump (or branch) to the instruction at address ADDRESS
- bl ADDRESS
subroutine call to address ADDRESS
- cmpd REGA, REGB
compare the contents of REGA and REGB, and set the bits of the status register appropriately
- beq ADDRESS
branch to ADDRESS if the previously compared register contents were equal
- bne, blt, bgt, ble, and bge
all of these follow the same form, but check for inequality, less than, greater than, less than or equal to, and greater than or equal to, respectively.
- std REGA, 0(REGB)
use the contents of REGB as the memory address to save the value of REGA into
- stb, sth, and stw
all of these follow the same format, but operate on bytes, halfwords, and words, respectively
- sc
makes a system call to the kernel
C a prg of fun point
#include
#include
int cmd_show()
{
printf("Show \n");
return 0;
}
int cmd_add()
{
printf("Add \n");
return 0;
}
/* command structure*/
typedef struct {
char name[100];
int (*exec_cmd)();
} cmd_t;
cmd_t cmd_table1[] = {
{"cmd_show", cmd_show},
{"cmd_add", cmd_add}
};
/* A Function that is returning the function pointer
* the syntax would be - return_type (*function_name(param_list of this))(argument_type of the fun ptrs)
*/
int (*get_func(char *str))()
{
int i = 0;
for (i = 0; i < sizeof(cmd_table1)/sizeof(cmd_t); i++)
{
if (strcpy(cmd_table1[i].name, str)) {
printf("Matched!\n");
return cmd_table1[i].exec_cmd;
}
}
return NULL;
}
int main()
{
int (*exec_fun)();
/* call the get func, it returns the function address based on the string passed */
exec_fun = get_func("cmd_show");
if (exec_fun != NULL)
return exec_fun();
return 0;
}
Thursday, October 15, 2009
Hmmm Software Design!
I believe software design is more difficult design than any other engineering design because, a software design involves arbitary variables and no software design is believed to have no bugs,..
So here the probability evolves.. It is effort of the engineers to make the probability of uncertainity to be less... but it is hard because the probability of determining the uncertainities for a human brain, unless it is subjected all uncertainities, is less...So probability of every first design to be 100% bug free is less, but the probability of successive designs may improve but could not be a perfect 1..
Friday, February 27, 2009
First Scribling....
Hope I enjoy the fullest happiness after sharing...
Next Posting will start with techie scrible.......