20230126使AIO-3568J开发板在原厂Android11下跑起来

20230126使AIO-3568J开发板在原厂Android11下跑起来
2023/1/26 18:22


1、前提
2、修改dts设备树
3、适配板子的dts
4、(修改uboot)编译系统烧入固件验证

前提
因源码是直接使用原厂的SDK,没有使用firefly配套的SDK源码,所以手上这块firefly aio-3568i板子在硬计上与原厂使用的板子会有些差异;
就是因为这些差异会导致新固件烧入后,debug串口 打印许多错息,可能的话,系统还会崩溃掉,跑不起来

主要差异在哪里呢?比如:
1、DDR类型和品牌多样性;
2、电源管理PMU: RK809 PMU芯片各路输出电压不同,需要修改dts配置
3、CPU,GPU电压配置或电压域配置问题
4、GPIO控制管脚分配控制的芯片器件不同这些问题只需我们到dts 设备树上进行修改,重新适配下我们手上的aio-3568i板子


1、【临时使用可以不用修改的!^_】修改dts设备树
找当前kernel使用的是哪个dts文件先配置Android分支:
/build/envsetup.sh
lunch rk3566_r-userdebug

查找方法:
查看编译脚本用的是哪个dts文件
查看build.sh脚本,找到kernel当前使用的dts名称:


Y:\rk3568_Android11.0_ToyBrick\device\rockchip\rk356x\rk3568_r\BoardConfig.mk
PRODUCT_KERNEL_DTS := rk3568-evb1-ddr4-v10
修改为:
PRODUCT_KERNEL_DTS := rk3568-evb2-lp4x-v10


# only save the version code
SDK_VERSION=`get_build_var CURRENT_SDK_VERSION`
UBOOT_DEFCONFIG=`get_build_var PRODUCT_UBOOT_CONFIG`
KERNEL_ARCH=`get_build_var PRODUCT_KERNEL_ARCH`
KERNEL_DEFCONFIG=`get_build_var PRODUCT_KERNEL_CONFIG`
if [ "$KERNEL_DTS" = "" ] ; then
KERNEL_DTS=`get_build_var PRODUCT_KERNEL_DTS`
fi
echo "-------------------KERNEL_DTS:$KERNEL_DTS"
PACK_TOOL_DIR=RKTools/linux/Linux_Pack_Firmware
IMAGE_PATH=rockdev/Image-$TARGET_PRODUCT
export PROJECT_TOP=`gettop`

lunch $TARGET_PRODUCT-$BUILD_VARIANT


服务器shell终端输入: get_build_var PRODUCT_KERNEL_DTS
ubuntu:~/rk356x/rk356x android11$ get build var PRODUCT KERNEL DTS68-evb1-ddr4-v10
从中可知道kernel是使用rk3568-evb1-ddr4-v10.dts


可以到源码中查找:
kernel/arch/arm64/boot/dts/rk3568-evb1-ddr4-v10.dts
替换dts文件
如如果需要替换为其他名称的dts,可以到这个文件下修改
device/rockchip/rk356x/rk3568_r/BoardConfig.mk


演示:因AIO-3568J的DDR是LPDDR4,所以替换个rk3568-evb2-p4x-v10.dts
修改: device/rockchip/rk356x/rk3568_r/BoardConfig.mk
PRODUCT_UBOOT_CONFIG := rk3568
PRODUCT_KERNEL_DTS := rk3568-evb2-lp4x-v10
BOARD_GSENSOR_MXC6655XA_SUPPORT := true
BOARD_CAMERA_SUPPORT_EXT := true
BOARD_HS_ETHERNET := true

再次执行: get build_var PRODUCT_KERNEL DTS
即可看到kernel使用的dts变为rk3568-evb2-lp4x-v10.dts

rootroot@rootroot-HP-ZHAN-66-Pro-A-14-G3:~/rk3568_Android11.0_ToyBrick$ 
rootroot@rootroot-HP-ZHAN-66-Pro-A-14-G3:~/rk3568_Android11.0_ToyBrick$ get_build_var PRODUCT_KERNEL_DTS
rk3568-evb2-lp4x-v10

rootroot@rootroot-HP-ZHAN-66-Pro-A-14-G3:~/rk3568_Android11.0_ToyBrick$ 


适配板子的dts
先打开板子的原理图和位置图
嵌入式开发和学习,板子硬件的原理图和位置图PDF图纸是不可或少的哈aio-3568i-位置图背面pdf          2021/8/6 23:56
aio-3568j-位置图正面pdf          2021/8/6 23:57
MB-JM3-RK3568-V12-20210616pdf    2021/8/7 8:25


