Thursday, 3 August 2017

BSP Notes

1.Head.s -> start_kernel -> setup_arch
Setup_arch will get the struct machine_desc defined in the platform file . All the initialization operations on the platform are based on machine_desc . Specific conditions is compiled in accordance with arch / arm / configs in xxx_defconfig

2.According to the above judgment, HAL (BSP) is written entirely with machine_desc as the entrance
The contents of the need to write include plat / xx and mach_xx / under the kernel beat, interrupt management, clock, GPIO , DMA , IO memory mapping, pin multiplexing, external device registration and resource- related code. The external device and device resources are registered in the board initialization, and the device driver is placed in the / drivers directory.Linux BSP (here do not consider the bootloader and file system) development level has three levels: 
1. Architecture level development. 
2.SOC level of transplantation.
3. Device-driven porting. 
The development of the architecture level is generally done by the Linux kernel community or architecture vendor. After the completion of the Linux kernel source tree, this level of development mainly to complete the memory management, process scheduling, anomalies, traps, etc., the development process need to refer to the architecture Of the datasheet , such as arm920TDMI / Cortex A8 even have armV6 / armV7 instruction set architecture .
 In fact, Linux 's arch directory has supported almost all of today's architecture, it is generally not going to be architecture-level BSP development. The most common or SOC level of BSP development and driver development, SOC level of BSP developers only need to refer to SOC 's Datasheet , such as S3C2410 / MX53. Drive the development not only to refer to the datasheet of the SOC but also refer to the PCB design schematic. This article is concerned about the SOC level of development or transplantation. Popular terms, is to let a set of official standard linux source in their own board to run up.

3.Struct machine_desc members and call the time
In Setup_arch() in int_irq(), timer & init_machine are assigned to the following variables:
         init_arch_irq = mdesc-> init_irq;
         system_timer = mdesc-> timer;
         init_machine = mdesc-> init_machine;
And the three function pointers are called in the following scenarios:
Start_kernel () -> init_IRQ () [irq.c] -> init_arch_irq ();
Start_kernel () -> time_init () [time.c] -> system_time-> init ();
Customize_machine () -> init_machine ();
Customize_machine is placed in the arch_initcall section, which is called in order. 
The function in the xxx_initcall section is called in the following order: 
start_kernel () -> rest_init () [ start kernel thread ] -> kernel_init () - > do_basic_setup () -> do_initcalls ();
map_io is called in the following order:
Start_kernel () -> setup_arch () -> paging_init () -> devicemaps_init () -> map_io ()
The fixup is called in the following order:
Start_kernel () -> setup_arch () -> setup_machine_tags ()
init_early is called in the following order:
Start_kernel () -> setup_arch () -> init_early
They are called in the start_kernel () order, we can see that they are: 
fixup -> map_io ->  init_early  -> init_irq ->   timer   -> init_machine , 
it should generally follow the order in order to achieve.
4.Fixup in mx53 although set up, but is an empty function
5.Map_io done the job
void __init mx6_map_io (void)
{
        otable_init (mx6_io_desc, ARRAY_SIZE (mx6_io_desc));
        mxc_iomux_v3_init (IO_ADDRESS (MX6Q_IOMUXC_BASE_ADDR));
        mxc_arch_reset_init (IO_ADDRESS (MX6Q_WDOG1_BASE_ADDR));
        mx6_set_cpu_type ();
        mxc_cpu_lp_set (WAIT_CLOCKED);
}
iotable_init is to carry out static memory mapping, some of the physical address permanently mapped to a fixed virtual address up; these virtual addresses must be in the kernel space; why mapping? In the driver can use the ioremap function for dynamic mapping, for the kind of operation in the system need to be frequently accessed during the physical address can use static mapping; may be static mapping of the area should not be too large, mx6q no more than 4M ; Of the physical address, in the future access to the direct use of a fixed virtual address can be accessed; perhaps the use of static mapping can be scattered to the physical address of a centralized virtual address area, so you can reduce the virtual address space debris?
mxc_iomux_v3_init sets the virtual address corresponding to the IOMUXC register block because this physical address area has been statically mapped;
mxc_arch_reset_init sets the virtual address corresponding to the watchdog register block because the physical address area has been statically mapped;
mx6_set_cpu_type read register, get the processor model mx6sl / mx6q / mx6dl and model version 1/2/3
mxc_cpu_lp_set sets the CPU to the specified low power state; this function is used in the system power management code ;
6.init_early is not set in mx6
7.init_irq done the job
void mx6_init_irq (void)
{
       void __iomem * gpc_base = IO_ADDRESS (GPC_BASE_ADDR);
   struct irq_desc * desc;
        unsigned int i;
        gic_init (0, 29, IO_ADDRESS (IC_DISTRIBUTOR_BASE_ADDR), IO_ADDRESS (IC_INTERFACES_BASE_ADDR));
        If (enable_wait_mode) {
                   / * Mask the always pending interrupts - HW bug. * /
                   __raw_writel (0x00400000, gpc_base + 0x0c);
                   __raw_writel (0x20000000, gpc_base + 0x10);
        }
        for (i = MXC_INT_START; i <= MXC_INT_END; i ++) {
                   desc = irq_to_desc (i);
                   desc-> irq_data.chip-> irq_set_wake = mx6_gic_irq_set_wake;
        }
        mx6q_register_gpios ();
#ifdef CONFIG_CPU_FREQ_GOV_INTERACTIVE
                   for (i = 0; i <ARRAY_SIZE (mxc_irq_tuner); i ++)
                             cpufreq_gov_irq_tuner_register (mxc_irq_tuner [i]);
#endif
#ifdef CONFIG_PCI_MSI
                   imx_msi_init ();
#endif
}
gic_init do not know what it is
mx6q_register_gpios () initializes the GPIO , or can be seen here as a GPIO- driven portal, GPIO as a system prerequisite resource, need to be added in the arch when the system is added;
8.Timer to finish the work
static void __init mx6_sabresd_timer_init (void)
{
        struct clk * uart_clk;
#ifdef CONFIG_LOCAL_TIMERS
        twd_base = ioremap (LOCAL_TWD_ADDR, SZ_256);
        BUG_ON (! Twd_base);
#endif
        mx6_clocks_init (32768, 24000000, 0, 0);
        uart_clk = clk_get_sys ("imx-uart.0", NULL);
        early_console_setup (UART1_BASE_ADDR, uart_clk);
}
mx6_clocks_init can be considered a clock driver, where the completion of all peripheral controller clock initialization;
early_console_setup in the system is also required during the serial output, where quickly set the serial port UART clock? Really?
9.Init_machine done the job
In the mx53 or mx6 , or in the s3cc24xx series, init_machine do things very consistent, that is, to the kernel registration controller device ; mainly including uart , i2c , spi , GPU , IPU , fb, etc .; To add some of the equipment on the board, such as i2c equipment, curing the MMC , the network Phy chip and so on; In fact, this function is completely related to the linux driver, and I do not put it into the BSP developed;

No comments:

Post a Comment