QNX調試筆記[IMX6Q/TQIMX6Q]---SD啓動卡製作

author:tianming1992
E-mail: [email protected]

採用QNX7.0和sabreARD BSP,主要工作在於製作bootloader。

1.IPL製作

IPL時QNX特有的bootloader,類似於u-boot。
mx6x BSP的IPL代碼位於src/ipl/boards/mx6x-sabreARD目錄下,觀察其main函數,基本可以理解爲一個裸奔的單片機程序,作用是初始化串口,SD卡,比通過讀取SD卡文件,將系統鏡像讀入內存中,並最終將控制權交給鏡像的start-up模塊。

int main()
{
    unsigned image = QNX_LOAD_ADDR;


    init_aips();

    init_clocks();

    init_regulator_settings();

    if ( get_imx6_type() == MX6_CHIP_TYPE_QUAD_OR_DUAL)
    {
        if ( get_imx6_rev() == MX6_CHIP_REV_2_0 )
        {
            //DDR配置相關
            apply_mx6_sdl_dcd_values((unsigned long) &dcd_hdr_quadplus);
        }
        else
        {
            apply_mx6_sdl_dcd_values((unsigned long) &dcd_hdr_quad);
        }

        //pin mux set!! 引腳配置
        init_pinmux_quad_dual();
    }
    else if (get_imx6_type() == MX6_CHIP_TYPE_DUAL_LITE_OR_SOLO)
    {
        apply_mx6_sdl_dcd_values((unsigned long) &dcd_hdr_solo);
        init_pinmux_dual_lite_solo();
    }
    else
    {
        apply_mx6_sdl_dcd_values((unsigned long) &dcd_hdr_quad);
        init_pinmux_quad_dual();
    }

    /* Init serial interface 串口配置*/
    init_serial_mx6x();

    ser_putstr("\nQNX Neutrino Initial Program Loader for the NXP i.MX6 Quad/Dual/DualLite/Solo/QuadPlus Sabre-ARD RevB (ARM Cortex-A9 MPCore)\n");
    ser_putstr("BeiJing Leadgen.AI\n");

    if ( get_imx6_type() == MX6_CHIP_TYPE_QUAD_OR_DUAL)
    {
        if ( get_imx6_rev() == MX6_CHIP_REV_2_0)
        {
            ser_putstr("\ni.MX6 Quad Plus CPU detected.\n\n");
        }
        else
        {
            ser_putstr("\ni.MX6 Quad or Dual CPU detected.\n\n");
        }
    }
    else if (get_imx6_type() == MX6_CHIP_TYPE_DUAL_LITE_OR_SOLO)
    {
        ser_putstr("\ni.MX6 Dual Lite or Solo CPU detected.\n\n");
    }
    else
    {
        ser_putstr("\ni.MX6 unknown CPU type.\n\n");
        ser_putstr("CHIP ID = ");
        ser_puthex(get_imx6_type());
    }

    ser_putstr("SDMMC download...\n");
            if (sdmmc_load_file(image, "QNX-IFS") == 0) {
                ser_putstr("load image done.\n");
                /* Proceed to image scan */
        image = image_scan(image, image + 0x200);

        if (image != 0xffffffff) {
            ser_putstr("Found image               @ 0x");
            ser_puthex(image);
            ser_putstr("\n");
            image_setup(image);

            ser_putstr("Jumping to startup        @ 0x");
            ser_puthex(startup_hdr.startup_vaddr);
            ser_putstr("\n\n");
            image_start(image);

            /* Never reach here */
            return 0;
        }


        }





    while (1) {
        ser_putstr("Command:\n");
        ser_putstr("Press 'D' for serial download, using the 'sendnto' utility\n");
        ser_putstr("Press 'M' for SDMMC download, IFS filename MUST be 'QNX-IFS'.\n");
        switch (ser_getchar()) {
        case 'D':
        case 'd':
            ser_putstr("send image now...\n");
            if (image_download_ser(image)) {
                ser_putstr("download failed...\n");
                continue;
            }
            else
                ser_putstr("download OK...\n");
            break;
        case 'M':
        case 'm':
            ser_putstr("SDMMC download...\n");
            if (sdmmc_load_file(image, "QNX-IFS") == 0) {
                ser_putstr("load image done.\n");
                /* Proceed to image scan */
                break;
            }
            else
            {
                ser_putstr("Load image failed.\n");
                continue;
            }
        default:
            ser_putstr("Unknown command.\n");
            continue;
        }

        image = image_scan(image, image + 0x200);

        if (image != 0xffffffff) {
            ser_putstr("Found image               @ 0x");
            ser_puthex(image);
            ser_putstr("\n");
            image_setup(image);

            ser_putstr("Jumping to startup        @ 0x");
            ser_puthex(startup_hdr.startup_vaddr);
            ser_putstr("\n\n");
            image_start(image);

            /* Never reach here */
            return 0;
        }

        ser_putstr("Image_scan failed...\n");
    }

    return 0;
}