【临时使用可以不用修改的!^_但是是给WIFI和以太网RJ45供电的,长期使用可能会损害相关器件!^_】
2、因AIO-3568J板子是核心板+底板形式,firefly官方并没有开放核心板的原理图,所以dts的配置需要参考发布的Android11源码;
主要参考:IO电源域和RK809配置部分;
可看下此篇文章IO电源域和RK809知识点:
https://blog.csdn.net/soar999999/article/details/120102934

[[RK3568 Android11] 教程之IO电源域和rk809 DTS讲解
两套SDK源码对比最终的dts配置如下:
lIO电源域配置 (rk3568-evbd.tsi) :

Y:\rk3568_Android11.0_ToyBrick\kernel\arch\arm64\boot\dts\rockchip\rk3568-evb.dtsi
 /*
  * There are 10 independent IO domains in RK3566/RK3568, including PMUIO[0:2] and VCCIO[1:7].
  * 1/ PMUIO0 and PMUIO1 are fixed-level power domains which cannot be configured;
  * 2/ PMUIO2 and VCCIO1,VCCIO[3:7] domains require that their hardware power supply voltages
  *    must be consistent with the software configuration correspondingly
  *    a/ When the hardware IO level is connected to 1.8V, the software voltage configuration
  *       should also be configured to 1.8V accordingly;
  *    b/ When the hardware IO level is connected to 3.3V, the software voltage configuration
  *       should also be configured to 3.3V accordingly;
  * 3/ VCCIO2 voltage control selection (0xFDC20140)
  *    BIT[0]: 0x0: from GPIO_0A7 (default)
  *    BIT[0]: 0x1: from GRF
  *    Default is determined by Pin FLASH_VOL_SEL/GPIO0_A7:
  *    L:VCCIO2 must supply 3.3V
  *    H:VCCIO2 must supply 1.8V
  */
&pmu_io_domains {
    status = "okay";
    pmuio1-supply = <&vcc3v3_pmu>;
    pmuio2-supply = <&vcc3v3_pmu>;
    vccio1-supply = <&vccio_acodec>;
    vccio3-supply = <&vccio_sd>;
    vccio4-supply = <&vcc_1v8>;
    vccio5-supply = <&vcc_3v3>;
    vccio6-supply = <&vcc_1v8>;
    vccio7-supply = <&vcc_3v3>;
};

&pwm4 {
    status = "okay";
};

【以下完全相同:就不上源码了!】
RK809各路输出电压配置 (rk3568-evb.dtsi) :

P:\AIO-3568J\rk3568_Android11.0_ToyBrick\kernel\arch\arm64\boot\dts\rockchip\rk3568-firefly-core.dtsi


3、【经过确认:可以不用修改。虽然Firefly的rbin的版本比ToyBrick的新!^_】


编译系统烧入固件验证
DTS里IO电源域和RK809都配置好后,编译固件,烧录到板子上验证烧录后,AIO-3568J板子会大概率崩溃重启,偶尔能进入Android系统桌面

用使比较软件对比了原厂的SDK包和firefly发布的SDK包,uboot和kernel部分没看出哪里有区别;然后对firefly固件和原厂SDK编译出来的固件开机log; 发现使用的DDR配置版本不同,firely使用的的版本比较新,所以尝试更新下DDR版本:路径: 
sdk/rkbin

比较目录后,果真是有区别;
解决办法: 把firefly的rkbin目录有差异的地方都拷贝过来;
重新编译固件: ./build.sh -UKAu
修改过后,AIO-3568J板子每次开机都能稳定的运行,没有出现崩溃和重启现象;老化了一段时间,系统正常;

Y:\rk3568_Android11.0_ToyBrick\rkbin\RKBOOT\RK3566MINIALL.ini
[CHIP_NAME]
NAME=RK3568
[VERSION]
MAJOR=1
MINOR=1
[CODE471_OPTION]
NUM=1
Path1=bin/rk35/rk3566_ddr_1056MHz_v1.08.bin
Sleep=1
[CODE472_OPTION]
NUM=1
Path1=bin/rk35/rk356x_usbplug_v1.09.bin
[LOADER_OPTION]
NUM=2
LOADER1=FlashData
LOADER2=FlashBoot
FlashData=bin/rk35/rk3566_ddr_1056MHz_v1.08.bin
FlashBoot=bin/rk35/rk356x_spl_v1.11.bin
[OUTPUT]
PATH=rk356x_spl_loader_v1.08.111.bin
[SYSTEM]
NEWIDB=true
[FLAG]
471_RC4_OFF=true
RC4_OFF=true


新版本:
[CHIP_NAME]
NAME=RK3568
[VERSION]
MAJOR=1
MINOR=1
[CODE471_OPTION]
NUM=1
Path1=bin/rk35/rk3566_ddr_1056MHz_v1.09.bin
Sleep=1
[CODE472_OPTION]
NUM=1
Path1=bin/rk35/rk356x_usbplug_v1.10.bin
[LOADER_OPTION]
NUM=2
LOADER1=FlashData
LOADER2=FlashBoot
FlashData=bin/rk35/rk3566_ddr_1056MHz_v1.09.bin
FlashBoot=bin/rk35/rk356x_spl_v1.11.bin
[OUTPUT]
PATH=rk356x_spl_loader_v1.09.111.bin
[SYSTEM]
NEWIDB=true
[FLAG]
471_RC4_OFF=true
RC4_OFF=true


4、替换uboot的三个文件,重新编译uboot。刷机就可以进去了!
Y:\rk3568_Android11.0_ToyBrick\u-boot\arch\arm\mach-rockchip\board.c

#include <asm/arch/param.h>
#ifdef CONFIG_DM_CHARGE_DISPLAY
#include <power/charge_display.h>
#endif
#ifdef CONFIG_DM_DVFS
#include <dvfs.h>
#endif
#ifdef CONFIG_ROCKCHIP_IO_DOMAIN
#include <io-domain.h>
#endif
#ifdef CONFIG_DM_REGULATOR
#include <power/regulator.h>
#endif
#ifdef CONFIG_DRM_ROCKCHIP
#include <video_rockchip.h>
#endif
#ifdef CONFIG_ROCKCHIP_DEBUGGER
#include <rockchip_debugger.h>
#endif
#include <of_live.h>
#include <dm/root.h>
#include <console.h>
#include <boot_rkimg.h>

#define BLK_OFFSET_31K    62
#define ABNORMAL_BOOT_COUNT    2
static long abnormal_boot_detect(void)
{
#ifdef CONFIG_ABNORMAL_BOOT_DETECT
    long ret;
    char *buf;
    struct blk_desc *dev_desc;
    char flag;
    dev_desc = rockchip_get_bootdev();
    lbaint_t start = BLK_OFFSET_31K;

    buf = (char *)memalign(ARCH_DMA_MINALIGN, RK_BLK_SIZE);
    if(!buf) {
        printf("%s: out of memory!\n", __func__);
        return -ENOMEM;
    }

    ret = blk_dread(dev_desc, start, 1, buf);
    if(ret < 0) {
        printf("%s: failed to get abnormal boot flag, ret=%lu\n",
                __func__, ret);
        return ret;
    }

    flag = buf[0];
    if(flag < ABNORMAL_BOOT_COUNT) {
        printf("Abnormal boot count: %d\n", flag);
        flag++;
        buf[0] = flag;
        ret = blk_dwrite(dev_desc, start, 1, buf); 
    } else {
        buf[0] = 0;
        ret = blk_dwrite(dev_desc, start, 1, buf); 
        printf("Enter bootrom download...");
        mdelay(100);
        writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG);
        do_reset(NULL, 0, 0, NULL);
        printf("failed!\n");
    }

    return ret;
#else
    return 0;
#endif
}