對於IPL移植,最重要的在引腳配置部分,根據TQIMX6Q原理圖,修改如下

init_pinmux_quad_dual()
{
       //tqimx6 -----uart1-------------------------
    //tx
    set_mux_cfg(SWMUX_SD3_DAT7, MUX_CTL_MUX_MODE_ALT1);
    set_pad_cfg(SWPAD_SD3_DAT7, MX6Q_PAD_SETTINGS_UART);
    set_pin_as_input(SWINPUT_UART1_IPP_UART_RXD_MUX, 0x02);
    //RX
    set_mux_cfg(SWMUX_SD3_DAT6, MUX_CTL_MUX_MODE_ALT1);
    set_pad_cfg(SWPAD_SD3_DAT6, MX6Q_PAD_SETTINGS_UART);
    set_pin_as_input(SWINPUT_UART1_IPP_UART_RXD_MUX, 0x03);
    //cts
    set_mux_cfg(SWMUX_EIM_D19, MUX_CTL_MUX_MODE_ALT4);
    set_pad_cfg(SWPAD_EIM_D19, MX6Q_PAD_SETTINGS_UART);
    set_pin_as_input(SWINPUT_UART1_IPP_UART_RTS_B, 0x00);
    //rts
    set_mux_cfg(SWMUX_EIM_D20, MUX_CTL_MUX_MODE_ALT4);
    set_pad_cfg(SWPAD_EIM_D20, MX6Q_PAD_SETTINGS_UART);
    set_pin_as_input(SWINPUT_UART1_IPP_UART_RTS_B, 0x01);
}

    /* SD2 CLK */
    set_mux_cfg(SWMUX_SD2_CLK, MUX_CTL_MUX_MODE_ALT0);
    set_pad_cfg(SWPAD_SD2_CLK, MX6Q_PAD_SETTINGS_USDHC);

    /* SD1 CMD */
    set_mux_cfg(SWMUX_SD2_CMD, MUX_CTL_MUX_MODE_ALT0 | MUX_CTL_SION);
    set_pad_cfg(SWPAD_SD2_CMD, MX6Q_PAD_SETTINGS_USDHC);

    /* SD1 DAT0 */
    set_mux_cfg(SWMUX_SD2_DAT0, MUX_CTL_MUX_MODE_ALT0);
    set_pad_cfg(SWPAD_SD2_DAT0, MX6Q_PAD_SETTINGS_USDHC);

    /* SD1 DAT1 */
    set_mux_cfg(SWMUX_SD2_DAT1, MUX_CTL_MUX_MODE_ALT0);
    set_pad_cfg(SWPAD_SD2_DAT1, MX6Q_PAD_SETTINGS_USDHC);

    /* SD1 DAT2 */
    set_mux_cfg(SWMUX_SD2_DAT2, MUX_CTL_MUX_MODE_ALT0);
    set_pad_cfg(SWPAD_SD2_DAT2, MX6Q_PAD_SETTINGS_USDHC);

    /* SD1 DAT3 */
    set_mux_cfg(SWMUX_SD2_DAT3, MUX_CTL_MUX_MODE_ALT0);
    set_pad_cfg(SWPAD_SD2_DAT3, MX6Q_PAD_SETTINGS_USDHC);

    /* SD2 Card Detect - configure GPIO4[1] as an input */
    set_mux_cfg(SWMUX_GPIO_4, MUX_CTL_MUX_MODE_ALT5);
    out32(MX6X_GPIO4_BASE + MX6X_GPIO_GDIR, in32(MX6X_GPIO4_BASE + MX6X_GPIO_GDIR) & ~(1<<1));

    /* SD2 Write Protect - configure GPIO5[20] as an input */
    set_mux_cfg(SWMUX_GPIO_2, MUX_CTL_MUX_MODE_ALT5);
    out32(MX6X_GPIO2_BASE + MX6X_GPIO_GDIR, in32(MX6X_GPIO2_BASE + MX6X_GPIO_GDIR) & ~(1<<20));

此外,串口配置的宏也要更改

#define MXC_CONSOLE_BASE       MX6X_UART1_BASE

SD卡部分類似。

2.SD卡燒寫

這個部分都是通用的,製作一張FAT32的活動主分區SD卡,利用

 sudo dd if=ipl-mx6q-sabresmart.bin of=/dev/sdd bs=512 seek=2
skip=2

將IPL寫入SD中即可。

3.其他坑

在前面改IPL源碼的時候,發現不管怎麼改,最終生成的IPL竟然時一樣的,最終發現這個BSP根目錄下的makefile竟然遺漏了make install,如下:

install: $(if $(wildcard prebuilt/*),prebuilt)
        $(MAKE) -Csrc hinstall
        $(MAKE) -Csrc 

增加install後,總算正常了:

install: $(if $(wildcard prebuilt/*),prebuilt)
        $(MAKE) -Csrc hinstall
        $(MAKE) -Csrc install

結結實實被QNX工程師坑了一把。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章