static void board_debug_init(void)
{
    if (!gd->serial.using_pre_serial &&
        !(gd->flags & GD_FLG_DISABLE_CONSOLE))
        debug_uart_init();

    if (tstc()) {
        gd->console_evt = getc();
        if (gd->console_evt <= 0x1a) /* 'z' */
            printf("Hotkey: ctrl+%c\n", gd->console_evt + 'a' - 1);
    }

    if (IS_ENABLED(CONFIG_CONSOLE_DISABLE_CLI))
        printf("Cmd interface: disabled\n");
}

#ifdef CONFIG_MTD_BLK
static void board_mtd_blk_map_partitions(void)
{
    struct blk_desc *dev_desc;

    dev_desc = rockchip_get_bootdev();
    if (dev_desc)
        mtd_blk_map_partitions(dev_desc);
}
#endif

int board_init(void)
{
    board_debug_init();
    abnormal_boot_detect();

#ifdef DEBUG
    soc_clk_dump();
#endif

Y:\rk3568_Android11.0_ToyBrick\u-boot\arch\arm\mach-rockchip\boot_mode.c

#include <asm/arch/toybrick.h>
#include <optee_include/OpteeClientInterface.h>
#include <u-boot/sha256.h>
 

static int load_SnMacAc_from_vendor(char *sn, char *mac, char *actcode)
{
    int ret;

    memset(sn, 0, TOYBRICK_SN_LEN + 1);
    memset(mac, 0, TOYBRICK_MAC_LEN + 1);
    memset(actcode, 0, TOYBRICK_ACTCODE_LEN + 1);

    ret = toybrick_get_sn(sn);
    if (ret <= 0) {
        printf("Load sn form vendor failed\n");
        return -EIO;
    }

    ret = toybrick_get_mac(mac);
    if (ret != TOYBRICK_MAC_LEN) {
        printf("Load mac form vendor failed\n");
        return -EIO;
    }

    ret = toybrick_get_actcode(actcode);
    if (ret != TOYBRICK_ACTCODE_LEN) {
        printf("Load actcode form vendor failed\n");
        return -EIO;
    }

    printf("Load SnMacAc from vendor: sn %s, mac %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
            sn, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    return 0;
}

static int save_SnMacAc_to_vendor(char *sn, char *mac, char *actcode)
{
    int ret;

    ret = toybrick_set_sn(sn);
    if (ret <= 0) {
        printf("Save sn to vendor failed\n");
        return -EIO;
    }

    ret = toybrick_set_mac(mac);
    if (ret != TOYBRICK_MAC_LEN) {
        printf("Save mac to vendor failed\n");
        return -EIO;
    }

    ret = toybrick_set_actcode(actcode);
    if (ret != TOYBRICK_ACTCODE_LEN) {
        printf("Save actcode to vendor failed\n");
        return -EIO;
    }

    return 0;
}

static int load_SnMacAc_from_rpmb(char *sn, char *mac, char *actcode)
{
    int ret;
    sha256_context ctx;
    uint8_t digest[SHA256_SUM_LEN + 1] = {0};
    uint8_t hash_pre[SHA256_SUM_LEN + 1] = {0};
    uint8_t data_sha256[TOYBRICK_SHA_LEN + 1]={0};

    memset(sn, 0, TOYBRICK_SN_LEN + 1);
    memset(mac, 0, TOYBRICK_MAC_LEN + 1);
    memset(actcode, 0, TOYBRICK_ACTCODE_LEN + 1);
    ret = trusty_read_toybrick_SnMacAc(data_sha256, TOYBRICK_SHA_LEN);
    if (ret != 0) {
        printf("Load SnMacAc from rpmb failed\n");
        return -EIO;
    }
    memcpy(hash_pre, data_sha256, SHA256_SUM_LEN);
    sha256_starts(&ctx);
    sha256_update(&ctx,(const uint8_t *)(data_sha256 + SHA256_SUM_LEN), TOYBRICK_DATA_LEN);
    sha256_finish(&ctx, digest);
    if (memcmp(digest, hash_pre, SHA256_SUM_LEN) != 0) {
        printf("SnMacAc from rpmb is invalid\n");
        return -EINVAL;
    }
    memcpy(sn, data_sha256 + SHA256_SUM_LEN, TOYBRICK_SN_LEN);
    memcpy(mac, data_sha256 + SHA256_SUM_LEN + TOYBRICK_SN_LEN, TOYBRICK_MAC_LEN);
    memcpy(actcode, data_sha256 + SHA256_SUM_LEN + TOYBRICK_SN_LEN + TOYBRICK_MAC_LEN, TOYBRICK_ACTCODE_LEN);

    if (strlen(sn) == 0) {
        printf("SnMacAc from rpmb is empty\n");
        return -EINVAL;
    }

    printf("Load SnMacAc from rpmb: sn %s, mac %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
            sn, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    return 0;
}

static int save_SnMacAc_to_rpmb(char *sn, char *mac, char *actcode)
{
    int ret;
    sha256_context ctx;
    uint8_t digest[SHA256_SUM_LEN + 1] = {0};
    uint8_t data[TOYBRICK_DATA_LEN + 1]={0};
    uint8_t data_sha256[TOYBRICK_SHA_LEN + 1]={0};

    memset(&data, 0, sizeof(data));
    memset(&data_sha256, 0, sizeof(data_sha256));
    memcpy(data, sn, TOYBRICK_SN_LEN);
    memcpy(data + TOYBRICK_SN_LEN, mac, TOYBRICK_MAC_LEN);
    memcpy(data + TOYBRICK_SN_LEN + TOYBRICK_MAC_LEN, actcode, TOYBRICK_ACTCODE_LEN);

    sha256_starts(&ctx);
    sha256_update(&ctx,(const uint8_t *)data, TOYBRICK_DATA_LEN);
    sha256_finish(&ctx, digest);
    memcpy(data_sha256, digest, SHA256_SUM_LEN);
    memcpy(data_sha256 + SHA256_SUM_LEN, data, TOYBRICK_DATA_LEN);
    
    ret = trusty_write_toybrick_SnMacAc(data_sha256, TOYBRICK_SHA_LEN);
    if (ret != 0) {
        printf("Save SnMacAc to rpmb failed\n");
        return -EIO;
    }

    return 0;
}

static int toybrick_check_SnMacAc(void)
{
    int ret = 0;
    int ret_vendor, ret_rpmb;
    char vendor_sn[TOYBRICK_SN_LEN + 1];
    char vendor_mac[TOYBRICK_MAC_LEN + 1];
    char vendor_actcode[TOYBRICK_ACTCODE_LEN + 1];
    char rpmb_sn[TOYBRICK_SN_LEN + 1];
    char rpmb_mac[TOYBRICK_MAC_LEN + 1];
    char rpmb_actcode[TOYBRICK_ACTCODE_LEN + 1];

    ret_vendor = load_SnMacAc_from_vendor(vendor_sn, vendor_mac, vendor_actcode);
    ret_rpmb = load_SnMacAc_from_rpmb(rpmb_sn, rpmb_mac, rpmb_actcode);

    if (ret_vendor < 0 && ret_rpmb < 0) {
        printf("No SnMacAc found in vendor and rpmb, goto loader ...\n");
        run_command_list("rockusb 0 ${devtype} ${devnum}", -1, 0);
        //set_back_to_bootrom_dnl_flag();
        do_reset(NULL, 0, 0, NULL);
    } else if (ret_vendor < 0) {
        printf("No SnMacAc found in vendor, load from rpmb and save to vendor\n");
        ret = save_SnMacAc_to_vendor(rpmb_sn, rpmb_mac, rpmb_actcode);
        do_reset(NULL, 0, 0, NULL);
    } else if (ret_rpmb < 0) {
        printf("No SnMacAc found in rpmb, load from vendor and save to rpmb\n");
        ret = save_SnMacAc_to_rpmb(vendor_sn, vendor_mac, vendor_actcode);
    } else if (memcmp(vendor_sn, rpmb_sn, TOYBRICK_SN_LEN) != 0){
        printf("Warn: SN(%s %s) form vendor and rpmb is different!\n",
                vendor_sn, rpmb_sn);
        ret = save_SnMacAc_to_vendor(rpmb_sn, rpmb_mac, rpmb_actcode);
        do_reset(NULL, 0, 0, NULL);
    } else if (memcmp(vendor_mac, rpmb_mac, TOYBRICK_MAC_LEN) != 0){
        printf("Warn: MAC form vendor and rpmb is different!\n");
        ret = save_SnMacAc_to_vendor(rpmb_sn, rpmb_mac, rpmb_actcode);
        do_reset(NULL, 0, 0, NULL);
    } else if (memcmp(vendor_actcode, rpmb_actcode, TOYBRICK_ACTCODE_LEN) != 0){
        printf("Warn: Actcode form vendor and rpmb is different!\n");
        ret = save_SnMacAc_to_vendor(rpmb_sn, rpmb_mac, rpmb_actcode);
        do_reset(NULL, 0, 0, NULL);
    } else {
        printf("Toybrick check SnMacAc OK, sn %s\n", vendor_sn);
        ret = 0;
    }

    return ret;
}

int setup_boot_mode(void)
{
    char env_preboot[256] = {0};
#ifndef CONFIG_ROCKCHIP_RK3288
    toybrick_check_SnMacAc();
#endif
    switch (rockchip_get_boot_mode()) {
    case BOOT_MODE_BOOTLOADER:
        printf("enter fastboot!\n");
#if defined(CONFIG_FASTBOOT_FLASH_MMC_DEV)
        snprintf(env_preboot, 256,
                "setenv preboot; mmc dev %x; fastboot usb 0; ",
                CONFIG_FASTBOOT_FLASH_MMC_DEV);
#elif defined(CONFIG_FASTBOOT_FLASH_NAND_DEV)
        snprintf(env_preboot, 256,
                "setenv preboot; fastboot usb 0; ");
#endif

Y:\rk3568_Android11.0_ToyBrick\u-boot\arch\arm\mach-rockchip\boot_rkimg.c

#include <asm/arch/uimage.h>
#include <asm/arch/toybrick.h>
#include <dm/ofnode.h>

#define KEY_DOWN_MIN_VAL    0
#define KEY_DOWN_MAX_VAL    30

__weak int rockchip_dnl_key_pressed(void)
{
#if defined(CONFIG_DM_KEY)
#ifdef CONFIG_CMD_ROCKUSB
    return key_is_pressed(key_read(KEY_VOLUMEUP));
#else
    return key_is_pressed(key_read(KEY_MENU));
#endif

#elif defined(CONFIG_ADC)
    const void *blob = gd->fdt_blob;
    int node, ret, channel = 1;
    u32 val, chns[2];

    node = fdt_node_offset_by_compatible(blob, 0, "adc-keys");
    if (node >= 0) {
        if (!fdtdec_get_int_array(blob, node, "io-channels", chns, 2))
            channel = chns[1];
    }

    ret = adc_channel_single_shot("saradc", channel, &val);
    if (ret) {
        printf("%s: Failed to read saradc, ret=%d\n", __func__, ret);
        return 0;
    }

    return ((val >= KEY_DOWN_MIN_VAL) && (val <= KEY_DOWN_MAX_VAL));
#endif

    return 0;
}


#if defined(CONFIG_ROCKCHIP_EARLY_DISTRO_DTB)
static int rockchip_read_distro_dtb(void *fdt_addr)
{
    const char *cmd = "part list ${devtype} ${devnum} -bootable devplist";
    char *devnum, *devtype, *devplist;
    char devnum_part[12];
    char fdt_hex_str[19];
    char *fs_argv[5];
    char flag[TOYBRICK_FLAG_LEN + 1];
    char dtb_path[128];
    int index = -1;
    //int size;
    //int ret;

    if (!rockchip_get_bootdev() || !fdt_addr)
        return -ENODEV;

    if (run_command_list(cmd, -1, 0)) {
        printf("Failed to find -bootable\n");
        return -EINVAL;
    }

    devplist = env_get("devplist");
    if (!devplist)
        return -ENODEV;

    devtype = env_get("devtype");
    devnum = env_get("devnum");
    sprintf(devnum_part, "%s:%s", devnum, devplist);
    sprintf(fdt_hex_str, "0x%lx", (ulong)fdt_addr);

    fs_argv[0] = "load";
    fs_argv[1] = devtype,
    fs_argv[2] = devnum_part;
    fs_argv[3] = fdt_hex_str;

    if(toybrick_get_flag(flag, &index) < 0)
        strcpy(dtb_path, CONFIG_ROCKCHIP_EARLY_DISTRO_DTB_PATH);
    else
        sprintf(dtb_path, "%s.%s", CONFIG_ROCKCHIP_EARLY_DISTRO_DTB_PATH, flag);
    fs_argv[4] = dtb_path;

    if (do_load(NULL, 0, 5, fs_argv, FS_TYPE_ANY))
        return -EIO;

    if (fdt_check_header(fdt_addr))
        return -EBADF;

    printf("DTB(Distro): %s\n", dtb_path);

    return 0;
}
#endif


参考资料:
https://blog.csdn.net/soar999999/article/details/120102401
[RK3568 Android11] 教程之原厂SDK源码适配AIO-3568J板子跑起来

https://t.rock-chips.com/wiki.php
ToyBrick
前言
本站旨在高效地知识分享--所见即所得。
让Toybrick板用户能够快速上手,利用Toybrick系列开发板快速开发、评估以及产品化。

https://t.rock-chips.com/wiki.php?filename=%E6%9D%BF%E7%BA%A7%E6%8C%87%E5%8D%97/TB-RK3568X
TB-RK3568X

https://t.rock-chips.com/wiki.php?filename=%E8%B5%84%E6%96%99%E4%B8%8B%E8%BD%BD/%E8%B5%84%E6%96%99%E4%B8%8B%E8%BD%BD
Android源码下载
Android源码下载地址
https://eyun.baidu.com-s/3c2U4Y7A#sharelink/path=%2F

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值