mirror of
https://github.com/Fishwaldo/OBLFR.git
synced 2025-03-15 11:21:23 +00:00
Initial Commit
This commit is contained in:
commit
cbd884c217
47 changed files with 18466 additions and 0 deletions
64
README.md
Normal file
64
README.md
Normal file
|
@ -0,0 +1,64 @@
|
|||
# OpenBouffalo Firmware Repository
|
||||
|
||||
This is a collection of Firmware/Example Applications for the Bouffalo Range of Chips utilizing the [Bouffalo MCU SDK](https://github.com/bouffalolab/bl_mcu_sdk/)
|
||||
|
||||
|
||||
## Quick Start
|
||||
For Pine64 OX64 Dev Board:
|
||||
```
|
||||
mkdir obfr && cd obfr
|
||||
git clone https://github.com/XXX
|
||||
git clone https://github.com/bouffalolab/bl_mcu_sdk.git
|
||||
git clone git@gitee.com:bouffalolab/toolchain_gcc_t-head_linux.git
|
||||
PATH=$PATH:<directory to toolchain_gcc_t-head_linux>/bin/
|
||||
cd XXX/apps/helloworld
|
||||
make
|
||||
```
|
||||
Then use BLDevCube to Flash the build/build_out/helloworld_m0.elf to your device
|
||||
|
||||
## Directory Layout
|
||||
* apps/
|
||||
* Applications
|
||||
* components/
|
||||
* Useful Libraries ported to the Boufallo Range of Chips
|
||||
* cmake/
|
||||
* Support Files for CMake/Make and Kconfig
|
||||
* bsp/
|
||||
* Board Support Packages for different boards using the Bouffalo Range of Chips
|
||||
* tools/
|
||||
* Various Tools
|
||||
|
||||
## Included Apps
|
||||
* HelloWorld
|
||||
* LowLoad
|
||||
* lowload firmware is used to assist Linux to boot on the BL808 Device. Please consult the [OpenBouffalo Buildroot repo](https://github.com/openbouffalo/buildroot_bouffalo) for more information
|
||||
|
||||
|
||||
## Configuring SDK Features
|
||||
|
||||
The Bouffalo SDK provides numerous configuration options, enabled via the proj.conf in a standard bl_mcu_sdk project. This repository has enabled menuconfig, to give a graphical interface to enable/disable features in the SDK. You can enter the configuration dialog by running
|
||||
```make config``` in each applications directory.
|
||||
|
||||
Default Configuration Options for a application are saved in ```sdkconfig.default```, and when a project is built, a ```sdkconfig``` is created (and may be edited by hand, or updated with ```make config```).
|
||||
```build/config/sdkconfig.h``` header file is also created when compiling, and any configuration options that affect cmake are placed into ```proj.conf```
|
||||
|
||||
If a Application has a specific configuration options, a ```Kconfig``` file can be placed in the root of the application directory and it will be picked up automatically
|
||||
|
||||
*If you wish to help out, updating the [cmake/Kconfig](cmake/Kconfig) with additional/new options or help text is greatly appreciated*
|
||||
|
||||
## Specifying Different CPU's or Cores
|
||||
|
||||
This SDK still respects the following commands to specify different CPU's/cores etc:
|
||||
```
|
||||
make CHIP=chip_name BOARD=board_name CPU_ID=d0
|
||||
```
|
||||
Please ensure you run ```make clean``` and remove the sdkconfig file if you change chips/boards or CPU's
|
||||
|
||||
## Specify Location of the Bouffalo Labs MCU SDK
|
||||
|
||||
If your bl_mcu_sdk located in different path, then the following will work:
|
||||
```BL_SDK_BASE=<path> make```
|
||||
|
||||
## Board Support
|
||||
We have started to write a board support package for the Pine64 OX64 in bsp/ox64. This is WIP. Other Boards are welcome
|
||||
|
27
apps/d0_lowload/CMakeLists.txt
Normal file
27
apps/d0_lowload/CMakeLists.txt
Normal file
|
@ -0,0 +1,27 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
include(proj.conf)
|
||||
|
||||
# Get SDK path
|
||||
if(NOT SDK_PATH)
|
||||
get_filename_component(SDK_PATH ../../ ABSOLUTE)
|
||||
if(EXISTS $ENV{MY_SDK_PATH})
|
||||
set(SDK_PATH $ENV{MY_SDK_PATH})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check SDK Path
|
||||
if(NOT EXISTS ${SDK_PATH})
|
||||
message(FATAL_ERROR "SDK path Error, Please set SDK_PATH or MY_SDK_PATH variable")
|
||||
endif()
|
||||
|
||||
include(${SDK_PATH}/cmake/bflbsdk.cmake)
|
||||
|
||||
target_sources(app PRIVATE
|
||||
src/rv32i_xtheade_lz4.S)
|
||||
|
||||
target_compile_options(app PRIVATE -ggdb -Os)
|
||||
|
||||
sdk_set_main_file(src/main.c)
|
||||
sdk_set_linker_script(bl808_flash_d0.ld)
|
||||
project(d0_lowload)
|
5
apps/d0_lowload/Makefile
Normal file
5
apps/d0_lowload/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
PINE64_SDK_PATH := $(realpath $(dir $(realpath $(lastword $(MAKEFILE_LIST))))../../)
|
||||
|
||||
CPU_ID = d0
|
||||
|
||||
include $(PINE64_SDK_PATH)/cmake/project.build
|
256
apps/d0_lowload/bl808_flash_d0.ld
Normal file
256
apps/d0_lowload/bl808_flash_d0.ld
Normal file
|
@ -0,0 +1,256 @@
|
|||
/****************************************************************************************
|
||||
* @file flash.ld
|
||||
*
|
||||
* @brief This file is the link script file (gnuarm or armgcc).
|
||||
*
|
||||
* Copyright (C) BouffaloLab 2021
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
/* configure the CPU type */
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
/* link with the standard c library */
|
||||
INPUT(-lc)
|
||||
/* link with the standard GCC library */
|
||||
INPUT(-lgcc)
|
||||
/* configure the entry point */
|
||||
ENTRY(__start)
|
||||
|
||||
StackSize = 0x0400; /* 1KB */
|
||||
HeapMinSize = 0x1000; /* 4KB */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
xip_memory (rx) : ORIGIN = 0x58000000, LENGTH = 1M
|
||||
itcm_memory (rx) : ORIGIN = 0x3effc000, LENGTH = 17K
|
||||
dtcm_memory (rx) : ORIGIN = 0x3f000400, LENGTH = 4K
|
||||
nocache_ram_memory (!rx) : ORIGIN = 0x3ef80000, LENGTH = 0K
|
||||
ram_memory (!rx) : ORIGIN = 0x3ef80000, LENGTH = 32K
|
||||
xram_memory (!rx) : ORIGIN = 0x40000000, LENGTH = 16K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__text_code_start__ = .;
|
||||
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
|
||||
/* section information for shell */
|
||||
. = ALIGN(8);
|
||||
__fsymtab_start = .;
|
||||
KEEP(*(FSymTab))
|
||||
__fsymtab_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
__vsymtab_start = .;
|
||||
KEEP(*(VSymTab))
|
||||
__vsymtab_end = .;
|
||||
|
||||
/*put .rodata**/
|
||||
*(EXCLUDE_FILE( *bl808_glb*.o* \
|
||||
*bl808_glb_gpio*.o* \
|
||||
*bl808_pds*.o* \
|
||||
*bl808_aon*.o* \
|
||||
*bl808_hbn*.o* \
|
||||
*bl808_l1c*.o* \
|
||||
*bl808_common*.o* \
|
||||
*bl808_clock*.o* \
|
||||
*bl808_ef_ctrl*.o* \
|
||||
*bl808_sf_cfg*.o* \
|
||||
*bl808_sf_ctrl*.o* \
|
||||
*bl808_sflash*.o* \
|
||||
*bl808_xip_sflash*.o* \
|
||||
*bl808_romapi_patch*.o* ) .rodata*)
|
||||
|
||||
*(.srodata)
|
||||
*(.srodata.*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__text_code_end__ = .;
|
||||
} > xip_memory
|
||||
|
||||
. = ALIGN(4);
|
||||
__itcm_load_addr = .;
|
||||
|
||||
.itcm_region : AT (__itcm_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__tcm_code_start__ = .;
|
||||
|
||||
*(.tcm_code.*)
|
||||
*(.tcm_const.*)
|
||||
*(.sclock_rlt_code.*)
|
||||
*(.sclock_rlt_const.*)
|
||||
|
||||
*bl808_glb*.o*(.rodata*)
|
||||
*bl808_glb_gpio*.o*(.rodata*)
|
||||
*bl808_pds*.o*(.rodata*)
|
||||
*bl808_aon*.o*(.rodata*)
|
||||
*bl808_hbn*.o*(.rodata*)
|
||||
*bl808_l1c*.o*(.rodata*)
|
||||
*bl808_common*.o*(.rodata*)
|
||||
*bl808_clock*.o*(.rodata*)
|
||||
*bl808_ef_ctrl*.o*(.rodata*)
|
||||
*bl808_sf_cfg*.o*(.rodata*)
|
||||
*bl808_sf_ctrl*.o*(.rodata*)
|
||||
*bl808_sflash*.o*(.rodata*)
|
||||
*bl808_xip_sflash*.o*(.rodata*)
|
||||
*bl808_romapi_patch*.o*(.rodata*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__tcm_code_end__ = .;
|
||||
} > itcm_memory
|
||||
|
||||
__dtcm_load_addr = __itcm_load_addr + SIZEOF(.itcm_region);
|
||||
|
||||
.dtcm_region : AT (__dtcm_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__tcm_data_start__ = .;
|
||||
|
||||
*(.tcm_data)
|
||||
/* *finger_print.o(.data*) */
|
||||
|
||||
. = ALIGN(4);
|
||||
__tcm_data_end__ = .;
|
||||
} > dtcm_memory
|
||||
|
||||
/*************************************************************************/
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (NOLOAD):
|
||||
{
|
||||
. = ALIGN(0x4);
|
||||
. = . + StackSize;
|
||||
. = ALIGN(0x4);
|
||||
} > dtcm_memory
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(dtcm_memory) + LENGTH(dtcm_memory);
|
||||
PROVIDE( __freertos_irq_stack_top = __StackTop);
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __tcm_data_end__, "region RAM overflowed with stack")
|
||||
/*************************************************************************/
|
||||
__nocache_ram_load_addr = __dtcm_load_addr + SIZEOF(.dtcm_region);
|
||||
|
||||
.nocache_ram_region (NOLOAD) : AT (__nocache_ram_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__nocache_ram_data_start__ = .;
|
||||
|
||||
*(.nocache_ram)
|
||||
|
||||
. = ALIGN(4);
|
||||
__nocache_ram_data_end__ = .;
|
||||
} > nocache_ram_memory
|
||||
|
||||
__system_ram_load_addr = __nocache_ram_load_addr + SIZEOF(.nocache_ram_region);
|
||||
|
||||
.system_ram_data_region : AT (__system_ram_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__system_ram_data_start__ = .;
|
||||
|
||||
*(.system_ram)
|
||||
|
||||
. = ALIGN(4);
|
||||
__system_ram_data_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
.system_ram_noinit_data_region (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.system_ram_noinit)
|
||||
|
||||
. = ALIGN(4);
|
||||
} > ram_memory
|
||||
|
||||
__ram_load_addr = __system_ram_load_addr + SIZEOF(.system_ram_data_region);
|
||||
|
||||
/* Data section */
|
||||
RAM_DATA : AT (__ram_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__ram_data_start__ = .;
|
||||
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__ram_data_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
__etext_final = (__ram_load_addr + SIZEOF (RAM_DATA));
|
||||
ASSERT(__etext_final <= ORIGIN(xip_memory) + LENGTH(xip_memory), "code memory overflow")
|
||||
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
|
||||
*(.bss*)
|
||||
*(.sbss*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
.noinit_data (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__noinit_data_start__ = .;
|
||||
|
||||
*(.noinit_data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__noinit_data_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
.nocache_noinit_ram_region (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__nocache_ram_data_start__ = .;
|
||||
|
||||
*(.nocache_noinit_ram)
|
||||
|
||||
. = ALIGN(4);
|
||||
__nocache_ram_data_end__ = .;
|
||||
} > nocache_ram_memory
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__HeapBase = .;
|
||||
|
||||
/*__end__ = .;*/
|
||||
/*end = __end__;*/
|
||||
KEEP(*(.heap*))
|
||||
|
||||
. = ALIGN(4);
|
||||
__HeapLimit = .;
|
||||
} > ram_memory
|
||||
|
||||
__HeapLimit = ORIGIN(ram_memory) + LENGTH(ram_memory);
|
||||
ASSERT(__HeapLimit - __HeapBase >= HeapMinSize, "heap region overflow")
|
||||
|
||||
}
|
||||
|
6
apps/d0_lowload/sdkconfig.default
Normal file
6
apps/d0_lowload/sdkconfig.default
Normal file
|
@ -0,0 +1,6 @@
|
|||
CONFIG_PSRAM=y
|
||||
CONFIG_BFLB_CHIP="bl808"
|
||||
CONFIG_BLFB_CPU_ID="d0"
|
||||
CONFIG_ROMAPI=y
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_LEVEL=3
|
190
apps/d0_lowload/src/main.c
Normal file
190
apps/d0_lowload/src/main.c
Normal file
|
@ -0,0 +1,190 @@
|
|||
/**
|
||||
* @file main.c
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2022 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <rv_pmp.h>
|
||||
#include <log.h>
|
||||
#include <csi_core.h>
|
||||
#include <bflb_uart.h>
|
||||
#include <bflb_gpio.h>
|
||||
|
||||
extern void unlz4(const void *aSource, void *aDestination, uint32_t FileLen);
|
||||
|
||||
#define PSRAM_BASIC_ADDR 0x50000000
|
||||
#define VRAM_BASIC_ADDR 0x3f008000
|
||||
|
||||
#define VM_LINUX_SRC_ADDR 0x580A0000 // 4M 3980268
|
||||
#define VM_LINUX_DST_ADDR 0x50000000
|
||||
|
||||
#define OPENSBI_SRC_ADDR 0x58090000 // 64K 0xc000
|
||||
#define OPENSBI_DST_ADDR 0x3eff0000
|
||||
|
||||
#define DTB_SRC_ADDR 0x58080000 // 64k
|
||||
#define DTB_DST_ADDR 0x51ff8000
|
||||
|
||||
static struct bflb_device_s *uart0;
|
||||
|
||||
#if (__riscv_xlen == 64)
|
||||
/* linux pmp setting */
|
||||
const pmp_config_entry_t pmp_entry_tab[8] = {
|
||||
[0] = {
|
||||
.entry_flag = ENTRY_FLAG_ADDR_NAPOT | ENTRY_FLAG_PERM_W | ENTRY_FLAG_PERM_R,
|
||||
.entry_pa_base = 0x20000000,
|
||||
.entry_pa_length = PMP_REG_SZ_1M,
|
||||
},
|
||||
|
||||
[1] = {
|
||||
.entry_flag = ENTRY_FLAG_ADDR_NAPOT | ENTRY_FLAG_PERM_W | ENTRY_FLAG_PERM_R,
|
||||
.entry_pa_base = 0x30000000,
|
||||
.entry_pa_length = PMP_REG_SZ_1M,
|
||||
},
|
||||
|
||||
[2] = {
|
||||
.entry_flag = ENTRY_FLAG_ADDR_NAPOT | ENTRY_FLAG_PERM_X | ENTRY_FLAG_PERM_W | ENTRY_FLAG_PERM_R,
|
||||
.entry_pa_base = 0x3eff0000,
|
||||
.entry_pa_length = 0x10000,
|
||||
},
|
||||
|
||||
[3] = {
|
||||
.entry_flag = ENTRY_FLAG_ADDR_NAPOT | ENTRY_FLAG_PERM_X | ENTRY_FLAG_PERM_W | ENTRY_FLAG_PERM_R,
|
||||
.entry_pa_base = 0x40000000,
|
||||
.entry_pa_length = PMP_REG_SZ_16K,
|
||||
},
|
||||
|
||||
[4] = {
|
||||
.entry_flag = ENTRY_FLAG_ADDR_NAPOT | ENTRY_FLAG_PERM_X | ENTRY_FLAG_PERM_W | ENTRY_FLAG_PERM_R,
|
||||
.entry_pa_base = 0x50000000,
|
||||
.entry_pa_length = 0x4000000,
|
||||
},
|
||||
|
||||
[5] = {
|
||||
.entry_flag = ENTRY_FLAG_ADDR_NAPOT | ENTRY_FLAG_PERM_W | ENTRY_FLAG_PERM_R,
|
||||
.entry_pa_base = 0x58000000,
|
||||
.entry_pa_length = 0x4000000,
|
||||
},
|
||||
|
||||
[6] = {
|
||||
.entry_flag = ENTRY_FLAG_ADDR_NAPOT | ENTRY_FLAG_PERM_W | ENTRY_FLAG_PERM_R,
|
||||
.entry_pa_base = 0xe0000000,
|
||||
.entry_pa_length = 0x8000000,
|
||||
},
|
||||
|
||||
[7] = {
|
||||
.entry_flag = ENTRY_FLAG_ADDR_TOR,
|
||||
.entry_pa_base = 0xffffffffff, /* 40-bit PA */
|
||||
.entry_pa_length = 0,
|
||||
},
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void linux_load()
|
||||
{
|
||||
LOG_I("linux load start... \r\n");
|
||||
uint32_t *pSrc, *pDest;
|
||||
uint32_t header_kernel_len = 0;
|
||||
header_kernel_len = *(volatile uint32_t *)(VM_LINUX_SRC_ADDR - 4);
|
||||
/* Copy and unlz4 vm linux code */
|
||||
LOG_I("len:0x%08x\r\n", header_kernel_len);
|
||||
__DMB();
|
||||
|
||||
unlz4((const void *)VM_LINUX_SRC_ADDR, (void *)VM_LINUX_DST_ADDR, header_kernel_len /*3980268*/ /*3993116 v0.3.0*/ /*4010168*/);
|
||||
|
||||
/* let's start */
|
||||
/* there are 7bytes file head that lz4d HW IP does not need, skip! */
|
||||
// LZ4D_Decompress((const void *)(VM_LINUX_SRC_ADDR + 7), (void *)VM_LINUX_DST_ADDR);
|
||||
|
||||
/* method 1: wait when done */
|
||||
// while (!LZ4D_GetStatus(LZ4D_STATUS_DONE))
|
||||
// ;
|
||||
// __ISB();
|
||||
LOG_I("vm linux load done!\r\n");
|
||||
|
||||
/* Copy dtb code */
|
||||
pSrc = (uint32_t *)DTB_SRC_ADDR;
|
||||
pDest = (uint32_t *)DTB_DST_ADDR;
|
||||
memcpy((void *)pDest, (void *)pSrc, 0x10000);
|
||||
LOG_I("dtb load done!\r\n");
|
||||
|
||||
/* Copy opensbi code */
|
||||
pSrc = (uint32_t *)OPENSBI_SRC_ADDR;
|
||||
pDest = (uint32_t *)OPENSBI_DST_ADDR;
|
||||
memcpy((void *)pDest, (void *)pSrc, 0xc000);
|
||||
LOG_I("opensbi load done!\r\n");
|
||||
|
||||
csi_dcache_clean_invalid();
|
||||
// csi_dcache_clean();
|
||||
}
|
||||
|
||||
extern void bflb_uart_set_console(struct bflb_device_s *dev);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
bflb_gpio_init(gpio, GPIO_PIN_16, 21 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_17, 21 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
|
||||
struct bflb_uart_config_s cfg;
|
||||
cfg.baudrate = 2000000;
|
||||
cfg.data_bits = UART_DATA_BITS_8;
|
||||
cfg.stop_bits = UART_STOP_BITS_1;
|
||||
cfg.parity = UART_PARITY_NONE;
|
||||
cfg.flow_ctrl = 0;
|
||||
cfg.tx_fifo_threshold = 7;
|
||||
cfg.rx_fifo_threshold = 7;
|
||||
uart0 = bflb_device_get_by_name("uart3");
|
||||
bflb_uart_init(uart0, &cfg);
|
||||
bflb_uart_set_console(uart0);
|
||||
|
||||
|
||||
LOG_I("C906 start...\r\n");
|
||||
uint64_t start_time, stop_time;
|
||||
|
||||
LOG_I("mtimer clk:%d\r\n", bflb_mtimer_get_freq());
|
||||
|
||||
CPU_MTimer_Delay_MS(100);
|
||||
|
||||
void (*opensbi)(int hart_id, int fdt_addr) = (void (*)(int hart_id, int fdt_addr))OPENSBI_DST_ADDR;
|
||||
|
||||
start_time = bflb_mtimer_get_time_us();
|
||||
linux_load();
|
||||
stop_time = bflb_mtimer_get_time_us();
|
||||
LOG_I("\r\nload time: %ld us \r\n", (stop_time - start_time));
|
||||
|
||||
__ASM volatile("csrw mcor, %0"
|
||||
:
|
||||
: "r"(0x30013));
|
||||
|
||||
LOG_I("Setting PMP\r\n");
|
||||
rvpmp_init(pmp_entry_tab, sizeof(pmp_entry_tab) / sizeof(pmp_config_entry_t));
|
||||
__ISB();
|
||||
LOG_I("Running OpenSBI\r\n");
|
||||
opensbi(0, DTB_DST_ADDR);
|
||||
while (1) {
|
||||
LOG_W("Return from OpenSBI!!!\r\n");
|
||||
bflb_mtimer_delay_ms(1000);
|
||||
}
|
||||
}
|
187
apps/d0_lowload/src/rv32i_xtheade_lz4.S
Normal file
187
apps/d0_lowload/src/rv32i_xtheade_lz4.S
Normal file
|
@ -0,0 +1,187 @@
|
|||
/**
|
||||
* @file main.c
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2022 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* a0: compressed data pool
|
||||
* a1: decompressed data pool
|
||||
* a2: total lengeth of the compressed data file
|
||||
*/
|
||||
/* void unlz4(const void *aSource, void *aDestination, uint32_t FileLen); */
|
||||
|
||||
.func unlz4
|
||||
|
||||
.global unlz4
|
||||
|
||||
.type unlz4,%function
|
||||
|
||||
.align 6
|
||||
.section .tcm_code.unlz4.text
|
||||
unlz4:
|
||||
addi sp, sp, -64 /* save fp and return-address */
|
||||
sw ra, 60(sp)
|
||||
sw s0, 56(sp)
|
||||
/* addi s0, sp, 64 */ /* no frame pointer needed */
|
||||
|
||||
sw s1, 0(sp)
|
||||
sw s2, 4(sp)
|
||||
sw s3, 8(sp)
|
||||
sw s4, 12(sp)
|
||||
sw s5, 16(sp)
|
||||
sw s6, 20(sp)
|
||||
sw s7, 24(sp)
|
||||
sw s8, 28(sp)
|
||||
sw s9, 32(sp)
|
||||
sw s10, 36(sp)
|
||||
sw s11, 40(sp)
|
||||
|
||||
mv s0, a0
|
||||
mv s1, a1
|
||||
add s9, a2,a0 /* s9 = end of the compressed data */
|
||||
|
||||
addi s0, s0, 7 /* !!! unaligned access needed !!! */
|
||||
addi s9, s9, -8 /* remove EoS and checksum */
|
||||
|
||||
loadConst: li s10, 0xf /* getLength */
|
||||
li s11, 0xff /* getLengthLoop */
|
||||
|
||||
blockStart:
|
||||
lw s2, 0(s0) /* get block length of compressed data */
|
||||
/* !!! unaligned access needed !!! */
|
||||
/* s2 = compressed data len of current block */
|
||||
|
||||
addi s0,s0,4 /* advance source pointer, s0 -> first token */
|
||||
|
||||
add s5,s2,s0 /* point a5 to end of compressed data */
|
||||
|
||||
getToken:
|
||||
lbuia s6,(s0),1,0 /* get token */
|
||||
|
||||
/* advance source pointer */
|
||||
|
||||
srli s4,s6, 4 /* get literal length, keep token in a6 */
|
||||
|
||||
and s8,s6, s10 /* match len in token: low 4-bit */
|
||||
|
||||
beqz s4, getOffset /* jump forward if there are no literals */
|
||||
|
||||
getLiteralLen: /* if length is 15, then more length info follows */
|
||||
|
||||
bne s10,s4,gotLiteralLen/* jump forward if we have the complete length */
|
||||
|
||||
getLiteralLenLoop: lbuia s3,(s0),1,0 /* read another byte */
|
||||
|
||||
/* advance source pointer */
|
||||
|
||||
/* check if end reached */
|
||||
|
||||
add s4,s4,s3 /* add byte to length */
|
||||
|
||||
/* if 0xff, get next length byte */
|
||||
beq s11,s3,getLiteralLenLoop
|
||||
gotLiteralLen:
|
||||
|
||||
/* copy literal */
|
||||
copy_literal:
|
||||
lbuia s3, (s0), 1, 0
|
||||
addi s4, s4, -1
|
||||
sbia s3, (s1), 1, 0
|
||||
beqz s4, copy_literal_done
|
||||
lbuia s3, (s0), 1, 0
|
||||
addi s4, s4, -1
|
||||
sbia s3, (s1), 1, 0
|
||||
bnez s4, copy_literal
|
||||
copy_literal_done:
|
||||
|
||||
mv s2,s0 /* update index */
|
||||
|
||||
beq s5,s2,blockDone /* no match data for last token in block */
|
||||
|
||||
getOffset:
|
||||
lhu s7, 0(s0) /* !!! unaligned access needed !!! */
|
||||
addi s0, s0, 2
|
||||
sub s2, s1, s7 /* subtract from destination; this will become the match position */
|
||||
|
||||
|
||||
getMatchLen:
|
||||
/* if length is 15, then more length info follows */
|
||||
bne s10,s8,gotMatchLen /* jump forward if we have the complete length */
|
||||
|
||||
getMatchLenLoop: lbuia s3,(s0),1,0 /* read another byte */
|
||||
|
||||
/* advance source pointer */
|
||||
|
||||
/* check if end reached */
|
||||
|
||||
add s8,s8,s3 /* add byte to length */
|
||||
|
||||
/* if 0xff, get another match len byte */
|
||||
beq s11,s3,getMatchLenLoop
|
||||
gotMatchLen:
|
||||
|
||||
/* minimum match length is 4 bytes */
|
||||
/* copy 4 bytes */
|
||||
copy_4bytes:
|
||||
lbuia s3, (s2), 1, 0
|
||||
sbia s3, (s1), 1, 0
|
||||
lbuia s3, (s2), 1, 0
|
||||
sbia s3, (s1), 1, 0
|
||||
lbuia s3, (s2), 1, 0
|
||||
sbia s3, (s1), 1, 0
|
||||
lbuia s3, (s2), 1, 0
|
||||
sbia s3, (s1), 1, 0
|
||||
|
||||
beqz s8, copy_match_done
|
||||
/* copy left match data */
|
||||
copy_match:
|
||||
lbuia s3, (s2), 1, 0
|
||||
addi s8, s8, -1
|
||||
sbia s3, (s1), 1, 0
|
||||
bnez s8, copy_match
|
||||
|
||||
copy_match_done:
|
||||
/* check if we've reached the end of the compressed data */
|
||||
blt s0,s5,getToken /* if not, go get the next token */
|
||||
|
||||
blockDone:
|
||||
blt s0,s9,blockStart /* there is another block of compressed data */
|
||||
|
||||
unlz4_exit:
|
||||
lw s1, 0(sp)
|
||||
lw s2, 4(sp)
|
||||
lw s3, 8(sp)
|
||||
lw s4, 12(sp)
|
||||
lw s5, 16(sp)
|
||||
lw s6, 20(sp)
|
||||
lw s7, 24(sp)
|
||||
lw s8, 28(sp)
|
||||
lw s9, 32(sp)
|
||||
lw s10, 36(sp)
|
||||
lw s11, 40(sp)
|
||||
|
||||
lw ra, 60(sp)
|
||||
lw s0, 56(sp)
|
||||
addi sp, sp, 64
|
||||
ret /* restore fp, then return */
|
||||
|
||||
.size unlz4,.-unlz4
|
||||
|
||||
.endfunc
|
22
apps/helloworld/CMakeLists.txt
Normal file
22
apps/helloworld/CMakeLists.txt
Normal file
|
@ -0,0 +1,22 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
include(proj.conf)
|
||||
|
||||
# Get SDK path
|
||||
if(NOT SDK_PATH)
|
||||
get_filename_component(SDK_PATH ../../ ABSOLUTE)
|
||||
if(EXISTS $ENV{MY_SDK_PATH})
|
||||
set(SDK_PATH $ENV{MY_SDK_PATH})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check SDK Path
|
||||
if(NOT EXISTS ${SDK_PATH})
|
||||
message(FATAL_ERROR "SDK path Error, Please set SDK_PATH or MY_SDK_PATH variable")
|
||||
endif()
|
||||
|
||||
include(${SDK_PATH}/cmake/bflbsdk.cmake)
|
||||
|
||||
sdk_set_main_file(main.c)
|
||||
|
||||
project(helloworld)
|
9
apps/helloworld/Kconfig
Normal file
9
apps/helloworld/Kconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
config EXAMPLE_HELLOWORLD
|
||||
string "String to Echo"
|
||||
default "hello world"
|
||||
|
||||
config EXAMPLE_INTERVAL
|
||||
int "Interval in milliseconds"
|
||||
default 1000
|
||||
range 100 10000
|
4
apps/helloworld/Makefile
Normal file
4
apps/helloworld/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
PINE64_SDK_PATH := $(realpath $(dir $(realpath $(lastword $(MAKEFILE_LIST))))../../)
|
||||
|
||||
include $(PINE64_SDK_PATH)/cmake/project.build
|
||||
|
18
apps/helloworld/main.c
Normal file
18
apps/helloworld/main.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include "bflb_mtimer.h"
|
||||
#include "board.h"
|
||||
#include "log.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
board_init();
|
||||
while (1) {
|
||||
LOG_F("%s\r\n", CONFIG_EXAMPLE_HELLOWORLD);
|
||||
LOG_E("%s\r\n", CONFIG_EXAMPLE_HELLOWORLD);
|
||||
LOG_W("%s\r\n", CONFIG_EXAMPLE_HELLOWORLD);
|
||||
LOG_I("%s\r\n", CONFIG_EXAMPLE_HELLOWORLD);
|
||||
LOG_D("%s\r\n", CONFIG_EXAMPLE_HELLOWORLD);
|
||||
LOG_T("%s\r\n", CONFIG_EXAMPLE_HELLOWORLD);
|
||||
bflb_mtimer_delay_ms(CONFIG_EXAMPLE_INTERVAL);
|
||||
}
|
||||
}
|
26
apps/m0_lowload/CMakeLists.txt
Normal file
26
apps/m0_lowload/CMakeLists.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
include(proj.conf)
|
||||
|
||||
# Get SDK path
|
||||
if(NOT SDK_PATH)
|
||||
get_filename_component(SDK_PATH ../../ ABSOLUTE)
|
||||
if(EXISTS $ENV{MY_SDK_PATH})
|
||||
set(SDK_PATH $ENV{MY_SDK_PATH})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check SDK Path
|
||||
if(NOT EXISTS ${SDK_PATH})
|
||||
message(FATAL_ERROR "SDK path Error, Please set SDK_PATH or MY_SDK_PATH variable")
|
||||
endif()
|
||||
|
||||
include(${SDK_PATH}/cmake/bflbsdk.cmake)
|
||||
|
||||
target_sources(app PRIVATE
|
||||
src/bl808_ipc.c)
|
||||
|
||||
target_compile_options(app PRIVATE -ggdb -Os)
|
||||
sdk_add_include_directories(include)
|
||||
sdk_set_main_file(src/main.c)
|
||||
project(m0_lowload)
|
14
apps/m0_lowload/Kconfig
Normal file
14
apps/m0_lowload/Kconfig
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
config LL_IRQFWD_SDH
|
||||
bool "Enable IRQ forwarding for SDH"
|
||||
default y
|
||||
|
||||
config LL_IRQFWD_UART2
|
||||
bool "Enable IRQ forwarding for UART2"
|
||||
default y
|
||||
|
||||
config LL_IRQFWD_USB
|
||||
bool "Enable IRQ forwarding for USB"
|
||||
default n
|
||||
|
||||
|
5
apps/m0_lowload/Makefile
Normal file
5
apps/m0_lowload/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
PINE64_SDK_PATH := $(realpath $(dir $(realpath $(lastword $(MAKEFILE_LIST))))../../)
|
||||
|
||||
CPU_ID = m0
|
||||
|
||||
include $(PINE64_SDK_PATH)/cmake/project.build
|
14
apps/m0_lowload/include/irq-forward.h
Normal file
14
apps/m0_lowload/include/irq-forward.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (C) 2023 Allen Martin <armartin@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_MAILBOX_BFLB_IPC_H
|
||||
#define __DT_BINDINGS_MAILBOX_BFLB_IPC_H
|
||||
|
||||
/* Peripheral device ID */
|
||||
#define BFLB_IPC_DEVICE_SDHCI 0
|
||||
#define BFLB_IPC_DEVICE_UART2 1
|
||||
#define BLFB_IPC_DEVICE_USB 2
|
||||
|
||||
#endif
|
8
apps/m0_lowload/sdkconfig.default
Normal file
8
apps/m0_lowload/sdkconfig.default
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
CONFIG_LL_IRQFWD_SDH=y
|
||||
CONFIG_LL_IRQFWD_UART2=y
|
||||
# CONFIG_LL_IRQFWD_USB is not set
|
||||
CONFIG_PSRAM=y
|
||||
CONFIG_BFLB_CHIP="bl808"
|
||||
CONFIG_BLFB_CPU_ID="m0"
|
||||
CONFIG_ROMAPI=y
|
738
apps/m0_lowload/src/bl808_ipc.c
Executable file
738
apps/m0_lowload/src/bl808_ipc.c
Executable file
|
@ -0,0 +1,738 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file bl808_ipc.c
|
||||
* @version V1.2
|
||||
* @date
|
||||
* @brief This file is the standard driver c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2018 Bouffalo Lab</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "bl808_ipc.h"
|
||||
|
||||
/** @addtogroup BL606P_Peripheral_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup IPC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup IPC_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
#define IPC_LP_OFFSET_IN_M0 0
|
||||
#define IPC_D0_OFFSET_IN_M0 16
|
||||
|
||||
#define IPC_M0_OFFSET_IN_LP 0
|
||||
#define IPC_D0_OFFSET_IN_LP 16
|
||||
|
||||
#define IPC_M0_OFFSET_IN_D0 0
|
||||
#define IPC_LP_OFFSET_IN_D0 16
|
||||
|
||||
/*@} end of group IPC_Private_Macros */
|
||||
|
||||
/** @defgroup IPC_Private_Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group IPC_Private_Types */
|
||||
|
||||
/** @defgroup IPC_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
ipcIntCallback *m0IpcIntCbfArra[GLB_CORE_ID_MAX - 1] = { NULL };
|
||||
ipcIntCallback *lpIpcIntCbfArra[GLB_CORE_ID_MAX - 1] = { NULL };
|
||||
ipcIntCallback *d0IpcIntCbfArra[GLB_CORE_ID_MAX - 1] = { NULL };
|
||||
|
||||
/*@} end of group IPC_Private_Variables */
|
||||
|
||||
/** @defgroup IPC_Global_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group IPC_Global_Variables */
|
||||
|
||||
/** @defgroup IPC_Private_Fun_Declaration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group IPC_Private_Fun_Declaration */
|
||||
|
||||
/** @defgroup IPC_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group IPC_Private_Functions */
|
||||
|
||||
/** @defgroup IPC_Public_Functions
|
||||
* @{
|
||||
*/
|
||||
#if defined(CPU_M0) || defined(CPU_LP)
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 IPC interrupt init
|
||||
*
|
||||
* @param onLPTriggerCallBack: Callback when LP trigger
|
||||
*
|
||||
* @param onD0TriggerCallBack: Callback when D0 trigger
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Init(ipcIntCallback *onLPTriggerCallBack,
|
||||
ipcIntCallback *onD0TriggerCallBack)
|
||||
{
|
||||
m0IpcIntCbfArra[0] = onLPTriggerCallBack;
|
||||
m0IpcIntCbfArra[1] = onD0TriggerCallBack;
|
||||
|
||||
IPC_M0_Int_Unmask_By_Word(0xffffffff);
|
||||
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
Interrupt_Handler_Register(IPC_M0_IRQn, IPC_M0_IRQHandler);
|
||||
#endif
|
||||
CPU_Interrupt_Enable(IPC_M0_IRQn);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 unmask IPC interrupt
|
||||
*
|
||||
* @param src: M0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Int_Unmask(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_IUSR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 unmask IPC interrupt by word
|
||||
*
|
||||
* @param src: IPC interrupt source in word,every bit is interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Int_Unmask_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_IUSR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 get IPC interrupt raw status
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return IPC interrupt raw status
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t IPC_M0_Get_Int_Raw_Status(void)
|
||||
{
|
||||
return BL_RD_REG(IPC0_BASE, IPC_CPU0_IPC_IRSRR);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 clear IPC interrupt
|
||||
*
|
||||
* @param src: M0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Clear_Int(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_ICR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 clear IPC interrupt by word
|
||||
*
|
||||
* @param src: IPC interrupt source in word,every bit is interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Clear_Int_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_ICR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief CPUx trigger IPC interrupt to M0
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @param cpuxOffset: CPU interrupt offset
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_CPUx_Trigger_M0(IPC_Grp_Int_Src_Type src, uint8_t cpuxOffset)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_Grp_Int_Src_Type(src));
|
||||
|
||||
tmpVal = (1 << (src + cpuxOffset));
|
||||
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU1_IPC_ISWR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP trigger IPC interrupt to M0
|
||||
*
|
||||
* @param src: LP IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Trigger_M0(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_M0(src, IPC_LP_OFFSET_IN_M0);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 trigger IPC interrupt to M0
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Trigger_M0(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_M0(src, IPC_D0_OFFSET_IN_M0);
|
||||
}
|
||||
|
||||
#if defined(CPU_M0) || defined(CPU_LP)
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP IPC interrupt init
|
||||
*
|
||||
* @param onM0TriggerCallBack: Callback when M0 trigger
|
||||
*
|
||||
* @param onD0TriggerCallBack: Callback when D0 trigger
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Init(ipcIntCallback *onM0TriggerCallBack,
|
||||
ipcIntCallback *onD0TriggerCallBack)
|
||||
{
|
||||
lpIpcIntCbfArra[0] = onM0TriggerCallBack;
|
||||
lpIpcIntCbfArra[1] = onD0TriggerCallBack;
|
||||
|
||||
IPC_LP_Int_Unmask_By_Word(0xffffffff);
|
||||
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
Interrupt_Handler_Register(IPC_LP_IRQn, IPC_LP_IRQHandler);
|
||||
#endif
|
||||
CPU_Interrupt_Enable(IPC_LP_IRQn);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP unmask IPC interrupt
|
||||
*
|
||||
* @param src: LP IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Int_Unmask(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_IUSR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP unmask IPC interrupt by word
|
||||
*
|
||||
* @param src: IPC interrupt source in word,every bit is interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Int_Unmask_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_IUSR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP get IPC interrupt raw status
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return IPC interrupt raw status
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t IPC_LP_Get_Int_Raw_Status(void)
|
||||
{
|
||||
return BL_RD_REG(IPC1_BASE, IPC_CPU0_IPC_IRSRR);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP clear IPC interrupt
|
||||
*
|
||||
* @param src: LP IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Clear_Int(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_ICR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP clear IPC interrupt by word
|
||||
*
|
||||
* @param src: IPC interrupt source in word,every bit is interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Clear_Int_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_ICR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief CPUx trigger IPC interrupt to LP
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @param cpuxOffset: CPU interrupt offset
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_CPUx_Trigger_LP(IPC_Grp_Int_Src_Type src, uint8_t cpuxOffset)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_Grp_Int_Src_Type(src));
|
||||
|
||||
tmpVal = (1 << (src + cpuxOffset));
|
||||
|
||||
BL_WR_REG(IPC1_BASE, IPC_CPU1_IPC_ISWR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 trigger IPC interrupt to LP
|
||||
*
|
||||
* @param src: M0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Trigger_LP(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_LP(src, IPC_M0_OFFSET_IN_LP);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 trigger IPC interrupt to LP
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Trigger_LP(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_LP(src, IPC_D0_OFFSET_IN_LP);
|
||||
}
|
||||
|
||||
#if defined(CPU_D0) || defined(CPU_D1)
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 IPC interrupt init
|
||||
*
|
||||
* @param onM0TriggerCallBack: Callback when M0 trigger
|
||||
*
|
||||
* @param onLPTriggerCallBack: Callback when LP trigger
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Init(ipcIntCallback *onM0TriggerCallBack,
|
||||
ipcIntCallback *onLPTriggerCallBack)
|
||||
{
|
||||
d0IpcIntCbfArra[0] = onM0TriggerCallBack;
|
||||
d0IpcIntCbfArra[1] = onLPTriggerCallBack;
|
||||
|
||||
IPC_D0_Int_Unmask_By_Word(0xffffffff);
|
||||
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
Interrupt_Handler_Register(IPC_D0_IRQn, IPC_D0_IRQHandler);
|
||||
#endif
|
||||
CPU_Interrupt_Enable(IPC_D0_IRQn);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 unmask IPC interrupt
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Int_Unmask(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_IUSR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 unmask IPC interrupt by word
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Int_Unmask_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_IUSR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 get IPC interrupt raw status
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return IPC interrupt raw status
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t IPC_D0_Get_Int_Raw_Status(void)
|
||||
{
|
||||
return BL_RD_REG(IPC2_BASE, IPC_CPU0_IPC_IRSRR);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 clear IPC interrupt
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Clear_Int(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_ICR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 clear IPC interrupt by word
|
||||
*
|
||||
* @param src: IPC interrupt source in word,every bit is interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Clear_Int_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_ICR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief CPUx trigger IPC interrupt to D0
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @param cpuxOffset: CPU interrupt offset
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_CPUx_Trigger_D0(IPC_Grp_Int_Src_Type src, uint8_t cpuxOffset)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_Grp_Int_Src_Type(src));
|
||||
|
||||
tmpVal = (1 << (src + cpuxOffset));
|
||||
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU1_IPC_ISWR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 trigger IPC interrupt to D0
|
||||
*
|
||||
* @param src: M0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Trigger_D0(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_D0(src, IPC_M0_OFFSET_IN_D0);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP trigger IPC interrupt to D0
|
||||
*
|
||||
* @param src: LP IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Trigger_D0(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_D0(src, IPC_LP_OFFSET_IN_D0);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 trigger IPC interrupt to CPUx
|
||||
*
|
||||
* @param tgtCPU: Target CPU
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Trigger_CPUx(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
switch (tgtCPU) {
|
||||
case GLB_CORE_ID_LP:
|
||||
IPC_M0_Trigger_LP(src);
|
||||
break;
|
||||
case GLB_CORE_ID_D0:
|
||||
IPC_M0_Trigger_D0(src);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP trigger IPC interrupt to CPUx
|
||||
*
|
||||
* @param tgtCPU: Target CPU
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Trigger_CPUx(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
switch (tgtCPU) {
|
||||
case GLB_CORE_ID_M0:
|
||||
IPC_LP_Trigger_M0(src);
|
||||
break;
|
||||
case GLB_CORE_ID_D0:
|
||||
IPC_LP_Trigger_D0(src);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 trigger IPC interrupt to CPUx
|
||||
*
|
||||
* @param tgtCPU: Target CPU
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Trigger_CPUx(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
switch (tgtCPU) {
|
||||
case GLB_CORE_ID_M0:
|
||||
IPC_D0_Trigger_M0(src);
|
||||
break;
|
||||
case GLB_CORE_ID_LP:
|
||||
IPC_D0_Trigger_LP(src);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 trigger IPC interrupt to D1
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_Trigger_Target_CPU(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
GLB_CORE_ID_Type localCPU = GLB_Get_Core_Type();
|
||||
|
||||
switch (localCPU) {
|
||||
case GLB_CORE_ID_M0:
|
||||
IPC_M0_Trigger_CPUx(tgtCPU, src);
|
||||
break;
|
||||
case GLB_CORE_ID_LP:
|
||||
IPC_LP_Trigger_CPUx(tgtCPU, src);
|
||||
break;
|
||||
case GLB_CORE_ID_D0:
|
||||
IPC_D0_Trigger_CPUx(tgtCPU, src);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 trigger IPC interrupt to D1
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_Common_Interrupt_Handler(uint32_t irqStatus, ipcIntCallback *callBack[GLB_CORE_ID_MAX - 1])
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint32_t grp = 0;
|
||||
|
||||
for (grp = 0; grp < GLB_CORE_ID_MAX - 1; grp++) {
|
||||
tmp = (irqStatus >> (16 * grp)) & 0xffff;
|
||||
if (tmp != 0) {
|
||||
if (callBack[grp] != NULL) {
|
||||
callBack[grp](tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 IPC IRQ handler
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
void IPC_M0_IRQHandler(void)
|
||||
{
|
||||
uint32_t irqStatus;
|
||||
MSG("%s: wrong handler!!\n", __func__);
|
||||
irqStatus = IPC_M0_Get_Int_Raw_Status();
|
||||
IPC_Common_Interrupt_Handler(irqStatus, m0IpcIntCbfArra);
|
||||
IPC_M0_Clear_Int_By_Word(irqStatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP IPC IRQ handler
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
void IPC_LP_IRQHandler(void)
|
||||
{
|
||||
uint32_t irqStatus;
|
||||
irqStatus = IPC_LP_Get_Int_Raw_Status();
|
||||
IPC_Common_Interrupt_Handler(irqStatus, lpIpcIntCbfArra);
|
||||
IPC_LP_Clear_Int_By_Word(irqStatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 IPC IRQ handler
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
void IPC_D0_IRQHandler(void)
|
||||
{
|
||||
uint32_t irqStatus;
|
||||
irqStatus = IPC_D0_Get_Int_Raw_Status();
|
||||
IPC_Common_Interrupt_Handler(irqStatus, d0IpcIntCbfArra);
|
||||
IPC_D0_Clear_Int_By_Word(irqStatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*@} end of group IPC_Public_Functions */
|
||||
|
||||
/*@} end of group IPC */
|
||||
|
||||
/*@} end of group BL606P_Peripheral_Driver */
|
139
apps/m0_lowload/src/main.c
Executable file
139
apps/m0_lowload/src/main.c
Executable file
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* @file main.c
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2022 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <bl808_common.h>
|
||||
#include <bflb_irq.h>
|
||||
#include <bl808_ipc.h>
|
||||
#include <ipc_reg.h>
|
||||
#include <sdh_reg.h>
|
||||
#include <log.h>
|
||||
#include <board.h>
|
||||
#include "irq-forward.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static uint32_t ipc_irqs[32] = {
|
||||
#ifdef CONFIG_LL_IRQFWD_SDH
|
||||
[BFLB_IPC_DEVICE_SDHCI] = SDH_IRQn,
|
||||
#endif
|
||||
#ifdef CONFIG_LL_IRQFWD_UART2
|
||||
[BFLB_IPC_DEVICE_UART2] = UART2_IRQn,
|
||||
#endif
|
||||
#ifdef CONFIG_LL_IRQFWD_USB
|
||||
[BLFB_IPC_DEVICE_USB] = USB_IRQn,
|
||||
#endif
|
||||
0,
|
||||
};
|
||||
|
||||
static void Send_IPC_IRQ(int device)
|
||||
{
|
||||
bflb_irq_disable(ipc_irqs[device]);
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU1_IPC_ISWR, (1 << device));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_SDH
|
||||
void SDH_MMC1_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
Send_IPC_IRQ(BFLB_IPC_DEVICE_SDHCI);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_UART2
|
||||
void UART2_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
Send_IPC_IRQ(BFLB_IPC_DEVICE_UART2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_USB
|
||||
void USB_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
Send_IPC_IRQ(BLFB_IPC_DEVICE_USB);
|
||||
}
|
||||
#endif
|
||||
|
||||
void IPC_M0_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
int i;
|
||||
uint32_t irqStatus = IPC_M0_Get_Int_Raw_Status();
|
||||
|
||||
for (i = 0; i < sizeof(irqStatus) * 8; i++)
|
||||
{
|
||||
if (irqStatus & (1 << i))
|
||||
bflb_irq_enable(ipc_irqs[i]);
|
||||
}
|
||||
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_ICR, irqStatus);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
board_init();
|
||||
|
||||
LOG_I("M0 CPU start...\r\n");
|
||||
|
||||
LOG_I("registering IPC interrupt handler\r\n");
|
||||
|
||||
bflb_irq_attach(IPC_M0_IRQn, IPC_M0_IRQHandler, NULL);
|
||||
IPC_M0_Int_Unmask_By_Word(0xffffffff);
|
||||
bflb_irq_enable(IPC_M0_IRQn);
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_SDH
|
||||
LOG_I("registering SDH interrupt handler\r\n");
|
||||
|
||||
bflb_irq_attach(SDH_IRQn, SDH_MMC1_IRQHandler, NULL);
|
||||
bflb_irq_enable(SDH_IRQn);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_UART2
|
||||
LOG_I("registering UART2 interrupt handler\r\n");
|
||||
|
||||
bflb_irq_attach(UART2_IRQn, UART2_IRQHandler, NULL);
|
||||
bflb_irq_enable(UART2_IRQn);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_USB
|
||||
LOG_I("registering USB interrupt handler\r\n");
|
||||
|
||||
bflb_irq_attach(USB_IRQn, UART2_IRQHandler, NULL);
|
||||
bflb_irq_enable(USB_IRQn);
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
{
|
||||
static int x = 0;
|
||||
if ((x++ % 999999999) == 0)
|
||||
{
|
||||
{
|
||||
// dump_ipc(IPC0_BASE);
|
||||
// dump_ipc(IPC1_BASE);
|
||||
LOG_I(".\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
int dummy;
|
||||
/* In lieu of a halt instruction, induce a long-latency stall. */
|
||||
__asm__ __volatile__("div %0, %0, zero"
|
||||
: "=r"(dummy));
|
||||
}
|
||||
}
|
9
bsp/ox64/CMakeLists.txt
Normal file
9
bsp/ox64/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
sdk_add_include_directories(include)
|
||||
|
||||
target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/board.c)
|
||||
|
||||
sdk_set_linker_script(bl808_flash_${CPU_ID}.ld)
|
||||
|
||||
if(CONFIG_PSRAM)
|
||||
sdk_add_compile_definitions(-DCONFIG_PSRAM)
|
||||
endif()
|
20
bsp/ox64/Kconfig
Normal file
20
bsp/ox64/Kconfig
Normal file
|
@ -0,0 +1,20 @@
|
|||
config JTAG_DEBUG
|
||||
bool "JTAG debug support"
|
||||
help
|
||||
This option enables JTAG debug support for the test kernel.
|
||||
|
||||
menu "JTAG Configuration"
|
||||
visible if JTAG_DEBUG
|
||||
choice
|
||||
prompt "JTAG Pinmux"
|
||||
default JTAG_M0
|
||||
help
|
||||
Select the core to attach the JTAG Debug Socket to.
|
||||
config JTAG_M0
|
||||
bool "Debug M0 Core"
|
||||
config JTAG_D0
|
||||
bool "Debug D0 Core"
|
||||
config JTAG_LP
|
||||
bool "Debug LP Core"
|
||||
endchoice
|
||||
endmenu
|
256
bsp/ox64/bl808_flash_d0.ld
Normal file
256
bsp/ox64/bl808_flash_d0.ld
Normal file
|
@ -0,0 +1,256 @@
|
|||
/****************************************************************************************
|
||||
* @file flash.ld
|
||||
*
|
||||
* @brief This file is the link script file (gnuarm or armgcc).
|
||||
*
|
||||
* Copyright (C) BouffaloLab 2021
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
/* configure the CPU type */
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
/* link with the standard c library */
|
||||
INPUT(-lc)
|
||||
/* link with the standard GCC library */
|
||||
INPUT(-lgcc)
|
||||
/* configure the entry point */
|
||||
ENTRY(__start)
|
||||
|
||||
StackSize = 0x0400; /* 1KB */
|
||||
HeapMinSize = 0x1000; /* 4KB */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
xip_memory (rx) : ORIGIN = 0x58000000, LENGTH = 32M
|
||||
itcm_memory (rx) : ORIGIN = 0x3eff0000, LENGTH = 28K
|
||||
dtcm_memory (rx) : ORIGIN = 0x3eff7000, LENGTH = 4K
|
||||
nocache_ram_memory (!rx) : ORIGIN = 0x3eff8000, LENGTH = 0K
|
||||
ram_memory (!rx) : ORIGIN = 0x3eff8000, LENGTH = 32K + 32K
|
||||
xram_memory (!rx) : ORIGIN = 0x40004000, LENGTH = 16K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__text_code_start__ = .;
|
||||
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
|
||||
/* section information for shell */
|
||||
. = ALIGN(8);
|
||||
__fsymtab_start = .;
|
||||
KEEP(*(FSymTab))
|
||||
__fsymtab_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
__vsymtab_start = .;
|
||||
KEEP(*(VSymTab))
|
||||
__vsymtab_end = .;
|
||||
|
||||
/*put .rodata**/
|
||||
*(EXCLUDE_FILE( *bl808_glb*.o* \
|
||||
*bl808_glb_gpio*.o* \
|
||||
*bl808_pds*.o* \
|
||||
*bl808_aon*.o* \
|
||||
*bl808_hbn*.o* \
|
||||
*bl808_l1c*.o* \
|
||||
*bl808_common*.o* \
|
||||
*bl808_clock*.o* \
|
||||
*bl808_ef_ctrl*.o* \
|
||||
*bl808_sf_cfg*.o* \
|
||||
*bl808_sf_ctrl*.o* \
|
||||
*bl808_sflash*.o* \
|
||||
*bl808_xip_sflash*.o* \
|
||||
*bl808_romapi_patch*.o* ) .rodata*)
|
||||
|
||||
*(.srodata)
|
||||
*(.srodata.*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__text_code_end__ = .;
|
||||
} > xip_memory
|
||||
|
||||
. = ALIGN(4);
|
||||
__itcm_load_addr = .;
|
||||
|
||||
.itcm_region : AT (__itcm_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__tcm_code_start__ = .;
|
||||
|
||||
*(.tcm_code.*)
|
||||
*(.tcm_const.*)
|
||||
*(.sclock_rlt_code.*)
|
||||
*(.sclock_rlt_const.*)
|
||||
|
||||
*bl808_glb*.o*(.rodata*)
|
||||
*bl808_glb_gpio*.o*(.rodata*)
|
||||
*bl808_pds*.o*(.rodata*)
|
||||
*bl808_aon*.o*(.rodata*)
|
||||
*bl808_hbn*.o*(.rodata*)
|
||||
*bl808_l1c*.o*(.rodata*)
|
||||
*bl808_common*.o*(.rodata*)
|
||||
*bl808_clock*.o*(.rodata*)
|
||||
*bl808_ef_ctrl*.o*(.rodata*)
|
||||
*bl808_sf_cfg*.o*(.rodata*)
|
||||
*bl808_sf_ctrl*.o*(.rodata*)
|
||||
*bl808_sflash*.o*(.rodata*)
|
||||
*bl808_xip_sflash*.o*(.rodata*)
|
||||
*bl808_romapi_patch*.o*(.rodata*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__tcm_code_end__ = .;
|
||||
} > itcm_memory
|
||||
|
||||
__dtcm_load_addr = __itcm_load_addr + SIZEOF(.itcm_region);
|
||||
|
||||
.dtcm_region : AT (__dtcm_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__tcm_data_start__ = .;
|
||||
|
||||
*(.tcm_data)
|
||||
/* *finger_print.o(.data*) */
|
||||
|
||||
. = ALIGN(4);
|
||||
__tcm_data_end__ = .;
|
||||
} > dtcm_memory
|
||||
|
||||
/*************************************************************************/
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (NOLOAD):
|
||||
{
|
||||
. = ALIGN(0x4);
|
||||
. = . + StackSize;
|
||||
. = ALIGN(0x4);
|
||||
} > dtcm_memory
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(dtcm_memory) + LENGTH(dtcm_memory);
|
||||
PROVIDE( __freertos_irq_stack_top = __StackTop);
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __tcm_data_end__, "region RAM overflowed with stack")
|
||||
/*************************************************************************/
|
||||
__nocache_ram_load_addr = __dtcm_load_addr + SIZEOF(.dtcm_region);
|
||||
|
||||
.nocache_ram_region (NOLOAD) : AT (__nocache_ram_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__nocache_ram_data_start__ = .;
|
||||
|
||||
*(.nocache_ram)
|
||||
|
||||
. = ALIGN(4);
|
||||
__nocache_ram_data_end__ = .;
|
||||
} > nocache_ram_memory
|
||||
|
||||
__system_ram_load_addr = __nocache_ram_load_addr + SIZEOF(.nocache_ram_region);
|
||||
|
||||
.system_ram_data_region : AT (__system_ram_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__system_ram_data_start__ = .;
|
||||
|
||||
*(.system_ram)
|
||||
|
||||
. = ALIGN(4);
|
||||
__system_ram_data_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
.system_ram_noinit_data_region (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.system_ram_noinit)
|
||||
|
||||
. = ALIGN(4);
|
||||
} > ram_memory
|
||||
|
||||
__ram_load_addr = __system_ram_load_addr + SIZEOF(.system_ram_data_region);
|
||||
|
||||
/* Data section */
|
||||
RAM_DATA : AT (__ram_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__ram_data_start__ = .;
|
||||
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__ram_data_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
__etext_final = (__ram_load_addr + SIZEOF (RAM_DATA));
|
||||
ASSERT(__etext_final <= ORIGIN(xip_memory) + LENGTH(xip_memory), "code memory overflow")
|
||||
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
|
||||
*(.bss*)
|
||||
*(.sbss*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
.noinit_data (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__noinit_data_start__ = .;
|
||||
|
||||
*(.noinit_data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__noinit_data_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
.nocache_noinit_ram_region (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__nocache_ram_data_start__ = .;
|
||||
|
||||
*(.nocache_noinit_ram)
|
||||
|
||||
. = ALIGN(4);
|
||||
__nocache_ram_data_end__ = .;
|
||||
} > nocache_ram_memory
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__HeapBase = .;
|
||||
|
||||
/*__end__ = .;*/
|
||||
/*end = __end__;*/
|
||||
KEEP(*(.heap*))
|
||||
|
||||
. = ALIGN(4);
|
||||
__HeapLimit = .;
|
||||
} > ram_memory
|
||||
|
||||
__HeapLimit = ORIGIN(ram_memory) + LENGTH(ram_memory);
|
||||
ASSERT(__HeapLimit - __HeapBase >= HeapMinSize, "heap region overflow")
|
||||
|
||||
}
|
||||
|
264
bsp/ox64/bl808_flash_m0.ld
Normal file
264
bsp/ox64/bl808_flash_m0.ld
Normal file
|
@ -0,0 +1,264 @@
|
|||
/****************************************************************************************
|
||||
* @file flash.ld
|
||||
*
|
||||
* @brief This file is the link script file (gnuarm or armgcc).
|
||||
*
|
||||
* Copyright (C) BouffaloLab 2021
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
/* configure the CPU type */
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
/* link with the standard c library */
|
||||
INPUT(-lc)
|
||||
/* link with the standard GCC library */
|
||||
INPUT(-lgcc)
|
||||
/* configure the entry point */
|
||||
ENTRY(__start)
|
||||
|
||||
StackSize = 0x0400; /* 1KB */
|
||||
HeapMinSize = 0x1000; /* 4KB */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
xip_memory (rx) : ORIGIN = 0x58000000, LENGTH = 32M
|
||||
itcm_memory (rx) : ORIGIN = 0x62020000, LENGTH = 20K
|
||||
dtcm_memory (rx) : ORIGIN = 0x62025000, LENGTH = 4K
|
||||
nocache_ram_memory (!rx) : ORIGIN = 0x22026000, LENGTH = 40K
|
||||
ram_memory (!rx) : ORIGIN = 0x62030000, LENGTH = 160K + 64K - 20K - 4K - 40K
|
||||
xram_memory (!rx) : ORIGIN = 0x40000000, LENGTH = 16K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__text_code_start__ = .;
|
||||
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
KEEP (*(SORT_NONE(.vector)))
|
||||
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
|
||||
/* section information for shell */
|
||||
. = ALIGN(4);
|
||||
__fsymtab_start = .;
|
||||
KEEP(*(FSymTab))
|
||||
__fsymtab_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
__vsymtab_start = .;
|
||||
KEEP(*(VSymTab))
|
||||
__vsymtab_end = .;
|
||||
|
||||
/* section information for usb usbh_class_info */
|
||||
. = ALIGN(4);
|
||||
__usbh_class_info_start__ = .;
|
||||
KEEP(*(.usbh_class_info))
|
||||
. = ALIGN(4);
|
||||
__usbh_class_info_end__ = .;
|
||||
|
||||
/*put .rodata**/
|
||||
*(EXCLUDE_FILE( *bl808_glb*.o* \
|
||||
*bl808_glb_gpio*.o* \
|
||||
*bl808_pds*.o* \
|
||||
*bl808_aon*.o* \
|
||||
*bl808_hbn*.o* \
|
||||
*bl808_l1c*.o* \
|
||||
*bl808_common*.o* \
|
||||
*bl808_clock*.o* \
|
||||
*bl808_ef_ctrl*.o* \
|
||||
*bl808_sf_cfg*.o* \
|
||||
*bl808_sf_ctrl*.o* \
|
||||
*bl808_sflash*.o* \
|
||||
*bl808_xip_sflash*.o* \
|
||||
*bl808_romapi_patch*.o* ) .rodata*)
|
||||
*(.srodata)
|
||||
*(.srodata.*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__text_code_end__ = .;
|
||||
} > xip_memory
|
||||
|
||||
. = ALIGN(4);
|
||||
__itcm_load_addr = .;
|
||||
|
||||
.itcm_region : AT (__itcm_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__tcm_code_start__ = .;
|
||||
|
||||
*(.tcm_code.*)
|
||||
*(.tcm_const.*)
|
||||
*(.sclock_rlt_code.*)
|
||||
*(.sclock_rlt_const.*)
|
||||
|
||||
*bl808_glb*.o*(.rodata*)
|
||||
*bl808_glb_gpio*.o*(.rodata*)
|
||||
*bl808_pds*.o*(.rodata*)
|
||||
*bl808_aon*.o*(.rodata*)
|
||||
*bl808_hbn*.o*(.rodata*)
|
||||
*bl808_l1c*.o*(.rodata*)
|
||||
*bl808_common*.o*(.rodata*)
|
||||
*bl808_clock*.o*(.rodata*)
|
||||
*bl808_ef_ctrl*.o*(.rodata*)
|
||||
*bl808_sf_cfg*.o*(.rodata*)
|
||||
*bl808_sf_ctrl*.o*(.rodata*)
|
||||
*bl808_sflash*.o*(.rodata*)
|
||||
*bl808_xip_sflash*.o*(.rodata*)
|
||||
*bl808_romapi_patch*.o*(.rodata*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__tcm_code_end__ = .;
|
||||
} > itcm_memory
|
||||
|
||||
__dtcm_load_addr = __itcm_load_addr + SIZEOF(.itcm_region);
|
||||
|
||||
.dtcm_region : AT (__dtcm_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__tcm_data_start__ = .;
|
||||
|
||||
*(.tcm_data)
|
||||
/* *finger_print.o(.data*) */
|
||||
|
||||
. = ALIGN(4);
|
||||
__tcm_data_end__ = .;
|
||||
} > dtcm_memory
|
||||
|
||||
/*************************************************************************/
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (NOLOAD):
|
||||
{
|
||||
. = ALIGN(0x4);
|
||||
. = . + StackSize;
|
||||
. = ALIGN(0x4);
|
||||
} > dtcm_memory
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(dtcm_memory) + LENGTH(dtcm_memory);
|
||||
PROVIDE( __freertos_irq_stack_top = __StackTop);
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __tcm_data_end__, "region RAM overflowed with stack")
|
||||
/*************************************************************************/
|
||||
__nocache_ram_load_addr = __dtcm_load_addr + SIZEOF(.dtcm_region);
|
||||
|
||||
.nocache_ram_region : AT (__nocache_ram_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__nocache_ram_data_start__ = .;
|
||||
|
||||
*(.nocache_ram)
|
||||
|
||||
. = ALIGN(4);
|
||||
__nocache_ram_data_end__ = .;
|
||||
} > nocache_ram_memory
|
||||
|
||||
__system_ram_load_addr = __nocache_ram_load_addr + SIZEOF(.nocache_ram_region);
|
||||
|
||||
.system_ram_data_region : AT (__system_ram_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__system_ram_data_start__ = .;
|
||||
|
||||
*(.system_ram)
|
||||
|
||||
. = ALIGN(4);
|
||||
__system_ram_data_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
.system_ram_noinit_data_region (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.system_ram_noinit)
|
||||
|
||||
. = ALIGN(4);
|
||||
} > ram_memory
|
||||
|
||||
__ram_load_addr = __system_ram_load_addr + SIZEOF(.system_ram_data_region);
|
||||
|
||||
/* Data section */
|
||||
RAM_DATA : AT (__ram_load_addr)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__ram_data_start__ = .;
|
||||
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__ram_data_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
__etext_final = (__ram_load_addr + SIZEOF (RAM_DATA));
|
||||
ASSERT(__etext_final <= ORIGIN(xip_memory) + LENGTH(xip_memory), "code memory overflow")
|
||||
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
|
||||
*(.bss*)
|
||||
*(.sbss*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
.noinit_data (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__noinit_data_start__ = .;
|
||||
|
||||
*(.noinit_data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
__noinit_data_end__ = .;
|
||||
} > ram_memory
|
||||
|
||||
.nocache_noinit_ram_region (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__nocache_noinit_ram_data_start__ = .;
|
||||
|
||||
*(.nocache_noinit_ram)
|
||||
*(.noncacheable)
|
||||
|
||||
. = ALIGN(4);
|
||||
__nocache_noinit_ram_data_end__ = .;
|
||||
} > nocache_ram_memory
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__HeapBase = .;
|
||||
|
||||
/*__end__ = .;*/
|
||||
/*end = __end__;*/
|
||||
KEEP(*(.heap*))
|
||||
|
||||
. = ALIGN(4);
|
||||
__HeapLimit = .;
|
||||
} > ram_memory
|
||||
|
||||
__HeapLimit = ORIGIN(ram_memory) + LENGTH(ram_memory);
|
||||
ASSERT(__HeapLimit - __HeapBase >= HeapMinSize, "heap region overflow")
|
||||
|
||||
}
|
||||
|
26
bsp/ox64/include/board.h
Normal file
26
bsp/ox64/include/board.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef _BOARD_H
|
||||
#define _BOARD_H
|
||||
|
||||
void board_init(void);
|
||||
|
||||
void board_jtag_gpio_init(void);
|
||||
void board_uartx_gpio_init(void);
|
||||
void board_i2c0_gpio_init(void);
|
||||
void board_spi0_gpio_init(void);
|
||||
void board_pwm_gpio_init(void);
|
||||
void board_adc_gpio_init(void);
|
||||
void board_dac_gpio_init(void);
|
||||
void board_ir_gpio_init(void);
|
||||
void board_emac_gpio_init(void);
|
||||
void board_sdh_gpio_init(void);
|
||||
void board_dvp_gpio_init(void);
|
||||
void board_csi_gpio_init(void);
|
||||
void board_iso11898_gpio_init(void);
|
||||
|
||||
#define DEFAULT_TEST_UART "uart1"
|
||||
#define DEFAULT_TEST_UART_DMA_TX_REQUEST DMA_REQUEST_UART1_TX
|
||||
#define DEFAULT_TEST_UART_DMA_RX_REQUEST DMA_REQUEST_UART1_RX
|
||||
#define DEFAULT_TEST_UART_DMA_TDR DMA_ADDR_UART1_TDR
|
||||
#define DEFAULT_TEST_UART_DMA_RDR DMA_ADDR_UART1_RDR
|
||||
|
||||
#endif
|
210
bsp/ox64/include/fw_header.h
Normal file
210
bsp/ox64/include/fw_header.h
Normal file
|
@ -0,0 +1,210 @@
|
|||
#ifndef __FW_HEADER_H__
|
||||
#define __FW_HEADER_H__
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
|
||||
struct __attribute__((packed, aligned(4))) spi_flash_cfg_t {
|
||||
uint8_t ioMode; /*!< Serail flash interface mode,bit0-3:IF mode,bit4:unwrap */
|
||||
uint8_t cReadSupport; /*!< Support continuous read mode,bit0:continuous read mode support,bit1:read mode cfg */
|
||||
uint8_t clkDelay; /*!< SPI clock delay,bit0-3:delay,bit4-6:pad delay */
|
||||
uint8_t clkInvert; /*!< SPI clock phase invert,bit0:clck invert,bit1:rx invert,bit2-4:pad delay,bit5-7:pad delay */
|
||||
uint8_t resetEnCmd; /*!< Flash enable reset command */
|
||||
uint8_t resetCmd; /*!< Flash reset command */
|
||||
uint8_t resetCreadCmd; /*!< Flash reset continuous read command */
|
||||
uint8_t resetCreadCmdSize; /*!< Flash reset continuous read command size */
|
||||
uint8_t jedecIdCmd; /*!< JEDEC ID command */
|
||||
uint8_t jedecIdCmdDmyClk; /*!< JEDEC ID command dummy clock */
|
||||
uint8_t enter32BitsAddrCmd; /*!< Enter 32-bits addr command */
|
||||
uint8_t exit32BitsAddrCmd; /*!< Exit 32-bits addr command */
|
||||
uint8_t sectorSize; /*!< *1024bytes */
|
||||
uint8_t mid; /*!< Manufacturer ID */
|
||||
uint16_t pageSize; /*!< Page size */
|
||||
uint8_t chipEraseCmd; /*!< Chip erase cmd */
|
||||
uint8_t sectorEraseCmd; /*!< Sector erase command */
|
||||
uint8_t blk32EraseCmd; /*!< Block 32K erase command,some Micron not support */
|
||||
uint8_t blk64EraseCmd; /*!< Block 64K erase command */
|
||||
uint8_t writeEnableCmd; /*!< Need before every erase or program */
|
||||
uint8_t pageProgramCmd; /*!< Page program cmd */
|
||||
uint8_t qpageProgramCmd; /*!< QIO page program cmd */
|
||||
uint8_t qppAddrMode; /*!< QIO page program address mode */
|
||||
uint8_t fastReadCmd; /*!< Fast read command */
|
||||
uint8_t frDmyClk; /*!< Fast read command dummy clock */
|
||||
uint8_t qpiFastReadCmd; /*!< QPI fast read command */
|
||||
uint8_t qpiFrDmyClk; /*!< QPI fast read command dummy clock */
|
||||
uint8_t fastReadDoCmd; /*!< Fast read dual output command */
|
||||
uint8_t frDoDmyClk; /*!< Fast read dual output command dummy clock */
|
||||
uint8_t fastReadDioCmd; /*!< Fast read dual io comamnd */
|
||||
uint8_t frDioDmyClk; /*!< Fast read dual io command dummy clock */
|
||||
uint8_t fastReadQoCmd; /*!< Fast read quad output comamnd */
|
||||
uint8_t frQoDmyClk; /*!< Fast read quad output comamnd dummy clock */
|
||||
uint8_t fastReadQioCmd; /*!< Fast read quad io comamnd */
|
||||
uint8_t frQioDmyClk; /*!< Fast read quad io comamnd dummy clock */
|
||||
uint8_t qpiFastReadQioCmd; /*!< QPI fast read quad io comamnd */
|
||||
uint8_t qpiFrQioDmyClk; /*!< QPI fast read QIO dummy clock */
|
||||
uint8_t qpiPageProgramCmd; /*!< QPI program command */
|
||||
uint8_t writeVregEnableCmd; /*!< Enable write reg */
|
||||
uint8_t wrEnableIndex; /*!< Write enable register index */
|
||||
uint8_t qeIndex; /*!< Quad mode enable register index */
|
||||
uint8_t busyIndex; /*!< Busy status register index */
|
||||
uint8_t wrEnableBit; /*!< Write enable bit pos */
|
||||
uint8_t qeBit; /*!< Quad enable bit pos */
|
||||
uint8_t busyBit; /*!< Busy status bit pos */
|
||||
uint8_t wrEnableWriteRegLen; /*!< Register length of write enable */
|
||||
uint8_t wrEnableReadRegLen; /*!< Register length of write enable status */
|
||||
uint8_t qeWriteRegLen; /*!< Register length of contain quad enable */
|
||||
uint8_t qeReadRegLen; /*!< Register length of contain quad enable status */
|
||||
uint8_t releasePowerDown; /*!< Release power down command */
|
||||
uint8_t busyReadRegLen; /*!< Register length of contain busy status */
|
||||
uint8_t readRegCmd[4]; /*!< Read register command buffer */
|
||||
uint8_t writeRegCmd[4]; /*!< Write register command buffer */
|
||||
uint8_t enterQpi; /*!< Enter qpi command */
|
||||
uint8_t exitQpi; /*!< Exit qpi command */
|
||||
uint8_t cReadMode; /*!< Config data for continuous read mode */
|
||||
uint8_t cRExit; /*!< Config data for exit continuous read mode */
|
||||
uint8_t burstWrapCmd; /*!< Enable burst wrap command */
|
||||
uint8_t burstWrapCmdDmyClk; /*!< Enable burst wrap command dummy clock */
|
||||
uint8_t burstWrapDataMode; /*!< Data and address mode for this command */
|
||||
uint8_t burstWrapData; /*!< Data to enable burst wrap */
|
||||
uint8_t deBurstWrapCmd; /*!< Disable burst wrap command */
|
||||
uint8_t deBurstWrapCmdDmyClk; /*!< Disable burst wrap command dummy clock */
|
||||
uint8_t deBurstWrapDataMode; /*!< Data and address mode for this command */
|
||||
uint8_t deBurstWrapData; /*!< Data to disable burst wrap */
|
||||
uint16_t timeEsector; /*!< 4K erase time */
|
||||
uint16_t timeE32k; /*!< 32K erase time */
|
||||
uint16_t timeE64k; /*!< 64K erase time */
|
||||
uint16_t timePagePgm; /*!< Page program time */
|
||||
uint16_t timeCe; /*!< Chip erase time in ms */
|
||||
uint8_t pdDelay; /*!< Release power down command delay time for wake up */
|
||||
uint8_t qeData; /*!< QE set data */
|
||||
};
|
||||
|
||||
struct __attribute__((packed, aligned(4))) boot_flash_cfg_t {
|
||||
uint32_t magiccode;
|
||||
struct spi_flash_cfg_t cfg;
|
||||
uint32_t crc32;
|
||||
};
|
||||
|
||||
struct __attribute__((packed, aligned(4))) sys_clk_cfg_t {
|
||||
uint8_t xtal_type;
|
||||
uint8_t mcu_clk;
|
||||
uint8_t mcu_clk_div;
|
||||
uint8_t mcu_bclk_div;
|
||||
|
||||
uint8_t mcu_pbclk_div;
|
||||
uint8_t lp_div;
|
||||
uint8_t dsp_clk;
|
||||
uint8_t dsp_clk_div;
|
||||
|
||||
uint8_t dsp_bclk_div;
|
||||
uint8_t dsp_pbclk;
|
||||
uint8_t dsp_pbclk_div;
|
||||
uint8_t emi_clk;
|
||||
|
||||
uint8_t emi_clk_div;
|
||||
uint8_t flash_clk_type;
|
||||
uint8_t flash_clk_div;
|
||||
uint8_t wifipll_pu;
|
||||
|
||||
uint8_t aupll_pu;
|
||||
uint8_t cpupll_pu;
|
||||
uint8_t mipipll_pu;
|
||||
uint8_t uhspll_pu;
|
||||
};
|
||||
|
||||
struct __attribute__((packed, aligned(4))) boot_clk_cfg_t {
|
||||
uint32_t magiccode;
|
||||
struct sys_clk_cfg_t cfg;
|
||||
uint32_t crc32;
|
||||
};
|
||||
|
||||
struct __attribute__((packed, aligned(4))) boot_basic_cfg_t {
|
||||
uint32_t sign_type : 2; /* [1: 0] for sign */
|
||||
uint32_t encrypt_type : 2; /* [3: 2] for encrypt */
|
||||
uint32_t key_sel : 2; /* [5: 4] key slot */
|
||||
uint32_t xts_mode : 1; /* [6] for xts mode */
|
||||
uint32_t aes_region_lock : 1; /* [7] rsvd */
|
||||
uint32_t no_segment : 1; /* [8] no segment info */
|
||||
uint32_t rsvd_0 : 1; /* [9] boot2 enable(rsvd_0) */
|
||||
uint32_t rsvd_1 : 1; /* [10] boot2 rollback(rsvd_1) */
|
||||
uint32_t cpu_master_id : 4; /* [14: 11] master id */
|
||||
uint32_t notload_in_bootrom : 1; /* [15] notload in bootrom */
|
||||
uint32_t crc_ignore : 1; /* [16] ignore crc */
|
||||
uint32_t hash_ignore : 1; /* [17] hash ignore */
|
||||
uint32_t power_on_mm : 1; /* [18] power on mm */
|
||||
uint32_t em_sel : 3; /* [21: 19] em_sel */
|
||||
uint32_t cmds_en : 1; /* [22] command spliter enable */
|
||||
uint32_t cmds_wrap_mode : 2; /* [24: 23] cmds wrap mode */
|
||||
uint32_t cmds_wrap_len : 4; /* [28: 25] cmds wrap len */
|
||||
uint32_t icache_invalid : 1; /* [29] icache invalid */
|
||||
uint32_t dcache_invalid : 1; /* [30] dcache invalid */
|
||||
uint32_t rsvd_3 : 1; /* [31] rsvd_3 */
|
||||
|
||||
uint32_t group_image_offset; /* flash controller offset */
|
||||
uint32_t aes_region_len; /* aes region length */
|
||||
|
||||
uint32_t img_len_cnt; /* image length or segment count */
|
||||
uint32_t hash[32 / 4]; /* hash of the image */
|
||||
};
|
||||
|
||||
struct __attribute__((packed, aligned(4))) boot_cpu_cfg_t {
|
||||
uint8_t config_enable; /* coinfig this cpu */
|
||||
uint8_t halt_cpu; /* halt this cpu */
|
||||
uint8_t cache_enable : 1; /* cache setting */
|
||||
uint8_t cache_wa : 1; /* cache setting */
|
||||
uint8_t cache_wb : 1; /* cache setting */
|
||||
uint8_t cache_wt : 1; /* cache setting */
|
||||
uint8_t cache_way_dis : 4; /* cache setting */
|
||||
uint8_t rsvd;
|
||||
|
||||
uint32_t cache_range_h; /* cache range high */
|
||||
uint32_t cache_range_l; /* cache range low */
|
||||
|
||||
uint32_t image_address_offset; /* image_address_offset */
|
||||
uint32_t rsvd0; /* rsvd0 */
|
||||
uint32_t msp_val; /* msp value */
|
||||
};
|
||||
|
||||
struct __attribute__((packed, aligned(4))) aesiv_cfg_t {
|
||||
uint8_t aesiv[16];
|
||||
uint32_t crc32;
|
||||
};
|
||||
|
||||
struct __attribute__((packed, aligned(4))) pkey_cfg_t {
|
||||
uint8_t eckeyx[32]; /* ec key in boot header */
|
||||
uint8_t eckeyy[32]; /* ec key in boot header */
|
||||
uint32_t crc32;
|
||||
};
|
||||
|
||||
struct __attribute__((packed, aligned(4))) sign_cfg_t {
|
||||
uint32_t sig_len;
|
||||
uint8_t signature[32];
|
||||
uint32_t crc32;
|
||||
};
|
||||
|
||||
struct __attribute__((packed, aligned(4))) bootheader_t {
|
||||
uint32_t magiccode; /* 4 */
|
||||
uint32_t rivison; /* 4 */
|
||||
|
||||
struct boot_flash_cfg_t flash_cfg; /* 4 + 84 + 4 */
|
||||
struct boot_clk_cfg_t clk_cfg; /* 4 + 20 + 4 */
|
||||
|
||||
struct boot_basic_cfg_t basic_cfg; /* 4 + 4 + 4 + 4 + 4*8 */
|
||||
|
||||
struct boot_cpu_cfg_t cpu_cfg[3]; /*24*3 */
|
||||
|
||||
uint32_t boot2_pt_table_0_rsvd; /* address of partition table 0 */ /* 4 */
|
||||
uint32_t boot2_pt_table_1_rsvd; /* address of partition table 1 */ /* 4 */
|
||||
|
||||
uint32_t flash_cfg_table_addr; /* address of flashcfg table list */ /* 4 */
|
||||
uint32_t flash_cfg_table_len; /* flashcfg table list len */ /* 4 */
|
||||
|
||||
uint32_t rsvd0[6]; /* rsvd */
|
||||
uint32_t rsvd1[6]; /* rsvd */
|
||||
|
||||
uint32_t rsvd3[5]; /* 4 */
|
||||
|
||||
uint32_t crc32; /* 4 */
|
||||
};
|
||||
|
||||
#endif
|
589
bsp/ox64/src/board.c
Normal file
589
bsp/ox64/src/board.c
Normal file
|
@ -0,0 +1,589 @@
|
|||
#include "bflb_uart.h"
|
||||
#include "bflb_gpio.h"
|
||||
#include "bflb_clock.h"
|
||||
#include "bflb_rtc.h"
|
||||
#include "bflb_flash.h"
|
||||
#ifdef CONFIG_TLSF
|
||||
#include "bflb_tlsf.h"
|
||||
#else
|
||||
#include "bflb_mmheap.h"
|
||||
#endif
|
||||
#include "bl808_glb.h"
|
||||
#include "bl808_sflash.h"
|
||||
#include "bl808_psram_uhs.h"
|
||||
#include "bl808_tzc_sec.h"
|
||||
#include "bl808_ef_cfg.h"
|
||||
#include "bl808_uhs_phy.h"
|
||||
#include "board.h"
|
||||
|
||||
#ifdef CONFIG_BSP_SDH_SDCARD
|
||||
#include "sdh_sdcard.h"
|
||||
#endif
|
||||
|
||||
extern uint32_t __HeapBase;
|
||||
extern uint32_t __HeapLimit;
|
||||
|
||||
#ifndef CONFIG_TLSF
|
||||
struct heap_info mmheap_root;
|
||||
|
||||
static struct heap_region system_mmheap[] = {
|
||||
{ NULL, 0 },
|
||||
{ NULL, 0 }, /* Terminates the array. */
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct bflb_device_s *uart0;
|
||||
|
||||
#if (defined(CONFIG_LUA) || defined(CONFIG_BFLOG) || defined(CONFIG_FATFS))
|
||||
static struct bflb_device_s *rtc;
|
||||
#endif
|
||||
|
||||
#if defined(CPU_M0)
|
||||
static void system_clock_init(void)
|
||||
{
|
||||
/* wifipll/audiopll */
|
||||
GLB_Power_On_XTAL_And_PLL_CLK(GLB_XTAL_40M, GLB_PLL_WIFIPLL |
|
||||
GLB_PLL_CPUPLL |
|
||||
GLB_PLL_UHSPLL |
|
||||
GLB_PLL_MIPIPLL);
|
||||
|
||||
GLB_Set_MCU_System_CLK(GLB_MCU_SYS_CLK_WIFIPLL_320M);
|
||||
GLB_Set_DSP_System_CLK(GLB_DSP_SYS_CLK_CPUPLL_400M);
|
||||
GLB_Config_CPU_PLL(GLB_XTAL_40M, cpuPllCfg_480M);
|
||||
|
||||
CPU_Set_MTimer_CLK(ENABLE, CPU_Get_MTimer_Source_Clock() / 1000 / 1000 - 1);
|
||||
}
|
||||
|
||||
static void peripheral_clock_init(void)
|
||||
{
|
||||
PERIPHERAL_CLOCK_ADC_DAC_ENABLE();
|
||||
PERIPHERAL_CLOCK_SEC_ENABLE();
|
||||
PERIPHERAL_CLOCK_DMA0_ENABLE();
|
||||
PERIPHERAL_CLOCK_UART0_ENABLE();
|
||||
PERIPHERAL_CLOCK_UART1_ENABLE();
|
||||
PERIPHERAL_CLOCK_SPI0_1_ENABLE();
|
||||
PERIPHERAL_CLOCK_I2C0_ENABLE();
|
||||
PERIPHERAL_CLOCK_PWM0_ENABLE();
|
||||
PERIPHERAL_CLOCK_TIMER0_1_WDG_ENABLE();
|
||||
PERIPHERAL_CLOCK_IR_ENABLE();
|
||||
PERIPHERAL_CLOCK_I2S_ENABLE();
|
||||
PERIPHERAL_CLOCK_USB_ENABLE();
|
||||
PERIPHERAL_CLOCK_CAN_UART2_ENABLE();
|
||||
|
||||
GLB_Set_ADC_CLK(ENABLE, GLB_ADC_CLK_XCLK, 4);
|
||||
GLB_Set_UART_CLK(ENABLE, HBN_UART_CLK_XCLK, 0);
|
||||
GLB_Set_DSP_UART0_CLK(ENABLE, GLB_DSP_UART_CLK_DSP_XCLK, 0);
|
||||
GLB_Set_SPI_CLK(ENABLE, GLB_SPI_CLK_MCU_MUXPLL_160M, 0);
|
||||
GLB_Set_I2C_CLK(ENABLE, GLB_I2C_CLK_XCLK, 0);
|
||||
GLB_Set_IR_CLK(ENABLE, GLB_IR_CLK_SRC_XCLK, 19);
|
||||
GLB_Set_ADC_CLK(ENABLE, GLB_ADC_CLK_XCLK, 1);
|
||||
GLB_Set_DIG_CLK_Sel(GLB_DIG_CLK_XCLK);
|
||||
GLB_Set_DIG_512K_CLK(ENABLE, ENABLE, 0x4E);
|
||||
GLB_Set_PWM1_IO_Sel(GLB_PWM1_IO_DIFF_END);
|
||||
GLB_Set_CAM_CLK(ENABLE, GLB_CAM_CLK_WIFIPLL_96M, 3);
|
||||
|
||||
GLB_Set_PKA_CLK_Sel(GLB_PKA_CLK_MCU_MUXPLL_160M);
|
||||
|
||||
#ifdef CONFIG_BSP_SDH_SDCARD
|
||||
PERIPHERAL_CLOCK_SDH_ENABLE();
|
||||
uint32_t tmp_val;
|
||||
tmp_val = BL_RD_REG(PDS_BASE, PDS_CTL5);
|
||||
uint32_t tmp_val2 = BL_GET_REG_BITS_VAL(tmp_val, PDS_CR_PDS_GPIO_KEEP_EN);
|
||||
tmp_val2 &= ~(1 << 0);
|
||||
tmp_val = BL_SET_REG_BITS_VAL(tmp_val, PDS_CR_PDS_GPIO_KEEP_EN, tmp_val2);
|
||||
BL_WR_REG(PDS_BASE, PDS_CTL5, tmp_val);
|
||||
GLB_AHB_MCU_Software_Reset(GLB_AHB_MCU_SW_SDH);
|
||||
#endif
|
||||
GLB_Set_USB_CLK_From_WIFIPLL(1);
|
||||
|
||||
#ifdef CONFIG_BSP_CSI
|
||||
GLB_CSI_Config_MIPIPLL(2, 0x21000);
|
||||
GLB_CSI_Power_Up_MIPIPLL();
|
||||
GLB_Set_DSP_CLK(ENABLE, GLB_DSP_CLK_MUXPLL_160M, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PSRAM
|
||||
#define WB_4MB_PSRAM (1)
|
||||
#define UHS_32MB_PSRAM (2)
|
||||
#define UHS_64MB_PSRAM (3)
|
||||
#define WB_32MB_PSRAM (4)
|
||||
#define NONE_UHS_PSRAM (-1)
|
||||
|
||||
int uhs_psram_init(void)
|
||||
{
|
||||
PSRAM_UHS_Cfg_Type psramDefaultCfg = {
|
||||
2000,
|
||||
PSRAM_MEM_SIZE_32MB,
|
||||
PSRAM_PAGE_SIZE_2KB,
|
||||
PSRAM_UHS_NORMAL_TEMP,
|
||||
};
|
||||
|
||||
bflb_efuse_device_info_type chip_info;
|
||||
bflb_ef_ctrl_get_device_info(&chip_info);
|
||||
if (chip_info.psramInfo == UHS_32MB_PSRAM) {
|
||||
psramDefaultCfg.psramMemSize = PSRAM_MEM_SIZE_32MB;
|
||||
} else if (chip_info.psramInfo == UHS_64MB_PSRAM) {
|
||||
psramDefaultCfg.psramMemSize = PSRAM_MEM_SIZE_64MB;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//init uhs PLL; Must open uhs pll first, and then initialize uhs psram
|
||||
GLB_Config_UHS_PLL(GLB_XTAL_40M, uhsPllCfg_2000M);
|
||||
//init uhs psram ;
|
||||
// Psram_UHS_x16_Init(Clock_Peripheral_Clock_Get(BL_PERIPHERAL_CLOCK_PSRAMA) / 1000000);
|
||||
Psram_UHS_x16_Init_Override(&psramDefaultCfg);
|
||||
Tzc_Sec_PSRAMA_Access_Release();
|
||||
|
||||
// example: 2000Mbps typical cal values
|
||||
uhs_phy_cal_res->rl = 39;
|
||||
uhs_phy_cal_res->rdqs = 3;
|
||||
uhs_phy_cal_res->rdq = 0;
|
||||
uhs_phy_cal_res->wl = 13;
|
||||
uhs_phy_cal_res->wdqs = 4;
|
||||
uhs_phy_cal_res->wdq = 5;
|
||||
uhs_phy_cal_res->ck = 9;
|
||||
/* TODO: use uhs psram trim update */
|
||||
set_uhs_latency_r(uhs_phy_cal_res->rl);
|
||||
cfg_dqs_rx(uhs_phy_cal_res->rdqs);
|
||||
cfg_dq_rx(uhs_phy_cal_res->rdq);
|
||||
set_uhs_latency_w(uhs_phy_cal_res->wl);
|
||||
cfg_dq_drv(uhs_phy_cal_res->wdq);
|
||||
cfg_ck_cen_drv(uhs_phy_cal_res->wdq + 4, uhs_phy_cal_res->wdq + 1);
|
||||
cfg_dqs_drv(uhs_phy_cal_res->wdqs);
|
||||
// set_odt_en();
|
||||
mr_read_back();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void bl_show_log(void)
|
||||
{
|
||||
printf("\r\n");
|
||||
printf(" ____ __ __ _ _ _ \r\n");
|
||||
printf(" | _ \\ / _|/ _| | | | | | | \r\n");
|
||||
printf(" | |_) | ___ _ _| |_| |_ __ _| | ___ | | __ _| |__ \r\n");
|
||||
printf(" | _ < / _ \\| | | | _| _/ _` | |/ _ \\| |/ _` | '_ \\ \r\n");
|
||||
printf(" | |_) | (_) | |_| | | | || (_| | | (_) | | (_| | |_) |\r\n");
|
||||
printf(" |____/ \\___/ \\__,_|_| |_| \\__,_|_|\\___/|_|\\__,_|_.__/ \r\n");
|
||||
printf("\r\n");
|
||||
printf("Build:%s,%s\r\n", __TIME__, __DATE__);
|
||||
printf("Copyright (c) 2022 Bouffalolab team\r\n");
|
||||
}
|
||||
|
||||
void bl_show_flashinfo(void)
|
||||
{
|
||||
SPI_Flash_Cfg_Type flashCfg;
|
||||
uint8_t *pFlashCfg = NULL;
|
||||
uint32_t flashCfgLen = 0;
|
||||
uint32_t flashJedecId = 0;
|
||||
|
||||
flashJedecId = bflb_flash_get_jedec_id();
|
||||
bflb_flash_get_cfg(&pFlashCfg, &flashCfgLen);
|
||||
arch_memcpy((void *)&flashCfg, pFlashCfg, flashCfgLen);
|
||||
printf("=========== flash cfg ==============\r\n");
|
||||
printf("jedec id 0x%06X\r\n", flashJedecId);
|
||||
printf("mid 0x%02X\r\n", flashCfg.mid);
|
||||
printf("iomode 0x%02X\r\n", flashCfg.ioMode);
|
||||
printf("clk delay 0x%02X\r\n", flashCfg.clkDelay);
|
||||
printf("clk invert 0x%02X\r\n", flashCfg.clkInvert);
|
||||
printf("read reg cmd0 0x%02X\r\n", flashCfg.readRegCmd[0]);
|
||||
printf("read reg cmd1 0x%02X\r\n", flashCfg.readRegCmd[1]);
|
||||
printf("write reg cmd0 0x%02X\r\n", flashCfg.writeRegCmd[0]);
|
||||
printf("write reg cmd1 0x%02X\r\n", flashCfg.writeRegCmd[1]);
|
||||
printf("qe write len 0x%02X\r\n", flashCfg.qeWriteRegLen);
|
||||
printf("cread support 0x%02X\r\n", flashCfg.cReadSupport);
|
||||
printf("cread code 0x%02X\r\n", flashCfg.cReadMode);
|
||||
printf("burst wrap cmd 0x%02X\r\n", flashCfg.burstWrapCmd);
|
||||
printf("=====================================\r\n");
|
||||
}
|
||||
|
||||
extern void bflb_uart_set_console(struct bflb_device_s *dev);
|
||||
|
||||
static void console_init()
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
#if defined(CPU_M0)
|
||||
bflb_gpio_uart_init(gpio, GPIO_PIN_14, GPIO_UART_FUNC_UART0_TX);
|
||||
bflb_gpio_uart_init(gpio, GPIO_PIN_15, GPIO_UART_FUNC_UART0_RX);
|
||||
#elif defined(CPU_D0)
|
||||
bflb_gpio_init(gpio, GPIO_PIN_16, 21 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_17, 21 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
//bflb_gpio_uart_init(gpio, GPIO_PIN_16, GPIO_UART_FUNC_UART1_TX);
|
||||
//bflb_gpio_uart_init(gpio, GPIO_PIN_17, GPIO_UART_FUNC_UART1_RX);
|
||||
|
||||
#endif
|
||||
struct bflb_uart_config_s cfg;
|
||||
#if defined(CPU_M0)
|
||||
cfg.baudrate = 2000000;
|
||||
#else
|
||||
cfg.baudrate = 2000000;
|
||||
#endif
|
||||
cfg.data_bits = UART_DATA_BITS_8;
|
||||
cfg.stop_bits = UART_STOP_BITS_1;
|
||||
cfg.parity = UART_PARITY_NONE;
|
||||
cfg.flow_ctrl = 0;
|
||||
cfg.tx_fifo_threshold = 7;
|
||||
cfg.rx_fifo_threshold = 7;
|
||||
#if defined(CPU_M0)
|
||||
uart0 = bflb_device_get_by_name("uart0");
|
||||
#elif defined(CPU_D0)
|
||||
uart0 = bflb_device_get_by_name("uart3");
|
||||
#endif
|
||||
bflb_uart_init(uart0, &cfg);
|
||||
bflb_uart_set_console(uart0);
|
||||
}
|
||||
|
||||
#if defined(CPU_M0)
|
||||
void board_init(void)
|
||||
{
|
||||
uintptr_t flag;
|
||||
|
||||
flag = bflb_irq_save();
|
||||
|
||||
bflb_flash_init();
|
||||
|
||||
GLB_Halt_CPU(GLB_CORE_ID_D0);
|
||||
GLB_Halt_CPU(GLB_CORE_ID_LP);
|
||||
|
||||
system_clock_init();
|
||||
peripheral_clock_init();
|
||||
bflb_irq_initialize();
|
||||
|
||||
GLB_Release_CPU(GLB_CORE_ID_D0);
|
||||
GLB_Release_CPU(GLB_CORE_ID_LP);
|
||||
|
||||
bflb_irq_restore(flag);
|
||||
|
||||
#ifdef CONFIG_TLSF
|
||||
bflb_mmheap_init((void *)&__HeapBase, ((size_t)&__HeapLimit - (size_t)&__HeapBase));
|
||||
#else
|
||||
system_mmheap[0].addr = (uint8_t *)&__HeapBase;
|
||||
system_mmheap[0].mem_size = ((size_t)&__HeapLimit - (size_t)&__HeapBase);
|
||||
|
||||
if (system_mmheap[0].mem_size > 0) {
|
||||
bflb_mmheap_init(&mmheap_root, system_mmheap);
|
||||
}
|
||||
#endif
|
||||
|
||||
console_init();
|
||||
|
||||
bl_show_log();
|
||||
bl_show_flashinfo();
|
||||
#ifdef CONFIG_TLSF
|
||||
bflb_tlsf_size_container_t *tlsf_size = bflb_tlsf_stats();
|
||||
printf("TLSF Dynamic Memory Init Success: Heap Size = %d Kbyte, Used Size = %d Kbyte, Free Size = %d Kbyte\r\n",
|
||||
tlsf_size->free + tlsf_size->used / 1024, tlsf_size->used / 1024, tlsf_size->free / 1024);
|
||||
#else
|
||||
printf("dynamic memory init success,heap size = %d Kbyte \r\n", system_mmheap[0].mem_size / 1024);
|
||||
#endif
|
||||
|
||||
printf("sig1:%08x\r\n", BL_RD_REG(GLB_BASE, GLB_UART_CFG1));
|
||||
printf("sig2:%08x\r\n", BL_RD_REG(GLB_BASE, GLB_UART_CFG2));
|
||||
|
||||
#if (defined(CONFIG_LUA) || defined(CONFIG_BFLOG) || defined(CONFIG_FATFS))
|
||||
rtc = bflb_device_get_by_name("rtc");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PSRAM
|
||||
if (uhs_psram_init() < 0) {
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* release d0 and then do can run */
|
||||
BL_WR_WORD(IPC_SYNC_ADDR1, IPC_SYNC_FLAG);
|
||||
BL_WR_WORD(IPC_SYNC_ADDR2, IPC_SYNC_FLAG);
|
||||
L1C_DCache_Clean_By_Addr(IPC_SYNC_ADDR1, 8);
|
||||
}
|
||||
#elif defined(CPU_D0)
|
||||
void board_init(void)
|
||||
{
|
||||
CPU_Set_MTimer_CLK(ENABLE, CPU_Get_MTimer_Source_Clock() / 1000 / 1000 - 1);
|
||||
|
||||
bflb_irq_initialize();
|
||||
|
||||
#ifdef CONFIG_TLSF
|
||||
bflb_mmheap_init((void *)&__HeapBase, ((size_t)&__HeapLimit - (size_t)&__HeapBase));
|
||||
bflb_tlsf_size_container_t *tlsf_size = bflb_tlsf_stats();
|
||||
printf("TLSF Dynamic Memory Init Success: Heap Size = %d Kbyte, Used Size = %d Kbyte, Free Size = %d Kbyte\r\n",
|
||||
tlsf_size->free + tlsf_size->used / 1024, tlsf_size->used / 1024, tlsf_size->free / 1024);
|
||||
#else
|
||||
system_mmheap[0].addr = (uint8_t *)&__HeapBase;
|
||||
system_mmheap[0].mem_size = ((size_t)&__HeapLimit - (size_t)&__HeapBase);
|
||||
|
||||
if (system_mmheap[0].mem_size > 0) {
|
||||
bflb_mmheap_init(&mmheap_root, system_mmheap);
|
||||
}
|
||||
#endif
|
||||
|
||||
console_init();
|
||||
|
||||
bl_show_log();
|
||||
|
||||
printf("dynamic memory init success,heap size = %d Kbyte \r\n", ((size_t)&__HeapLimit - (size_t)&__HeapBase) / 1024);
|
||||
|
||||
printf("sig1:%08x\r\n", BL_RD_REG(GLB_BASE, GLB_UART_CFG1));
|
||||
printf("sig2:%08x\r\n", BL_RD_REG(GLB_BASE, GLB_UART_CFG2));
|
||||
printf("cgen1:%08x\r\n", getreg32(BFLB_GLB_CGEN1_BASE));
|
||||
}
|
||||
#endif
|
||||
|
||||
void board_uartx_gpio_init(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
|
||||
bflb_gpio_uart_init(gpio, GPIO_PIN_4, GPIO_UART_FUNC_UART1_TX);
|
||||
bflb_gpio_uart_init(gpio, GPIO_PIN_5, GPIO_UART_FUNC_UART1_RX);
|
||||
bflb_gpio_uart_init(gpio, GPIO_PIN_6, GPIO_UART_FUNC_UART1_CTS);
|
||||
bflb_gpio_uart_init(gpio, GPIO_PIN_7, GPIO_UART_FUNC_UART1_RTS);
|
||||
}
|
||||
|
||||
void board_i2c0_gpio_init(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
/* I2C0_SDA */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_11, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
/* I2C0_SCL */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_16, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
}
|
||||
|
||||
void board_spi0_gpio_init(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
/* spi cs */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_16, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
/* spi miso */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_17, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
/* spi mosi */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_18, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
/* spi clk */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_19, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
}
|
||||
|
||||
void board_pwm_gpio_init(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
bflb_gpio_init(gpio, GPIO_PIN_24, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_25, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_26, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_27, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_28, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_29, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_30, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_31, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
}
|
||||
|
||||
void board_adc_gpio_init(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
/* ADC_CH0 */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_17, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* ADC_CH1 */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_5, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* ADC_CH2 */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_4, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* ADC_CH3 */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_11, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* ADC_CH4 */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_6, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* ADC_CH5 */
|
||||
//bflb_gpio_init(gpio, GPIO_PIN_40, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* ADC_CH6 */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_12, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* ADC_CH7 */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_13, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* ADC_CH8 */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_16, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* ADC_CH9 */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_18, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* ADC_CH10 */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_19, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* ADC_CH11,note the FLASH pin */
|
||||
//bflb_gpio_init(gpio, GPIO_PIN_34, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
}
|
||||
|
||||
void board_dac_gpio_init(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
/* DAC_CHA */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_11, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
/* DAC_CHB */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_4, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
}
|
||||
|
||||
void board_ir_gpio_init(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
bflb_gpio_init(gpio, GPIO_PIN_11, GPIO_ANALOG | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_17, GPIO_INPUT | GPIO_SMT_EN | GPIO_DRV_0);
|
||||
GLB_IR_RX_GPIO_Sel(GLB_GPIO_PIN_17);
|
||||
}
|
||||
|
||||
void board_emac_gpio_init(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
bflb_gpio_init(gpio, GPIO_PIN_24, GPIO_FUNC_EMAC | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_25, GPIO_FUNC_EMAC | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_26, GPIO_FUNC_EMAC | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_27, GPIO_FUNC_EMAC | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_28, GPIO_FUNC_EMAC | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_29, GPIO_FUNC_EMAC | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_30, GPIO_FUNC_EMAC | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_31, GPIO_FUNC_EMAC | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_32, GPIO_FUNC_EMAC | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_33, GPIO_FUNC_EMAC | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
|
||||
#if defined(BL808)
|
||||
// GLB_PER_Clock_UnGate(1<<12);
|
||||
#endif
|
||||
}
|
||||
|
||||
void board_sdh_gpio_init(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
bflb_gpio_init(gpio, GPIO_PIN_0, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_1, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_2, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_3, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_4, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_5, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
}
|
||||
|
||||
void board_dvp_gpio_init(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
/* I2C GPIO */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_22, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_23, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
|
||||
/* Power down GPIO */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_21, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_reset(gpio, GPIO_PIN_21);
|
||||
|
||||
/* Reset GPIO */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_20, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_set(gpio, GPIO_PIN_20);
|
||||
|
||||
/* MCLK GPIO */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_33, GPIO_FUNC_CLKOUT | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
|
||||
/* DVP GPIO */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_16, GPIO_FUNC_CAM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_17, GPIO_FUNC_CAM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_24, GPIO_FUNC_CAM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_25, GPIO_FUNC_CAM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_26, GPIO_FUNC_CAM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_27, GPIO_FUNC_CAM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_28, GPIO_FUNC_CAM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_29, GPIO_FUNC_CAM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_30, GPIO_FUNC_CAM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_31, GPIO_FUNC_CAM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_32, GPIO_FUNC_CAM | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
}
|
||||
|
||||
void board_csi_gpio_init(void)
|
||||
{
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
|
||||
/* I2C GPIO */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_19, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_20, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
|
||||
/* Power down GPIO */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_22, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_set(gpio, GPIO_PIN_22);
|
||||
|
||||
/* Reset GPIO */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_21, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
bflb_gpio_set(gpio, GPIO_PIN_21);
|
||||
|
||||
/* MCLK GPIO */
|
||||
bflb_gpio_init(gpio, GPIO_PIN_23, GPIO_FUNC_CLKOUT | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
|
||||
|
||||
GLB_Set_Ldo15cis_Vout(GLB_LDO15CIS_LEVEL_1P20V);
|
||||
}
|
||||
|
||||
void board_iso11898_gpio_init(void)
|
||||
{
|
||||
// struct bflb_device_s *gpio;
|
||||
|
||||
// gpio = bflb_device_get_by_name("gpio");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BFLOG
|
||||
__attribute__((weak)) uint64_t bflog_clock(void)
|
||||
{
|
||||
return bflb_mtimer_get_time_us();
|
||||
}
|
||||
|
||||
__attribute__((weak)) uint32_t bflog_time(void)
|
||||
{
|
||||
return BFLB_RTC_TIME2SEC(bflb_rtc_get_time(rtc));
|
||||
}
|
||||
|
||||
__attribute__((weak)) char *bflog_thread(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LUA
|
||||
__attribute__((weak)) clock_t luaport_clock(void)
|
||||
{
|
||||
return (clock_t)bflb_mtimer_get_time_us();
|
||||
}
|
||||
|
||||
__attribute__((weak)) time_t luaport_time(time_t *seconds)
|
||||
{
|
||||
time_t t = (time_t)BFLB_RTC_TIME2SEC(bflb_rtc_get_time(rtc));
|
||||
if (seconds != NULL) {
|
||||
*seconds = t;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FATFS
|
||||
#include "bflb_timestamp.h"
|
||||
__attribute__((weak)) uint32_t get_fattime(void)
|
||||
{
|
||||
bflb_timestamp_t tm;
|
||||
|
||||
bflb_timestamp_utc2time(BFLB_RTC_TIME2SEC(bflb_rtc_get_time(rtc)), &tm);
|
||||
|
||||
return ((uint32_t)(tm.year - 1980) << 25) /* Year 2015 */
|
||||
| ((uint32_t)tm.mon << 21) /* Month 1 */
|
||||
| ((uint32_t)tm.mday << 16) /* Mday 1 */
|
||||
| ((uint32_t)tm.hour << 11) /* Hour 0 */
|
||||
| ((uint32_t)tm.min << 5) /* Min 0 */
|
||||
| ((uint32_t)tm.sec >> 1); /* Sec 0 */
|
||||
}
|
||||
#endif
|
403
bsp/ox64/src/fw_header.c
Normal file
403
bsp/ox64/src/fw_header.c
Normal file
|
@ -0,0 +1,403 @@
|
|||
#include "fw_header.h"
|
||||
|
||||
__attribute__((section(".fw_header0"))) struct bootheader_t fw_header0 = {
|
||||
.magiccode = 0x504e4642,
|
||||
.rivison = 0x00000001,
|
||||
/*flash config */
|
||||
.flash_cfg.magiccode = 0x47464346,
|
||||
.flash_cfg.cfg.ioMode = 0x10, /*!< Serail flash interface mode,bit0-3:IF mode,bit4:unwrap */
|
||||
.flash_cfg.cfg.cReadSupport = 0x00, /*!< Support continuous read mode,bit0:continuous read mode support,bit1:read mode cfg */
|
||||
.flash_cfg.cfg.clkDelay = 0x01, /*!< SPI clock delay,bit0-3:delay,bit4-6:pad delay */
|
||||
.flash_cfg.cfg.clkInvert = 0x01, /*!< SPI clock phase invert,bit0:clck invert,bit1:rx invert,bit2-4:pad delay,bit5-7:pad delay */
|
||||
.flash_cfg.cfg.resetEnCmd = 0x66, /*!< Flash enable reset command */
|
||||
.flash_cfg.cfg.resetCmd = 0x99, /*!< Flash reset command */
|
||||
.flash_cfg.cfg.resetCreadCmd = 0xff, /*!< Flash reset continuous read command */
|
||||
.flash_cfg.cfg.resetCreadCmdSize = 0x03, /*!< Flash reset continuous read command size */
|
||||
.flash_cfg.cfg.jedecIdCmd = 0x9f, /*!< JEDEC ID command */
|
||||
.flash_cfg.cfg.jedecIdCmdDmyClk = 0x00, /*!< JEDEC ID command dummy clock */
|
||||
.flash_cfg.cfg.enter32BitsAddrCmd = 0xb7, /*!< Enter 32-bits addr command */
|
||||
.flash_cfg.cfg.exit32BitsAddrCmd = 0xe9, /*!< Exit 32-bits addr command */
|
||||
.flash_cfg.cfg.sectorSize = 0x04, /*!< *1024bytes */
|
||||
.flash_cfg.cfg.mid = 0x00, /*!< Manufacturer ID */
|
||||
.flash_cfg.cfg.pageSize = 0x100, /*!< Page size */
|
||||
.flash_cfg.cfg.chipEraseCmd = 0xc7, /*!< Chip erase cmd */
|
||||
.flash_cfg.cfg.sectorEraseCmd = 0x20, /*!< Sector erase command */
|
||||
.flash_cfg.cfg.blk32EraseCmd = 0x52, /*!< Block 32K erase command,some Micron not support */
|
||||
.flash_cfg.cfg.blk64EraseCmd = 0xd8, /*!< Block 64K erase command */
|
||||
.flash_cfg.cfg.writeEnableCmd = 0x06, /*!< Need before every erase or program */
|
||||
.flash_cfg.cfg.pageProgramCmd = 0x02, /*!< Page program cmd */
|
||||
.flash_cfg.cfg.qpageProgramCmd = 0x32, /*!< QIO page program cmd */
|
||||
.flash_cfg.cfg.qppAddrMode = 0x00, /*!< QIO page program address mode */
|
||||
.flash_cfg.cfg.fastReadCmd = 0x0b, /*!< Fast read command */
|
||||
.flash_cfg.cfg.frDmyClk = 0x01, /*!< Fast read command dummy clock */
|
||||
.flash_cfg.cfg.qpiFastReadCmd = 0x0b, /*!< QPI fast read command */
|
||||
.flash_cfg.cfg.qpiFrDmyClk = 0x01, /*!< QPI fast read command dummy clock */
|
||||
.flash_cfg.cfg.fastReadDoCmd = 0x3b, /*!< Fast read dual output command */
|
||||
.flash_cfg.cfg.frDoDmyClk = 0x01, /*!< Fast read dual output command dummy clock */
|
||||
.flash_cfg.cfg.fastReadDioCmd = 0xbb, /*!< Fast read dual io comamnd */
|
||||
.flash_cfg.cfg.frDioDmyClk = 0x00, /*!< Fast read dual io command dummy clock */
|
||||
.flash_cfg.cfg.fastReadQoCmd = 0x6b, /*!< Fast read quad output comamnd */
|
||||
.flash_cfg.cfg.frQoDmyClk = 0x01, /*!< Fast read quad output comamnd dummy clock */
|
||||
.flash_cfg.cfg.fastReadQioCmd = 0xeb, /*!< Fast read quad io comamnd */
|
||||
.flash_cfg.cfg.frQioDmyClk = 0x02, /*!< Fast read quad io comamnd dummy clock */
|
||||
.flash_cfg.cfg.qpiFastReadQioCmd = 0xeb, /*!< QPI fast read quad io comamnd */
|
||||
.flash_cfg.cfg.qpiFrQioDmyClk = 0x02, /*!< QPI fast read QIO dummy clock */
|
||||
.flash_cfg.cfg.qpiPageProgramCmd = 0x02, /*!< QPI program command */
|
||||
.flash_cfg.cfg.writeVregEnableCmd = 0x50, /*!< Enable write reg */
|
||||
.flash_cfg.cfg.wrEnableIndex = 0x00, /*!< Write enable register index */
|
||||
.flash_cfg.cfg.qeIndex = 0x01, /*!< Quad mode enable register index */
|
||||
.flash_cfg.cfg.busyIndex = 0x00, /*!< Busy status register index */
|
||||
.flash_cfg.cfg.wrEnableBit = 0x01, /*!< Write enable bit pos */
|
||||
.flash_cfg.cfg.qeBit = 0x01, /*!< Quad enable bit pos */
|
||||
.flash_cfg.cfg.busyBit = 0x00, /*!< Busy status bit pos */
|
||||
.flash_cfg.cfg.wrEnableWriteRegLen = 0x02, /*!< Register length of write enable */
|
||||
.flash_cfg.cfg.wrEnableReadRegLen = 0x01, /*!< Register length of write enable status */
|
||||
.flash_cfg.cfg.qeWriteRegLen = 0x02, /*!< Register length of contain quad enable */
|
||||
.flash_cfg.cfg.qeReadRegLen = 0x01, /*!< Register length of contain quad enable status */
|
||||
.flash_cfg.cfg.releasePowerDown = 0xab, /*!< Release power down command */
|
||||
.flash_cfg.cfg.busyReadRegLen = 0x01, /*!< Register length of contain busy status */
|
||||
.flash_cfg.cfg.readRegCmd[0] = 0x05, /*!< Read register command buffer */
|
||||
.flash_cfg.cfg.readRegCmd[1] = 0x35, /*!< Read register command buffer */
|
||||
.flash_cfg.cfg.readRegCmd[2] = 0x00, /*!< Read register command buffer */
|
||||
.flash_cfg.cfg.readRegCmd[3] = 0x00, /*!< Read register command buffer */
|
||||
.flash_cfg.cfg.writeRegCmd[0] = 0x01, /*!< Write register command buffer */
|
||||
.flash_cfg.cfg.writeRegCmd[1] = 0x01, /*!< Write register command buffer */
|
||||
.flash_cfg.cfg.writeRegCmd[2] = 0x00, /*!< Write register command buffer */
|
||||
.flash_cfg.cfg.writeRegCmd[3] = 0x00, /*!< Write register command buffer */
|
||||
.flash_cfg.cfg.enterQpi = 0x38, /*!< Enter qpi command */
|
||||
.flash_cfg.cfg.exitQpi = 0xff, /*!< Exit qpi command */
|
||||
.flash_cfg.cfg.cReadMode = 0x20, /*!< Config data for continuous read mode */
|
||||
.flash_cfg.cfg.cRExit = 0xf0, /*!< Config data for exit continuous read mode */
|
||||
.flash_cfg.cfg.burstWrapCmd = 0x77, /*!< Enable burst wrap command */
|
||||
.flash_cfg.cfg.burstWrapCmdDmyClk = 0x03, /*!< Enable burst wrap command dummy clock */
|
||||
.flash_cfg.cfg.burstWrapDataMode = 0x02, /*!< Data and address mode for this command */
|
||||
.flash_cfg.cfg.burstWrapData = 0x40, /*!< Data to enable burst wrap */
|
||||
.flash_cfg.cfg.deBurstWrapCmd = 0x77, /*!< Disable burst wrap command */
|
||||
.flash_cfg.cfg.deBurstWrapCmdDmyClk = 0x03, /*!< Disable burst wrap command dummy clock */
|
||||
.flash_cfg.cfg.deBurstWrapDataMode = 0x02, /*!< Data and address mode for this command */
|
||||
.flash_cfg.cfg.deBurstWrapData = 0xf0, /*!< Data to disable burst wrap */
|
||||
.flash_cfg.cfg.timeEsector = 300, /*!< 4K erase time */
|
||||
.flash_cfg.cfg.timeE32k = 1200, /*!< 32K erase time */
|
||||
.flash_cfg.cfg.timeE64k = 1200, /*!< 64K erase time */
|
||||
.flash_cfg.cfg.timePagePgm = 50, /*!< Page program time */
|
||||
.flash_cfg.cfg.timeCe = 30000, /*!< Chip erase time in ms */
|
||||
.flash_cfg.cfg.pdDelay = 20, /*!< Release power down command delay time for wake up */
|
||||
.flash_cfg.cfg.qeData = 0, /*!< QE set data */
|
||||
.flash_cfg.crc32 = 0xdeadbeef,
|
||||
/* clock cfg */
|
||||
.clk_cfg.magiccode = 0x47464350,
|
||||
.clk_cfg.cfg.xtal_type = 0x07, /*!< 0:None,1:24M,2:32M,3:38.4M,4:40M,5:26M,6:RC32M */
|
||||
.clk_cfg.cfg.mcu_clk = 0x04, /*!< mcu_clk 0:RC32M,1:Xtal,2:cpupll 400M,3:wifipll 192M,4:wifipll 320M */
|
||||
.clk_cfg.cfg.mcu_clk_div = 0x00,
|
||||
.clk_cfg.cfg.mcu_bclk_div = 0x00,
|
||||
|
||||
.clk_cfg.cfg.mcu_pbclk_div = 0x03,
|
||||
.clk_cfg.cfg.lp_div = 0x01,
|
||||
.clk_cfg.cfg.dsp_clk = 0x03, /* 0:RC32M,1:Xtal,2:wifipll 240M,3:wifipll 320M,4:cpupll 400M */
|
||||
.clk_cfg.cfg.dsp_clk_div = 0x00,
|
||||
|
||||
.clk_cfg.cfg.dsp_bclk_div = 0x01,
|
||||
.clk_cfg.cfg.dsp_pbclk = 0x02, /* 0:RC32M,1:Xtal,2:wifipll 160M,3:cpupll 160M,4:wifipll 240M */
|
||||
.clk_cfg.cfg.dsp_pbclk_div = 0x00,
|
||||
.clk_cfg.cfg.emi_clk = 0x02, /*!< 0:mcu pbclk,1:cpupll 200M,2:wifipll 320M,3:cpupll 400M */
|
||||
|
||||
.clk_cfg.cfg.emi_clk_div = 0x01,
|
||||
.clk_cfg.cfg.flash_clk_type = 0x01, /*!< 0:wifipll 120M,1:xtal,2:cpupll 100M,3:wifipll 80M,4:bclk,5:wifipll 96M */
|
||||
.clk_cfg.cfg.flash_clk_div = 0x00,
|
||||
.clk_cfg.cfg.wifipll_pu = 0x01,
|
||||
|
||||
.clk_cfg.cfg.aupll_pu = 0x01,
|
||||
.clk_cfg.cfg.cpupll_pu = 0x01,
|
||||
.clk_cfg.cfg.mipipll_pu = 0x01,
|
||||
.clk_cfg.cfg.uhspll_pu = 0x01,
|
||||
|
||||
.clk_cfg.crc32 = 0xdeadbeef,
|
||||
|
||||
/* basic cfg */
|
||||
.basic_cfg.sign_type = 0x0, /* [1: 0] for sign */
|
||||
.basic_cfg.encrypt_type = 0x0, /* [3: 2] for encrypt */
|
||||
.basic_cfg.key_sel = 0x0, /* [5: 4] key slot */
|
||||
.basic_cfg.xts_mode = 0x0, /* [6] for xts mode */
|
||||
.basic_cfg.aes_region_lock = 0x0, /* [7] rsvd */
|
||||
.basic_cfg.no_segment = 0x1, /* [8] no segment info */
|
||||
.basic_cfg.rsvd_0 = 0x0, /* [9] boot2 enable(rsvd_0) */
|
||||
.basic_cfg.rsvd_1 = 0x0, /* [10] boot2 rollback(rsvd_1) */
|
||||
.basic_cfg.cpu_master_id = 0x0, /* [14: 11] master id */
|
||||
.basic_cfg.notload_in_bootrom = 0x0, /* [15] notload in bootrom */
|
||||
.basic_cfg.crc_ignore = 0x1, /* [16] ignore crc */
|
||||
.basic_cfg.hash_ignore = 0x1, /* [17] hash ignore */
|
||||
.basic_cfg.power_on_mm = 0x1, /* [18] power on mm */
|
||||
.basic_cfg.em_sel = 0x1, /* [21: 19] em_sel */
|
||||
.basic_cfg.cmds_en = 0x1, /* [22] command spliter enable */
|
||||
#if 0
|
||||
# 0 : cmds bypass wrap commands to macro, original mode;
|
||||
# 1 : cmds handle wrap commands, original mode;
|
||||
# 2 : cmds bypass wrap commands to macro, cmds force wrap16 * 4 splitted into two wrap8 * 4;
|
||||
# 3 : cmds handle wrap commands, cmds force wrap16 * 4 splitted into two wrap8 * 4
|
||||
#endif
|
||||
.basic_cfg.cmds_wrap_mode = 0x1, /* [24: 23] cmds wrap mode */
|
||||
#if 0
|
||||
# 0 : SF_CTRL_WRAP_LEN_8, 1 : SF_CTRL_WRAP_LEN_16, 2 : SF_CTRL_WRAP_LEN_32,
|
||||
# 3 : SF_CTRL_WRAP_LEN_64, 9 : SF_CTRL_WRAP_LEN_4096
|
||||
#endif
|
||||
.basic_cfg.cmds_wrap_len = 0x9, /* [28: 25] cmds wrap len */
|
||||
.basic_cfg.icache_invalid = 0x1, /* [29] icache invalid */
|
||||
.basic_cfg.dcache_invalid = 0x1, /* [30] dcache invalid */
|
||||
.basic_cfg.rsvd_3 = 0x0, /* [31] rsvd_3 */
|
||||
|
||||
.basic_cfg.group_image_offset = 0x00002000, /* flash controller offset */
|
||||
.basic_cfg.aes_region_len = 0x00000000, /* aes region length */
|
||||
|
||||
.basic_cfg.img_len_cnt = 0x00004000, /* image length or segment count */
|
||||
.basic_cfg.hash = { 0xdeadbeef }, /* hash of the image */
|
||||
|
||||
/* cpu cfg */
|
||||
.cpu_cfg[0].config_enable = 0x01, /* coinfig this cpu */
|
||||
.cpu_cfg[0].halt_cpu = 0x0, /* halt this cpu */
|
||||
.cpu_cfg[0].cache_enable = 0x0, /* cache setting :only for BL Cache */
|
||||
.cpu_cfg[0].cache_wa = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[0].cache_wb = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[0].cache_wt = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[0].cache_way_dis = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[0].rsvd = 0x0,
|
||||
|
||||
.cpu_cfg[0].cache_range_h = 0x00000000,
|
||||
.cpu_cfg[0].cache_range_l = 0x00000000,
|
||||
/* image_address_offset */
|
||||
.cpu_cfg[0].image_address_offset = 0x0,
|
||||
.cpu_cfg[0].rsvd0 = 0x58000000, /* rsvd0 */
|
||||
.cpu_cfg[0].msp_val = 0x00000000, /* msp value */
|
||||
|
||||
/* cpu cfg */
|
||||
.cpu_cfg[1].config_enable = 0x00, /* coinfig this cpu */
|
||||
.cpu_cfg[1].halt_cpu = 0x0, /* halt this cpu */
|
||||
.cpu_cfg[1].cache_enable = 0x0, /* cache setting :only for BL Cache */
|
||||
.cpu_cfg[1].cache_wa = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[1].cache_wb = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[1].cache_wt = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[1].cache_way_dis = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[1].rsvd = 0x0,
|
||||
|
||||
.cpu_cfg[1].cache_range_h = 0x00000000,
|
||||
.cpu_cfg[1].cache_range_l = 0x00000000,
|
||||
/* image_address_offset */
|
||||
.cpu_cfg[1].image_address_offset = 0x0,
|
||||
.cpu_cfg[1].rsvd0 = 0x58000000, /* rsvd0 */
|
||||
.cpu_cfg[1].msp_val = 0x00000000, /* msp value */
|
||||
|
||||
/* address of partition table 0 */ /* 4 */
|
||||
.boot2_pt_table_0_rsvd = 0x00000000,
|
||||
/* address of partition table 1 */ /* 4 */
|
||||
.boot2_pt_table_1_rsvd = 0x00000000,
|
||||
|
||||
/* address of flashcfg table list */ /* 4 */
|
||||
.flash_cfg_table_addr = 0x00000000,
|
||||
/* flashcfg table list len */ /* 4 */
|
||||
.flash_cfg_table_len = 0x00000000,
|
||||
|
||||
.rsvd1[0] = 0x20000320,
|
||||
.rsvd1[1] = 0x00000000,
|
||||
.rsvd1[2] = 0x2000F038,
|
||||
.rsvd1[3] = 0x18000000,
|
||||
|
||||
.crc32 = 0xdeadbeef /* 4 */
|
||||
};
|
||||
|
||||
__attribute__((section(".fw_header1"))) struct bootheader_t fw_header1 = {
|
||||
.magiccode = 0x50414642,
|
||||
.rivison = 0x00000001,
|
||||
/*flash config */
|
||||
.flash_cfg.magiccode = 0x47464346,
|
||||
.flash_cfg.cfg.ioMode = 0x10, /*!< Serail flash interface mode,bit0-3:IF mode,bit4:unwrap */
|
||||
.flash_cfg.cfg.cReadSupport = 0x00, /*!< Support continuous read mode,bit0:continuous read mode support,bit1:read mode cfg */
|
||||
.flash_cfg.cfg.clkDelay = 0x01, /*!< SPI clock delay,bit0-3:delay,bit4-6:pad delay */
|
||||
.flash_cfg.cfg.clkInvert = 0x01, /*!< SPI clock phase invert,bit0:clck invert,bit1:rx invert,bit2-4:pad delay,bit5-7:pad delay */
|
||||
.flash_cfg.cfg.resetEnCmd = 0x66, /*!< Flash enable reset command */
|
||||
.flash_cfg.cfg.resetCmd = 0x99, /*!< Flash reset command */
|
||||
.flash_cfg.cfg.resetCreadCmd = 0xff, /*!< Flash reset continuous read command */
|
||||
.flash_cfg.cfg.resetCreadCmdSize = 0x03, /*!< Flash reset continuous read command size */
|
||||
.flash_cfg.cfg.jedecIdCmd = 0x9f, /*!< JEDEC ID command */
|
||||
.flash_cfg.cfg.jedecIdCmdDmyClk = 0x00, /*!< JEDEC ID command dummy clock */
|
||||
.flash_cfg.cfg.enter32BitsAddrCmd = 0xb7, /*!< Enter 32-bits addr command */
|
||||
.flash_cfg.cfg.exit32BitsAddrCmd = 0xe9, /*!< Exit 32-bits addr command */
|
||||
.flash_cfg.cfg.sectorSize = 0x04, /*!< *1024bytes */
|
||||
.flash_cfg.cfg.mid = 0x00, /*!< Manufacturer ID */
|
||||
.flash_cfg.cfg.pageSize = 0x100, /*!< Page size */
|
||||
.flash_cfg.cfg.chipEraseCmd = 0xc7, /*!< Chip erase cmd */
|
||||
.flash_cfg.cfg.sectorEraseCmd = 0x20, /*!< Sector erase command */
|
||||
.flash_cfg.cfg.blk32EraseCmd = 0x52, /*!< Block 32K erase command,some Micron not support */
|
||||
.flash_cfg.cfg.blk64EraseCmd = 0xd8, /*!< Block 64K erase command */
|
||||
.flash_cfg.cfg.writeEnableCmd = 0x06, /*!< Need before every erase or program */
|
||||
.flash_cfg.cfg.pageProgramCmd = 0x02, /*!< Page program cmd */
|
||||
.flash_cfg.cfg.qpageProgramCmd = 0x32, /*!< QIO page program cmd */
|
||||
.flash_cfg.cfg.qppAddrMode = 0x00, /*!< QIO page program address mode */
|
||||
.flash_cfg.cfg.fastReadCmd = 0x0b, /*!< Fast read command */
|
||||
.flash_cfg.cfg.frDmyClk = 0x01, /*!< Fast read command dummy clock */
|
||||
.flash_cfg.cfg.qpiFastReadCmd = 0x0b, /*!< QPI fast read command */
|
||||
.flash_cfg.cfg.qpiFrDmyClk = 0x01, /*!< QPI fast read command dummy clock */
|
||||
.flash_cfg.cfg.fastReadDoCmd = 0x3b, /*!< Fast read dual output command */
|
||||
.flash_cfg.cfg.frDoDmyClk = 0x01, /*!< Fast read dual output command dummy clock */
|
||||
.flash_cfg.cfg.fastReadDioCmd = 0xbb, /*!< Fast read dual io comamnd */
|
||||
.flash_cfg.cfg.frDioDmyClk = 0x00, /*!< Fast read dual io command dummy clock */
|
||||
.flash_cfg.cfg.fastReadQoCmd = 0x6b, /*!< Fast read quad output comamnd */
|
||||
.flash_cfg.cfg.frQoDmyClk = 0x01, /*!< Fast read quad output comamnd dummy clock */
|
||||
.flash_cfg.cfg.fastReadQioCmd = 0xeb, /*!< Fast read quad io comamnd */
|
||||
.flash_cfg.cfg.frQioDmyClk = 0x02, /*!< Fast read quad io comamnd dummy clock */
|
||||
.flash_cfg.cfg.qpiFastReadQioCmd = 0xeb, /*!< QPI fast read quad io comamnd */
|
||||
.flash_cfg.cfg.qpiFrQioDmyClk = 0x02, /*!< QPI fast read QIO dummy clock */
|
||||
.flash_cfg.cfg.qpiPageProgramCmd = 0x02, /*!< QPI program command */
|
||||
.flash_cfg.cfg.writeVregEnableCmd = 0x50, /*!< Enable write reg */
|
||||
.flash_cfg.cfg.wrEnableIndex = 0x00, /*!< Write enable register index */
|
||||
.flash_cfg.cfg.qeIndex = 0x01, /*!< Quad mode enable register index */
|
||||
.flash_cfg.cfg.busyIndex = 0x00, /*!< Busy status register index */
|
||||
.flash_cfg.cfg.wrEnableBit = 0x01, /*!< Write enable bit pos */
|
||||
.flash_cfg.cfg.qeBit = 0x01, /*!< Quad enable bit pos */
|
||||
.flash_cfg.cfg.busyBit = 0x00, /*!< Busy status bit pos */
|
||||
.flash_cfg.cfg.wrEnableWriteRegLen = 0x02, /*!< Register length of write enable */
|
||||
.flash_cfg.cfg.wrEnableReadRegLen = 0x01, /*!< Register length of write enable status */
|
||||
.flash_cfg.cfg.qeWriteRegLen = 0x02, /*!< Register length of contain quad enable */
|
||||
.flash_cfg.cfg.qeReadRegLen = 0x01, /*!< Register length of contain quad enable status */
|
||||
.flash_cfg.cfg.releasePowerDown = 0xab, /*!< Release power down command */
|
||||
.flash_cfg.cfg.busyReadRegLen = 0x01, /*!< Register length of contain busy status */
|
||||
.flash_cfg.cfg.readRegCmd[0] = 0x05, /*!< Read register command buffer */
|
||||
.flash_cfg.cfg.readRegCmd[1] = 0x35, /*!< Read register command buffer */
|
||||
.flash_cfg.cfg.readRegCmd[2] = 0x00, /*!< Read register command buffer */
|
||||
.flash_cfg.cfg.readRegCmd[3] = 0x00, /*!< Read register command buffer */
|
||||
.flash_cfg.cfg.writeRegCmd[0] = 0x01, /*!< Write register command buffer */
|
||||
.flash_cfg.cfg.writeRegCmd[1] = 0x01, /*!< Write register command buffer */
|
||||
.flash_cfg.cfg.writeRegCmd[2] = 0x00, /*!< Write register command buffer */
|
||||
.flash_cfg.cfg.writeRegCmd[3] = 0x00, /*!< Write register command buffer */
|
||||
.flash_cfg.cfg.enterQpi = 0x38, /*!< Enter qpi command */
|
||||
.flash_cfg.cfg.exitQpi = 0xff, /*!< Exit qpi command */
|
||||
.flash_cfg.cfg.cReadMode = 0x20, /*!< Config data for continuous read mode */
|
||||
.flash_cfg.cfg.cRExit = 0xf0, /*!< Config data for exit continuous read mode */
|
||||
.flash_cfg.cfg.burstWrapCmd = 0x77, /*!< Enable burst wrap command */
|
||||
.flash_cfg.cfg.burstWrapCmdDmyClk = 0x03, /*!< Enable burst wrap command dummy clock */
|
||||
.flash_cfg.cfg.burstWrapDataMode = 0x02, /*!< Data and address mode for this command */
|
||||
.flash_cfg.cfg.burstWrapData = 0x40, /*!< Data to enable burst wrap */
|
||||
.flash_cfg.cfg.deBurstWrapCmd = 0x77, /*!< Disable burst wrap command */
|
||||
.flash_cfg.cfg.deBurstWrapCmdDmyClk = 0x03, /*!< Disable burst wrap command dummy clock */
|
||||
.flash_cfg.cfg.deBurstWrapDataMode = 0x02, /*!< Data and address mode for this command */
|
||||
.flash_cfg.cfg.deBurstWrapData = 0xf0, /*!< Data to disable burst wrap */
|
||||
.flash_cfg.cfg.timeEsector = 300, /*!< 4K erase time */
|
||||
.flash_cfg.cfg.timeE32k = 1200, /*!< 32K erase time */
|
||||
.flash_cfg.cfg.timeE64k = 1200, /*!< 64K erase time */
|
||||
.flash_cfg.cfg.timePagePgm = 50, /*!< Page program time */
|
||||
.flash_cfg.cfg.timeCe = 30000, /*!< Chip erase time in ms */
|
||||
.flash_cfg.cfg.pdDelay = 20, /*!< Release power down command delay time for wake up */
|
||||
.flash_cfg.cfg.qeData = 0, /*!< QE set data */
|
||||
.flash_cfg.crc32 = 0xdeadbeef,
|
||||
/* clock cfg */
|
||||
.clk_cfg.magiccode = 0x47464350,
|
||||
.clk_cfg.cfg.xtal_type = 0x07, /*!< 0:None,1:24M,2:32M,3:38.4M,4:40M,5:26M,6:RC32M */
|
||||
.clk_cfg.cfg.mcu_clk = 0x04, /*!< mcu_clk 0:RC32M,1:Xtal,2:cpupll 400M,3:wifipll 192M,4:wifipll 320M */
|
||||
.clk_cfg.cfg.mcu_clk_div = 0x00,
|
||||
.clk_cfg.cfg.mcu_bclk_div = 0x00,
|
||||
|
||||
.clk_cfg.cfg.mcu_pbclk_div = 0x03,
|
||||
.clk_cfg.cfg.lp_div = 0x01,
|
||||
.clk_cfg.cfg.dsp_clk = 0x03, /* 0:RC32M,1:Xtal,2:wifipll 240M,3:wifipll 320M,4:cpupll 400M */
|
||||
.clk_cfg.cfg.dsp_clk_div = 0x00,
|
||||
|
||||
.clk_cfg.cfg.dsp_bclk_div = 0x01,
|
||||
.clk_cfg.cfg.dsp_pbclk = 0x02, /* 0:RC32M,1:Xtal,2:wifipll 160M,3:cpupll 160M,4:wifipll 240M */
|
||||
.clk_cfg.cfg.dsp_pbclk_div = 0x00,
|
||||
.clk_cfg.cfg.emi_clk = 0x02, /*!< 0:mcu pbclk,1:cpupll 200M,2:wifipll 320M,3:cpupll 400M */
|
||||
|
||||
.clk_cfg.cfg.emi_clk_div = 0x01,
|
||||
.clk_cfg.cfg.flash_clk_type = 0x01, /*!< 0:wifipll 120M,1:xtal,2:cpupll 100M,3:wifipll 80M,4:bclk,5:wifipll 96M */
|
||||
.clk_cfg.cfg.flash_clk_div = 0x00,
|
||||
.clk_cfg.cfg.wifipll_pu = 0x01,
|
||||
|
||||
.clk_cfg.cfg.aupll_pu = 0x01,
|
||||
.clk_cfg.cfg.cpupll_pu = 0x01,
|
||||
.clk_cfg.cfg.mipipll_pu = 0x01,
|
||||
.clk_cfg.cfg.uhspll_pu = 0x01,
|
||||
|
||||
.clk_cfg.crc32 = 0xdeadbeef,
|
||||
|
||||
/* basic cfg */
|
||||
.basic_cfg.sign_type = 0x0, /* [1: 0] for sign */
|
||||
.basic_cfg.encrypt_type = 0x0, /* [3: 2] for encrypt */
|
||||
.basic_cfg.key_sel = 0x0, /* [5: 4] key slot */
|
||||
.basic_cfg.xts_mode = 0x0, /* [6] for xts mode */
|
||||
.basic_cfg.aes_region_lock = 0x0, /* [7] rsvd */
|
||||
.basic_cfg.no_segment = 0x1, /* [8] no segment info */
|
||||
.basic_cfg.rsvd_0 = 0x0, /* [9] boot2 enable(rsvd_0) */
|
||||
.basic_cfg.rsvd_1 = 0x0, /* [10] boot2 rollback(rsvd_1) */
|
||||
.basic_cfg.cpu_master_id = 0x0, /* [14: 11] master id */
|
||||
.basic_cfg.notload_in_bootrom = 0x0, /* [15] notload in bootrom */
|
||||
.basic_cfg.crc_ignore = 0x1, /* [16] ignore crc */
|
||||
.basic_cfg.hash_ignore = 0x1, /* [17] hash ignore */
|
||||
.basic_cfg.power_on_mm = 0x1, /* [18] power on mm */
|
||||
.basic_cfg.em_sel = 0x1, /* [21: 19] em_sel */
|
||||
.basic_cfg.cmds_en = 0x1, /* [22] command spliter enable */
|
||||
#if 0
|
||||
# 0 : cmds bypass wrap commands to macro, original mode;
|
||||
# 1 : cmds handle wrap commands, original mode;
|
||||
# 2 : cmds bypass wrap commands to macro, cmds force wrap16 * 4 splitted into two wrap8 * 4;
|
||||
# 3 : cmds handle wrap commands, cmds force wrap16 * 4 splitted into two wrap8 * 4
|
||||
#endif
|
||||
.basic_cfg.cmds_wrap_mode = 0x1, /* [24: 23] cmds wrap mode */
|
||||
#if 0
|
||||
# 0 : SF_CTRL_WRAP_LEN_8, 1 : SF_CTRL_WRAP_LEN_16, 2 : SF_CTRL_WRAP_LEN_32,
|
||||
# 3 : SF_CTRL_WRAP_LEN_64, 9 : SF_CTRL_WRAP_LEN_4096
|
||||
#endif
|
||||
.basic_cfg.cmds_wrap_len = 0x9, /* [28: 25] cmds wrap len */
|
||||
.basic_cfg.icache_invalid = 0x1, /* [29] icache invalid */
|
||||
.basic_cfg.dcache_invalid = 0x1, /* [30] dcache invalid */
|
||||
.basic_cfg.rsvd_3 = 0x0, /* [31] rsvd_3 */
|
||||
|
||||
.basic_cfg.group_image_offset = 0x00011000, /* flash controller offset */
|
||||
.basic_cfg.aes_region_len = 0x00000000, /* aes region length */
|
||||
|
||||
.basic_cfg.img_len_cnt = 0x00004000, /* image length or segment count */
|
||||
.basic_cfg.hash = { 0xdeadbeef }, /* hash of the image */
|
||||
|
||||
/* cpu cfg */
|
||||
.cpu_cfg[0].config_enable = 0x00, /* coinfig this cpu */
|
||||
.cpu_cfg[0].halt_cpu = 0x0, /* halt this cpu */
|
||||
.cpu_cfg[0].cache_enable = 0x0, /* cache setting :only for BL Cache */
|
||||
.cpu_cfg[0].cache_wa = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[0].cache_wb = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[0].cache_wt = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[0].cache_way_dis = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[0].rsvd = 0x0,
|
||||
|
||||
.cpu_cfg[0].cache_range_h = 0x00000000,
|
||||
.cpu_cfg[0].cache_range_l = 0x00000000,
|
||||
/* image_address_offset */
|
||||
.cpu_cfg[0].image_address_offset = 0x0,
|
||||
|
||||
.cpu_cfg[0].rsvd0 = 0x58000000, /* rsvd0 */
|
||||
.cpu_cfg[0].msp_val = 0x00000000, /* msp value */
|
||||
|
||||
/* cpu cfg */
|
||||
.cpu_cfg[1].config_enable = 0x01, /* coinfig this cpu */
|
||||
.cpu_cfg[1].halt_cpu = 0x0, /* halt this cpu */
|
||||
.cpu_cfg[1].cache_enable = 0x0, /* cache setting :only for BL Cache */
|
||||
.cpu_cfg[1].cache_wa = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[1].cache_wb = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[1].cache_wt = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[1].cache_way_dis = 0x0, /* cache setting :only for BL Cache*/
|
||||
.cpu_cfg[1].rsvd = 0x0,
|
||||
|
||||
.cpu_cfg[1].cache_range_h = 0x00000000,
|
||||
.cpu_cfg[1].cache_range_l = 0x00000000,
|
||||
/* image_address_offset */
|
||||
.cpu_cfg[1].image_address_offset = 0x0,
|
||||
.cpu_cfg[1].rsvd0 = 0x58000000, /* rsvd0 */
|
||||
.cpu_cfg[1].msp_val = 0x00000000, /* msp value */
|
||||
|
||||
/* address of partition table 0 */ /* 4 */
|
||||
.boot2_pt_table_0_rsvd = 0x00000000,
|
||||
/* address of partition table 1 */ /* 4 */
|
||||
.boot2_pt_table_1_rsvd = 0x00000000,
|
||||
|
||||
/* address of flashcfg table list */ /* 4 */
|
||||
.flash_cfg_table_addr = 0x00000000,
|
||||
/* flashcfg table list len */ /* 4 */
|
||||
.flash_cfg_table_len = 0x00000000,
|
||||
|
||||
.crc32 = 0xdeadbeef /* 4 */
|
||||
};
|
282
cmake/SDKconfig
Normal file
282
cmake/SDKconfig
Normal file
|
@ -0,0 +1,282 @@
|
|||
|
||||
mainmenu "Pine64 OX64 SDK configuration"
|
||||
|
||||
menu "Application"
|
||||
osource "Kconfig"
|
||||
endmenu
|
||||
|
||||
menu "Board Support Configuration"
|
||||
menu "$(BFLB_BOARD) Board Config"
|
||||
source "$(BFLB_BOARD_DIR)/$(BFLB_BOARD)/Kconfig"
|
||||
endmenu
|
||||
|
||||
config PSRAM
|
||||
bool "Enable PSRAM"
|
||||
default y
|
||||
|
||||
config ETHERNET
|
||||
bool "Enable Ethernet"
|
||||
default n
|
||||
|
||||
config BSP_SDH_SDCARD
|
||||
bool "Enable SD SDHCI Driver Support"
|
||||
default n
|
||||
|
||||
config BSP_SPI_SDCARD
|
||||
bool "Enable SD SPI Driver Support"
|
||||
default n
|
||||
|
||||
config BSP_LCD
|
||||
bool "Enable LCD Driver Support"
|
||||
default n
|
||||
|
||||
config BSP_IMAGE_SENSOR
|
||||
bool "Enable Image Sensor Driver Support"
|
||||
default n
|
||||
endmenu
|
||||
|
||||
menu "CPU Configuration"
|
||||
config BFLB_CHIP
|
||||
string
|
||||
default "$(BFLB_CHIP)"
|
||||
config BLFB_CPU_ID
|
||||
string
|
||||
default "$(BFLB_CPU_ID)"
|
||||
|
||||
config ROMAPI
|
||||
bool "Enable ROM API"
|
||||
default y
|
||||
endmenu
|
||||
|
||||
|
||||
menu "SDK configuration"
|
||||
menu "Logging Configuration"
|
||||
choice LOG_TYPE
|
||||
prompt "Logging Type"
|
||||
default BFLOG
|
||||
help
|
||||
Select the logging type to use.
|
||||
config BFLOG
|
||||
bool "Use BFLOG Implementation"
|
||||
depends on VLIBC
|
||||
config LOG
|
||||
bool "Use Basic LOG_* Functions"
|
||||
config LOG_DISABLE
|
||||
bool "No Logging"
|
||||
endchoice
|
||||
menu "Logging Options"
|
||||
visible if !LOG_DISABLE
|
||||
config LOG_LEVEL
|
||||
int "Logging Level"
|
||||
default 3
|
||||
range 0 5
|
||||
depends on !LOG_DISABLE
|
||||
help
|
||||
Higher Levels mean more logging
|
||||
|
||||
config BFLOG_POOL_SIZE
|
||||
int "BFLOG Pool Size"
|
||||
default 1024
|
||||
depends on BFLOG
|
||||
help
|
||||
Number of bytes to allocate for BFLOG
|
||||
|
||||
config BFLOG_USER
|
||||
bool "Enable Custom BFLOG Header File"
|
||||
default n
|
||||
depends on BFLOG
|
||||
help
|
||||
Enable BFLOG User Header File
|
||||
|
||||
config BFLOG_DEBUG
|
||||
bool "Enable BFLOG Debugging"
|
||||
default n
|
||||
depends on BFLOG
|
||||
help
|
||||
Enable BFLOG Debug
|
||||
endmenu
|
||||
|
||||
config ASSERT_DISABLE
|
||||
bool "Disable ASSERT"
|
||||
default n
|
||||
endmenu
|
||||
menu "Libc Configuration"
|
||||
choice LIBC_TYPE
|
||||
prompt "LibC Type"
|
||||
default LIBC
|
||||
help
|
||||
Select the Libc implementation to use.
|
||||
config VLIBC
|
||||
bool "VFS Libc Support"
|
||||
help
|
||||
VLIBC supports basic hosting (open/close/read/write) support
|
||||
config LIBC
|
||||
bool "Basic Libc Support"
|
||||
help
|
||||
LIBC supports basic libc functions only
|
||||
endchoice
|
||||
config VLIBC_DEBUG
|
||||
bool "Enable VFS Libc Debug"
|
||||
default n
|
||||
depends on VLIBC
|
||||
config VLIBC_FATFS
|
||||
bool "Enable FATFS Support"
|
||||
default n
|
||||
depends on VLIBC
|
||||
depends on FATFS
|
||||
menu "Printf Support"
|
||||
config VSNPRINTFNANO
|
||||
bool "Enable VSNPRINTF NANO Support"
|
||||
default n
|
||||
depends on LIBC
|
||||
config CONFIG_VSNPRINTF_FLOAT
|
||||
bool "Enable VSNPRINTF FLOAT Support"
|
||||
default y
|
||||
config VSNPRINTF_FLOAT_EX
|
||||
bool "Enable VSNPRINTF FLOAT EX Support"
|
||||
default y
|
||||
config VSNPRINTF_LONG_LONG
|
||||
bool "Enable VSNPRINTF LONG LONG Support"
|
||||
default y
|
||||
config VSNPRINTF_WRITEBACK
|
||||
bool "Enable VSNPRINTF WRITEBACK Support"
|
||||
default n
|
||||
endmenu
|
||||
config TLSF
|
||||
bool "Enable TLSF Malloc Library"
|
||||
default n
|
||||
config MMHEAP_USER
|
||||
bool "Enable MMHEAP User Malloc Library"
|
||||
default n
|
||||
depends on !TLSF
|
||||
menu "Block Pool"
|
||||
config BFLB_BLOCK_POOL_DEBUG
|
||||
bool "Enable Block Pool Debug"
|
||||
default n
|
||||
config BFLB_BLOCK_POOL_MTX_TIMEOUT
|
||||
int "Block Pool Mutex Timeout"
|
||||
default 100
|
||||
range 0 1000
|
||||
endmenu
|
||||
config CONFIG_TIMEZONE
|
||||
int "Timezone offset"
|
||||
default 8
|
||||
range 0 24
|
||||
help
|
||||
Timezone offset in hours
|
||||
|
||||
endmenu
|
||||
menu "FileSystem Configuration"
|
||||
config FATFS
|
||||
bool "Enable FATFS Support"
|
||||
default n
|
||||
config FF_FS_REENTRANT
|
||||
bool "Enable Re-entrant Support in FatFS"
|
||||
default n
|
||||
depends on FATFS
|
||||
config FATFS_SDH_SDCARD
|
||||
bool "Enable SD Card Support for FatFS"
|
||||
default y if BSP_SDH_SDCARD || BSP_SPI_SDCARD
|
||||
depends on FATFS
|
||||
depends on BSP_SDH_SDCARD || BSP_SPI_SDCARD
|
||||
endmenu
|
||||
menu "SDK Components"
|
||||
config SHELL
|
||||
bool "Enable Shell"
|
||||
default n
|
||||
config FREERTOS
|
||||
bool "Enable FreeRTOS"
|
||||
default n
|
||||
config CHERRYUSB
|
||||
bool "Enable Cherry USB"
|
||||
default n
|
||||
menu "CherryUSB Options"
|
||||
visible if CHERRYUSB
|
||||
|
||||
config CHERRYUSB_DEVICE
|
||||
bool "USB Device Support"
|
||||
depends on CHERRYUSB
|
||||
default y
|
||||
|
||||
menu "CherryUSB Device Options"
|
||||
visible if CHERRYUSB_DEVICE
|
||||
|
||||
config CONFIG_USB_ALIGN_SIZE
|
||||
int "Alignment Size"
|
||||
default 32
|
||||
range 0 1024
|
||||
depends on CHERRYUSB_DEVICE
|
||||
|
||||
config CONFIG_USB_HS
|
||||
bool "Enable High Speed Support"
|
||||
default y
|
||||
depends on CHERRYUSB_DEVICE
|
||||
|
||||
config CHERRYUSB_DEVICE_CDC
|
||||
bool "Enable CDC Device Support"
|
||||
default y
|
||||
depends on CHERRYUSB_DEVICE
|
||||
|
||||
config CHERRYUSB_DEVICE_HID
|
||||
bool "Enable HID Device Support"
|
||||
default y
|
||||
depends on CHERRYUSB_DEVICE
|
||||
|
||||
config CHERRYUSB_DEVICE_MSC
|
||||
bool "Enable MSC Device Support"
|
||||
default y
|
||||
depends on CHERRYUSB_DEVICE
|
||||
|
||||
config CHERRYUSB_DEVICE_AUDIO
|
||||
bool "Enable AUDIO Device Support"
|
||||
default y
|
||||
depends on CHERRYUSB_DEVICE
|
||||
|
||||
config CHERRYUSB_DEVICE_VIDEO
|
||||
bool "Enable VIDEO Device Support"
|
||||
default y
|
||||
depends on CHERRYUSB_DEVICE
|
||||
endmenu
|
||||
|
||||
config CHERRYUSB_HOST
|
||||
bool "USB Host Support"
|
||||
depends on CHERRYUSB
|
||||
default y
|
||||
endmenu
|
||||
config LUA
|
||||
bool "Enable Lua"
|
||||
default n
|
||||
|
||||
menu "Lua Options"
|
||||
visible if LUA
|
||||
|
||||
config LUA_LHAL
|
||||
bool "Enable Lua HAL Support"
|
||||
default y
|
||||
depends on LUA
|
||||
|
||||
endmenu
|
||||
config LVGL
|
||||
bool "Enable LVGL"
|
||||
default n
|
||||
config LWIP
|
||||
bool "Enable LWIP"
|
||||
default n
|
||||
config BLUETOOTH
|
||||
bool "Enable Bluetooth"
|
||||
default n
|
||||
config XZ
|
||||
bool "Enable XZ"
|
||||
default n
|
||||
config TINYMAIX
|
||||
bool "Enable TinyMaix"
|
||||
default n
|
||||
config TENSORFLOWLITE
|
||||
bool "Enable Tensorflow Lite"
|
||||
default n
|
||||
endmenu
|
||||
endmenu
|
||||
|
||||
menu "Custom Components"
|
||||
osource "${PINE64_SDK_PATH}/components/*/Kconfig"
|
||||
endmenu
|
4
cmake/bflbsdk.cmake
Normal file
4
cmake/bflbsdk.cmake
Normal file
|
@ -0,0 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
|
||||
include(${SDK_PATH}/cmake/kconfig.cmake)
|
||||
|
13
cmake/kconfig.cmake
Normal file
13
cmake/kconfig.cmake
Normal file
|
@ -0,0 +1,13 @@
|
|||
message("Running KConfig")
|
||||
add_custom_target(config-dir ALL
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory config)
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/config/sdkconfig.h
|
||||
COMMAND ${SDK_PATH}/tools/kconfig/gensdkconfig.py --sdkpath ${SDK_PATH} --header ${CMAKE_CURRENT_BINARY_DIR}/config/ --projectdir ${CMAKE_CURRENT_SOURCE_DIR} --env BFLB_BOARD_DIR=${BOARD_DIR} --env BFLB_BOARD=${BOARD} --env BFLB_CHIP=${CHIP} --env BFLB_CPU_ID=${CPU_ID}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/sdkconfig
|
||||
COMMENT "Generating SDKConfig"
|
||||
VERBATIM)
|
||||
|
||||
target_sources(app PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/config/sdkconfig.h)
|
||||
|
||||
target_include_directories(app PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/config)
|
31
cmake/project.build
Normal file
31
cmake/project.build
Normal file
|
@ -0,0 +1,31 @@
|
|||
BL_SDK_BASE ?= ${PINE64_SDK_PATH}/../bl_mcu_sdk
|
||||
|
||||
export BL_SDK_BASE
|
||||
|
||||
CHIP ?= bl808
|
||||
BOARD ?= ox64
|
||||
CPU_ID ?= m0
|
||||
BOARD_DIR ?= ${PINE64_SDK_PATH}/bsp
|
||||
|
||||
CROSS_COMPILE ?= riscv64-unknown-elf-
|
||||
|
||||
.PHONY:config
|
||||
|
||||
default: proj.conf
|
||||
@$(MAKE) build
|
||||
|
||||
sdkconfig:
|
||||
@echo "Generating sdkconfig from sdkconfig.default"
|
||||
@${PINE64_SDK_PATH}/tools/kconfig/gensdkconfig.py --sdkpath ${PINE64_SDK_PATH} --projectdir ${PWD} --env BFLB_BOARD_DIR=${BOARD_DIR} --env BFLB_BOARD=${BOARD} --env BFLB_CHIP=${CHIP} --env BFLB_CPU_ID=${CPU_ID}
|
||||
|
||||
proj.conf: sdkconfig
|
||||
@echo "Generating proj.conf from sdkconfig"
|
||||
@${PINE64_SDK_PATH}/tools/kconfig/gensdkconfig.py --sdkpath ${PINE64_SDK_PATH} --cmake 1 --projectdir ${PWD} --env BFLB_BOARD_DIR=${BOARD_DIR} --env BFLB_BOARD=${BOARD} --env BFLB_CHIP=${CHIP} --env BFLB_CPU_ID=${CPU_ID}
|
||||
|
||||
config:
|
||||
@${PINE64_SDK_PATH}/tools/kconfig/gensdkconfig.py --sdkpath ${PINE64_SDK_PATH} --menuconfig 1 --cmake 1 --projectdir ${PWD} --env BFLB_BOARD_DIR=${BOARD_DIR} --env BFLB_BOARD=${BOARD} --env BFLB_CHIP=${CHIP} --env BFLB_CPU_ID=${CPU_ID}
|
||||
|
||||
include $(BL_SDK_BASE)/project.build
|
||||
|
||||
|
||||
|
5
tools/kconfig/LICENSE.txt
Normal file
5
tools/kconfig/LICENSE.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
Copyright (c) 2011-2019, Ulf Magnusson <ulfalizer@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
841
tools/kconfig/README.rst
Normal file
841
tools/kconfig/README.rst
Normal file
|
@ -0,0 +1,841 @@
|
|||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
|
||||
News
|
||||
----
|
||||
|
||||
Dependency loop with recent linux-next kernels
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To fix issues with dependency loops on recent linux-next kernels, apply `this
|
||||
patch <https://www.spinics.net/lists/linux-kbuild/msg23455.html>`_. Hopefully,
|
||||
it will be in ``linux-next`` soon.
|
||||
|
||||
``windows-curses`` is no longer automatically installed on Windows
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Starting with Kconfiglib 13.0.0, the `windows-curses
|
||||
<https://github.com/zephyrproject-rtos/windows-curses>`__ package is no longer
|
||||
automatically installed on Windows, and needs to be installed manually for the
|
||||
terminal ``menuconfig`` to work.
|
||||
|
||||
This fixes installation of Kconfiglib on MSYS2, which is not compatible with
|
||||
``windows-curses``. See `this issue
|
||||
<https://github.com/ulfalizer/Kconfiglib/issues/77>`__.
|
||||
|
||||
The ``menuconfig`` now shows a hint re. installing ``windows-curses`` when the
|
||||
``curses`` module can't be imported on Windows.
|
||||
|
||||
Sorry if this change caused problems!
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Kconfiglib is a `Kconfig
|
||||
<https://github.com/torvalds/linux/blob/master/Documentation/kbuild/kconfig-language.rst>`__
|
||||
implementation in Python 2/3. It started out as a helper library, but now has a
|
||||
enough functionality to also work well as a standalone Kconfig implementation
|
||||
(including `terminal and GUI menuconfig interfaces <Menuconfig interfaces_>`_
|
||||
and `Kconfig extensions`_).
|
||||
|
||||
The entire library is contained in `kconfiglib.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_. The
|
||||
bundled scripts are implemented on top of it. Implementing your own scripts
|
||||
should be relatively easy, if needed.
|
||||
|
||||
Kconfiglib is used exclusively by e.g. the `Zephyr
|
||||
<https://www.zephyrproject.org/>`__, `esp-idf
|
||||
<https://github.com/espressif/esp-idf>`__, and `ACRN
|
||||
<https://projectacrn.org/>`__ projects. It is also used for many small helper
|
||||
scripts in various projects.
|
||||
|
||||
Since Kconfiglib is based around a library, it can be used e.g. to generate a
|
||||
`Kconfig cross-reference
|
||||
<https://docs.zephyrproject.org/latest/reference/kconfig/index.html>`_, using
|
||||
the same robust Kconfig parser used for other Kconfig tools, instead of brittle
|
||||
ad-hoc parsing. The documentation generation script can be found `here
|
||||
<https://github.com/zephyrproject-rtos/zephyr/blob/master/doc/scripts/genrest.py>`__.
|
||||
|
||||
Kconfiglib implements the recently added `Kconfig preprocessor
|
||||
<https://github.com/torvalds/linux/blob/master/Documentation/kbuild/kconfig-macro-language.rst>`__.
|
||||
For backwards compatibility, environment variables can be referenced both as
|
||||
``$(FOO)`` (the new syntax) and as ``$FOO`` (the old syntax). The old syntax is
|
||||
deprecated, but will probably be supported for a long time, as it's needed to
|
||||
stay compatible with older Linux kernels. The major version will be increased
|
||||
if support is ever dropped. Using the old syntax with an undefined environment
|
||||
variable keeps the string as is.
|
||||
|
||||
Note: See `this issue <https://github.com/ulfalizer/Kconfiglib/issues/47>`__ if
|
||||
you run into a "macro expanded to blank string" error with kernel 4.18+.
|
||||
|
||||
See `this page
|
||||
<https://docs.zephyrproject.org/latest/guides/kconfig/tips.html>`__ for some
|
||||
Kconfig tips and best practices.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Installation with pip
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Kconfiglib is available on `PyPI <https://pypi.python.org/pypi/kconfiglib/>`_ and can be
|
||||
installed with e.g.
|
||||
|
||||
.. code::
|
||||
|
||||
$ pip(3) install kconfiglib
|
||||
|
||||
Microsoft Windows is supported.
|
||||
|
||||
The ``pip`` installation will give you both the base library and the following
|
||||
executables. All but two (``genconfig`` and ``setconfig``) mirror functionality
|
||||
available in the C tools.
|
||||
|
||||
- `menuconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/menuconfig.py>`_
|
||||
|
||||
- `guiconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/guiconfig.py>`_
|
||||
|
||||
- `oldconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/oldconfig.py>`_
|
||||
|
||||
- `olddefconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/olddefconfig.py>`_
|
||||
|
||||
- `savedefconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/savedefconfig.py>`_
|
||||
|
||||
- `defconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/defconfig.py>`_
|
||||
|
||||
- `alldefconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/alldefconfig.py>`_
|
||||
|
||||
- `allnoconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/allnoconfig.py>`_
|
||||
|
||||
- `allmodconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/allmodconfig.py>`_
|
||||
|
||||
- `allyesconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/allyesconfig.py>`_
|
||||
|
||||
- `listnewconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/listnewconfig.py>`_
|
||||
|
||||
- `genconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/genconfig.py>`_
|
||||
|
||||
- `setconfig <https://github.com/ulfalizer/Kconfiglib/blob/master/setconfig.py>`_
|
||||
|
||||
``genconfig`` is intended to be run at build time. It generates a C header from
|
||||
the configuration and (optionally) information that can be used to rebuild only
|
||||
files that reference Kconfig symbols that have changed value.
|
||||
|
||||
Starting with Kconfiglib version 12.2.0, all utilities are compatible with both
|
||||
Python 2 and Python 3. Previously, ``menuconfig.py`` only ran under Python 3
|
||||
(i.e., it's now more backwards compatible than before).
|
||||
|
||||
**Note:** If you install Kconfiglib with ``pip``'s ``--user`` flag, make sure
|
||||
that your ``PATH`` includes the directory where the executables end up. You can
|
||||
list the installed files with ``pip(3) show -f kconfiglib``.
|
||||
|
||||
All releases have a corresponding tag in the git repository, e.g. ``v14.1.0``
|
||||
(the latest version).
|
||||
|
||||
`Semantic versioning <http://semver.org/>`_ is used. There's been ten small
|
||||
changes to the behavior of the API, a Windows packaging change, and a hashbang
|
||||
change to use ``python3``
|
||||
(`1 <https://github.com/ulfalizer/Kconfiglib/commit/e8b4ecb6ff6ccc1c7be0818314fbccda2ef2b2ee>`_,
|
||||
`2 <https://github.com/ulfalizer/Kconfiglib/commit/db633015a4d7b0ba1e882f665e191f350932b2af>`_,
|
||||
`3 <https://github.com/ulfalizer/Kconfiglib/commit/8983f7eb297dd614faf0beee3129559bc8ba338e>`_,
|
||||
`4 <https://github.com/ulfalizer/Kconfiglib/commit/cbf32e29a130d22bc734b7778e6304ac9df2a3e8>`_,
|
||||
`5 <https://github.com/ulfalizer/Kconfiglib/commit/eb6c21a9b33a2d6e2bed9882d4f930d0cab2f03b>`_,
|
||||
`6 <https://github.com/ulfalizer/Kconfiglib/commit/c19fc11355b13d75d97286402c7a933fb23d3b70>`_,
|
||||
`7 <https://github.com/ulfalizer/Kconfiglib/commit/7a428aa415606820a44291f475248b08e3952c4b>`_,
|
||||
`8 <https://github.com/ulfalizer/Kconfiglib/commit/f247ddf618ad29718e5efd3e69f8baf75d4d347b>`_,
|
||||
`9 <https://github.com/ulfalizer/Kconfiglib/commit/4fed39d9271ceb68be4157ab3f96a45b94f77dc0>`_,
|
||||
`10 <https://github.com/ulfalizer/Kconfiglib/commit/55bc8c380869ea663092212e8fe388ad7abae596>`_,
|
||||
`Windows packaging change <https://github.com/ulfalizer/Kconfiglib/commit/21b4c1e3b6e2867b9a0788d21a358f6b1f581d86>`_,
|
||||
`Python 3 hashbang change <https://github.com/ulfalizer/Kconfiglib/commit/9e0a8d29fa76adcb3f27bb2e20f16fefc2a8591e>`_),
|
||||
which is why the major version is at 14 rather than 2. I do major version bumps
|
||||
for all behavior changes, even tiny ones, and most of these were fixes for baby
|
||||
issues in the early days of the Kconfiglib 2 API.
|
||||
|
||||
Manual installation
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Just drop ``kconfiglib.py`` and the scripts you want somewhere. There are no
|
||||
third-party dependencies, but the terminal ``menuconfig`` won't work on Windows
|
||||
unless a package like `windows-curses
|
||||
<https://github.com/zephyrproject-rtos/windows-curses>`__ is installed.
|
||||
|
||||
Installation for the Linux kernel
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
See the module docstring at the top of `kconfiglib.py <https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_.
|
||||
|
||||
Python version compatibility (2.7/3.2+)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Kconfiglib and all utilities run under both Python 2.7 and Python 3.2 and
|
||||
later. The code mostly uses basic Python features and has no third-party
|
||||
dependencies, so keeping it backwards-compatible is pretty low effort.
|
||||
|
||||
The 3.2 requirement comes from ``argparse``. ``format()`` with unnumbered
|
||||
``{}`` is used as well.
|
||||
|
||||
A recent Python 3 version is recommended if you have a choice, as it'll give
|
||||
you better Unicode handling.
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
|
||||
1. `Install <Installation_>`_ the library and the utilities.
|
||||
|
||||
2. Write `Kconfig
|
||||
<https://github.com/torvalds/linux/blob/master/Documentation/kbuild/kconfig-language.rst>`__
|
||||
files that describe the available configuration options. See `this page
|
||||
<https://docs.zephyrproject.org/latest/guides/kconfig/tips.html>`__ for some
|
||||
general Kconfig advice.
|
||||
|
||||
3. Generate an initial configuration with e.g. ``menuconfig``/``guiconfig`` or
|
||||
``alldefconfig``. The configuration is saved as ``.config`` by default.
|
||||
|
||||
For more advanced projects, the ``defconfig`` utility can be used to
|
||||
generate the initial configuration from an existing configuration file.
|
||||
Usually, this existing configuration file would be a minimal configuration
|
||||
file, as generated by e.g. ``savedefconfig``.
|
||||
|
||||
4. Run ``genconfig`` to generate a header file. By default, it is saved as
|
||||
``config.h``.
|
||||
|
||||
Normally, ``genconfig`` would be run automatically as part of the build.
|
||||
|
||||
Before writing a header file or other configuration output, Kconfiglib
|
||||
compares the old contents of the file against the new contents. If there's
|
||||
no change, the write is skipped. This avoids updating file metadata like the
|
||||
modification time, and might save work depending on your build setup.
|
||||
|
||||
Adding new configuration output formats should be relatively straightforward.
|
||||
See the implementation of ``write_config()`` in `kconfiglib.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_.
|
||||
The documentation for the ``Symbol.config_string`` property has some tips as
|
||||
well.
|
||||
|
||||
5. To update an old ``.config`` file after the Kconfig files have changed (e.g.
|
||||
to add new options), run ``oldconfig`` (prompts for values for new options)
|
||||
or ``olddefconfig`` (gives new options their default value). Entering the
|
||||
``menuconfig`` or ``guiconfig`` interface and saving the configuration will
|
||||
also update it (the configuration interfaces always prompt for saving
|
||||
on exit if it would modify the contents of the ``.config`` file).
|
||||
|
||||
Due to Kconfig semantics, simply loading an old ``.config`` file performs an
|
||||
implicit ``olddefconfig``, so building will normally not be affected by
|
||||
having an outdated configuration.
|
||||
|
||||
Whenever ``.config`` is overwritten, the previous version of the file is saved
|
||||
to ``.config.old`` (or, more generally, to ``$KCONFIG_CONFIG.old``).
|
||||
|
||||
Using ``.config`` files as Make input
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``.config`` files use Make syntax and can be included directly in Makefiles to
|
||||
read configuration values from there. This is why ``n``-valued
|
||||
``bool``/``tristate`` values are written out as ``# CONFIG_FOO is not set`` (a
|
||||
Make comment) in ``.config``, allowing them to be tested with ``ifdef`` in
|
||||
Make.
|
||||
|
||||
If you make use of this, you might want to pass ``--config-out <filename>`` to
|
||||
``genconfig`` and include the configuration file it generates instead of
|
||||
including ``.config`` directly. This has the advantage that the generated
|
||||
configuration file will always be a "full" configuration file, even if
|
||||
``.config`` is outdated. Otherwise, it might be necessary to run
|
||||
``old(def)config`` or ``menuconfig``/``guiconfig`` before rebuilding with an
|
||||
outdated ``.config``.
|
||||
|
||||
If you use ``--sync-deps`` to generate incremental build information, you can
|
||||
include ``deps/auto.conf`` instead, which is also a full configuration file.
|
||||
|
||||
Useful helper macros
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The `include/linux/kconfig.h
|
||||
<https://github.com/torvalds/linux/blob/master/include/linux/kconfig.h>`_
|
||||
header in the Linux kernel defines some useful helper macros for testing
|
||||
Kconfig configuration values.
|
||||
|
||||
``IS_ENABLED()`` is generally useful, allowing configuration values to be
|
||||
tested in ``if`` statements with no runtime overhead.
|
||||
|
||||
Incremental building
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
See the docstring for ``Kconfig.sync_deps()`` in `kconfiglib.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_ for hints
|
||||
on implementing incremental builds (rebuilding just source files that reference
|
||||
changed configuration values).
|
||||
|
||||
Running the ``scripts/basic/fixdep.c`` tool from the kernel on the output of
|
||||
``gcc -MD <source file>`` might give you an idea of how it all fits together.
|
||||
|
||||
Library documentation
|
||||
---------------------
|
||||
|
||||
Kconfiglib comes with extensive documentation in the form of docstrings. To view it, run e.g.
|
||||
the following command:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
$ pydoc(3) kconfiglib
|
||||
|
||||
For HTML output, add ``-w``:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
$ pydoc(3) -w kconfiglib
|
||||
|
||||
This will also work after installing Kconfiglib with ``pip(3)``.
|
||||
|
||||
Documentation for other modules can be viewed in the same way (though a plain
|
||||
``--help`` will work when they're run as executables):
|
||||
|
||||
.. code:: sh
|
||||
|
||||
$ pydoc(3) menuconfig/guiconfig/...
|
||||
|
||||
A good starting point for learning the library is to read the module docstring
|
||||
(which you could also just read directly at the beginning of `kconfiglib.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_). It
|
||||
gives an introduction to symbol values, the menu tree, and expressions.
|
||||
|
||||
After reading the module docstring, a good next step is to read the ``Kconfig``
|
||||
class documentation, and then the documentation for the ``Symbol``, ``Choice``,
|
||||
and ``MenuNode`` classes.
|
||||
|
||||
Please tell me if something is unclear or can be explained better.
|
||||
|
||||
Library features
|
||||
----------------
|
||||
|
||||
Kconfiglib can do the following, among other things:
|
||||
|
||||
- **Programmatically get and set symbol values**
|
||||
|
||||
See `allnoconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/allnoconfig.py>`_ and
|
||||
`allyesconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/allyesconfig.py>`_,
|
||||
which are automatically verified to produce identical output to the standard
|
||||
``make allnoconfig`` and ``make allyesconfig``.
|
||||
|
||||
- **Read and write .config and defconfig files**
|
||||
|
||||
The generated ``.config`` and ``defconfig`` (minimal configuration) files are
|
||||
character-for-character identical to what the C implementation would generate
|
||||
(except for the header comment). The test suite relies on this, as it
|
||||
compares the generated files.
|
||||
|
||||
- **Write C headers**
|
||||
|
||||
The generated headers use the same format as ``include/generated/autoconf.h``
|
||||
from the Linux kernel. Output for symbols appears in the order that they're
|
||||
defined, unlike in the C tools (where the order depends on the hash table
|
||||
implementation).
|
||||
|
||||
- **Implement incremental builds**
|
||||
|
||||
This uses the same scheme as the ``include/config`` directory in the kernel:
|
||||
Symbols are translated into files that are touched when the symbol's value
|
||||
changes between builds, which can be used to avoid having to do a full
|
||||
rebuild whenever the configuration is changed.
|
||||
|
||||
See the ``sync_deps()`` function for more information.
|
||||
|
||||
- **Inspect symbols**
|
||||
|
||||
Printing a symbol or other item (which calls ``__str__()``) returns its
|
||||
definition in Kconfig format. This also works for symbols defined in multiple
|
||||
locations.
|
||||
|
||||
A helpful ``__repr__()`` is on all objects too.
|
||||
|
||||
All ``__str__()`` and ``__repr__()`` methods are deliberately implemented
|
||||
with just public APIs, so all symbol information can be fetched separately as
|
||||
well.
|
||||
|
||||
- **Inspect expressions**
|
||||
|
||||
Expressions use a simple tuple-based format that can be processed manually
|
||||
if needed. Expression printing and evaluation functions are provided,
|
||||
implemented with public APIs.
|
||||
|
||||
- **Inspect the menu tree**
|
||||
|
||||
The underlying menu tree is exposed, including submenus created implicitly
|
||||
from symbols depending on preceding symbols. This can be used e.g. to
|
||||
implement menuconfig-like functionality.
|
||||
|
||||
See `menuconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/menuconfig.py>`_/`guiconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/guiconfig.py>`_ and the
|
||||
minimalistic `menuconfig_example.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/examples/menuconfig_example.py>`_
|
||||
example.
|
||||
|
||||
Kconfig extensions
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following Kconfig extensions are available:
|
||||
|
||||
- ``source`` supports glob patterns and includes each matching file. A pattern
|
||||
is required to match at least one file.
|
||||
|
||||
A separate ``osource`` statement is available for cases where it's okay for
|
||||
the pattern to match no files (in which case ``osource`` turns into a no-op).
|
||||
|
||||
- A relative ``source`` statement (``rsource``) is available, where file paths
|
||||
are specified relative to the directory of the current Kconfig file. An
|
||||
``orsource`` statement is available as well, analogous to ``osource``.
|
||||
|
||||
- Preprocessor user functions can be defined in Python, which makes it simple
|
||||
to integrate information from existing Python tools into Kconfig (e.g. to
|
||||
have Kconfig symbols depend on hardware information stored in some other
|
||||
format).
|
||||
|
||||
See the *Kconfig extensions* section in the
|
||||
`kconfiglib.py <https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_
|
||||
module docstring for more information.
|
||||
|
||||
- ``def_int``, ``def_hex``, and ``def_string`` are available in addition to
|
||||
``def_bool`` and ``def_tristate``, allowing ``int``, ``hex``, and ``string``
|
||||
symbols to be given a type and a default at the same time.
|
||||
|
||||
These can be useful in projects that make use of symbols defined in multiple
|
||||
locations, and remove some Kconfig inconsistency.
|
||||
|
||||
- Environment variables are expanded directly in e.g. ``source`` and
|
||||
``mainmenu`` statements, meaning ``option env`` symbols are redundant.
|
||||
|
||||
This is the standard behavior with the new `Kconfig preprocessor
|
||||
<https://github.com/torvalds/linux/blob/master/Documentation/kbuild/kconfig-macro-language.rst>`__,
|
||||
which Kconfiglib implements.
|
||||
|
||||
``option env`` symbols are accepted but ignored, which leads the caveat that
|
||||
they must have the same name as the environment variables they reference
|
||||
(Kconfiglib warns if the names differ). This keeps Kconfiglib compatible with
|
||||
older Linux kernels, where the name of the ``option env`` symbol always
|
||||
matched the environment variable. Compatibility with older Linux kernels is
|
||||
the main reason ``option env`` is still supported.
|
||||
|
||||
The C tools have dropped support for ``option env``.
|
||||
|
||||
- Two extra optional warnings can be enabled by setting environment variables,
|
||||
covering cases that are easily missed when making changes to Kconfig files:
|
||||
|
||||
* ``KCONFIG_WARN_UNDEF``: If set to ``y``, warnings will be generated for all
|
||||
references to undefined symbols within Kconfig files. The only gotcha is
|
||||
that all hex literals must be prefixed with ``0x`` or ``0X``, to make it
|
||||
possible to distinguish them from symbol references.
|
||||
|
||||
Some projects (e.g. the Linux kernel) use multiple Kconfig trees with many
|
||||
shared Kconfig files, leading to some safe undefined symbol references.
|
||||
``KCONFIG_WARN_UNDEF`` is useful in projects that only have a single
|
||||
Kconfig tree though.
|
||||
|
||||
``KCONFIG_STRICT`` is an older alias for this environment variable,
|
||||
supported for backwards compatibility.
|
||||
|
||||
* ``KCONFIG_WARN_UNDEF_ASSIGN``: If set to ``y``, warnings will be generated
|
||||
for all assignments to undefined symbols within ``.config`` files. By
|
||||
default, no such warnings are generated.
|
||||
|
||||
This warning can also be enabled/disabled by setting
|
||||
``Kconfig.warn_assign_undef`` to ``True``/``False``.
|
||||
|
||||
Other features
|
||||
--------------
|
||||
|
||||
- **Single-file implementation**
|
||||
|
||||
The entire library is contained in `kconfiglib.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`_.
|
||||
|
||||
The tools implemented on top of it are one file each.
|
||||
|
||||
- **Robust and highly compatible with the C Kconfig tools**
|
||||
|
||||
The `test suite <https://github.com/ulfalizer/Kconfiglib/blob/master/testsuite.py>`_
|
||||
automatically compares output from Kconfiglib and the C tools
|
||||
by diffing the generated ``.config`` files for the real kernel Kconfig and
|
||||
defconfig files, for all ARCHes.
|
||||
|
||||
This currently involves comparing the output for 36 ARCHes and 498 defconfig
|
||||
files (or over 18000 ARCH/defconfig combinations in "obsessive" test suite
|
||||
mode). All tests are expected to pass.
|
||||
|
||||
A comprehensive suite of selftests is included as well.
|
||||
|
||||
- **Not horribly slow despite being a pure Python implementation**
|
||||
|
||||
The `allyesconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/allyesconfig.py>`_
|
||||
script currently runs in about 1.3 seconds on the Linux kernel on a Core i7
|
||||
2600K (with a warm file cache), including the ``make`` overhead from ``make
|
||||
scriptconfig``. Note that the Linux kernel Kconfigs are absolutely massive
|
||||
(over 14k symbols for x86) compared to most projects, and also have overhead
|
||||
from running shell commands via the Kconfig preprocessor.
|
||||
|
||||
Kconfiglib is especially speedy in cases where multiple ``.config`` files
|
||||
need to be processed, because the ``Kconfig`` files will only need to be parsed
|
||||
once.
|
||||
|
||||
For long-running jobs, `PyPy <https://pypy.org/>`_ gives a big performance
|
||||
boost. CPython is faster for short-running jobs as PyPy needs some time to
|
||||
warm up.
|
||||
|
||||
Kconfiglib also works well with the
|
||||
`multiprocessing <https://docs.python.org/3/library/multiprocessing.html>`_
|
||||
module. No global state is kept.
|
||||
|
||||
- **Generates more warnings than the C implementation**
|
||||
|
||||
Generates the same warnings as the C implementation, plus additional ones.
|
||||
Also detects dependency and ``source`` loops.
|
||||
|
||||
All warnings point out the location(s) in the ``Kconfig`` files where a
|
||||
symbol is defined, where applicable.
|
||||
|
||||
- **Unicode support**
|
||||
|
||||
Unicode characters in string literals in ``Kconfig`` and ``.config`` files are
|
||||
correctly handled. This support mostly comes for free from Python.
|
||||
|
||||
- **Windows support**
|
||||
|
||||
Nothing Linux-specific is used. Universal newlines mode is used for both
|
||||
Python 2 and Python 3.
|
||||
|
||||
The `Zephyr <https://www.zephyrproject.org/>`_ project uses Kconfiglib to
|
||||
generate ``.config`` files and C headers on Linux as well as Windows.
|
||||
|
||||
- **Internals that (mostly) mirror the C implementation**
|
||||
|
||||
While being simpler to understand and tweak.
|
||||
|
||||
Menuconfig interfaces
|
||||
---------------------
|
||||
|
||||
Three configuration interfaces are currently available:
|
||||
|
||||
- `menuconfig.py <https://github.com/ulfalizer/Kconfiglib/blob/master/menuconfig.py>`_
|
||||
is a terminal-based configuration interface implemented using the standard
|
||||
Python ``curses`` module. ``xconfig`` features like showing invisible symbols and
|
||||
showing symbol names are included, and it's possible to jump directly to a symbol
|
||||
in the menu tree (even if it's currently invisible).
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/ulfalizer/Kconfiglib/screenshots/screenshots/menuconfig.gif
|
||||
|
||||
*There is now also a show-help mode that shows the help text of the currently
|
||||
selected symbol in the help window at the bottom.*
|
||||
|
||||
Starting with Kconfiglib 12.2.0, ``menuconfig.py`` runs under both Python 2
|
||||
and Python 3 (previously, it only ran under Python 3, so this was a
|
||||
backport). Running it under Python 3 provides better support for Unicode text
|
||||
entry (``get_wch()`` is not available in the ``curses`` module on Python 2).
|
||||
|
||||
There are no third-party dependencies on \*nix. On Windows,
|
||||
the ``curses`` modules is not available by default, but support
|
||||
can be added by installing the ``windows-curses`` package:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ pip install windows-curses
|
||||
|
||||
This uses wheels built from `this repository
|
||||
<https://github.com/zephyrproject-rtos/windows-curses>`_, which is in turn
|
||||
based on Christoph Gohlke's `Python Extension Packages for Windows
|
||||
<https://www.lfd.uci.edu/~gohlke/pythonlibs/#curses>`_.
|
||||
|
||||
See the docstring at the top of `menuconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/menuconfig.py>`_ for
|
||||
more information about the terminal menuconfig implementation.
|
||||
|
||||
- `guiconfig.py
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/master/guiconfig.py>`_ is a
|
||||
graphical configuration interface written in `Tkinter
|
||||
<https://docs.python.org/3/library/tkinter.html>`_. Like ``menuconfig.py``,
|
||||
it supports showing all symbols (with invisible symbols in red) and jumping
|
||||
directly to symbols. Symbol values can also be changed directly from the
|
||||
jump-to dialog.
|
||||
|
||||
When single-menu mode is enabled, a single menu is shown at a time, like in
|
||||
the terminal menuconfig. Only this mode distinguishes between symbols defined
|
||||
with ``config`` and symbols defined with ``menuconfig``.
|
||||
|
||||
``guiconfig.py`` has been tested on X11, Windows, and macOS, and is
|
||||
compatible with both Python 2 and Python 3.
|
||||
|
||||
Despite being part of the Python standard library, ``tkinter`` often isn't
|
||||
included by default in Python installations on Linux. These commands will
|
||||
install it on a few different distributions:
|
||||
|
||||
- Ubuntu: ``sudo apt install python-tk``/``sudo apt install python3-tk``
|
||||
|
||||
- Fedora: ``dnf install python2-tkinter``/``dnf install python3-tkinter``
|
||||
|
||||
- Arch: ``sudo pacman -S tk``
|
||||
|
||||
- Clear Linux: ``sudo swupd bundle-add python3-tcl``
|
||||
|
||||
Screenshot below, with show-all mode enabled and the jump-to dialog open:
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/ulfalizer/Kconfiglib/screenshots/screenshots/guiconfig.png
|
||||
|
||||
To avoid having to carry around a bunch of GIFs, the image data is embedded
|
||||
in ``guiconfig.py``. To use separate GIF files instead, change
|
||||
``_USE_EMBEDDED_IMAGES`` to ``False`` in ``guiconfig.py``. The image files
|
||||
can be found in the `screenshots
|
||||
<https://github.com/ulfalizer/Kconfiglib/tree/screenshots/guiconfig>`_
|
||||
branch.
|
||||
|
||||
I did my best with the images, but some are definitely only art adjacent.
|
||||
Touch-ups are welcome. :)
|
||||
|
||||
- `pymenuconfig <https://github.com/RomaVis/pymenuconfig>`_, built by `RomaVis
|
||||
<https://github.com/RomaVis>`_, is an older portable Python 2/3 TkInter
|
||||
menuconfig implementation.
|
||||
|
||||
Screenshot below:
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/RomaVis/pymenuconfig/master/screenshot.PNG
|
||||
|
||||
While working on the terminal menuconfig implementation, I added a few APIs
|
||||
to Kconfiglib that turned out to be handy. ``pymenuconfig`` predates
|
||||
``menuconfig.py`` and ``guiconfig.py``, and so didn't have them available.
|
||||
Blame me for any workarounds.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Example scripts
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The `examples/ <https://github.com/ulfalizer/Kconfiglib/blob/master/examples>`_ directory contains some simple example scripts. Among these are the following ones. Make sure you run them with the latest version of Kconfiglib, as they might make use of newly added features.
|
||||
|
||||
- `eval_expr.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/eval_expr.py>`_ evaluates an expression in the context of a configuration.
|
||||
|
||||
- `find_symbol.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/find_symbol.py>`_ searches through expressions to find references to a symbol, also printing a "backtrace" with parents for each reference found.
|
||||
|
||||
- `help_grep.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/help_grep.py>`_ searches for a string in all help texts.
|
||||
|
||||
- `print_tree.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/print_tree.py>`_ prints a tree of all configuration items.
|
||||
|
||||
- `print_config_tree.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/print_config_tree.py>`_ is similar to ``print_tree.py``, but dumps the tree as it would appear in ``menuconfig``, including values. This can be handy for visually diffing between ``.config`` files and different versions of ``Kconfig`` files.
|
||||
|
||||
- `list_undefined.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/list_undefined.py>`_ finds references to symbols that are not defined by any architecture in the Linux kernel.
|
||||
|
||||
- `merge_config.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/merge_config.py>`_ merges configuration fragments to produce a complete .config, similarly to ``scripts/kconfig/merge_config.sh`` from the kernel.
|
||||
|
||||
- `menuconfig_example.py <https://github.com/ulfalizer/Kconfiglib/blob/master/examples/menuconfig_example.py>`_ implements a configuration interface that uses notation similar to ``make menuconfig``. It's deliberately kept as simple as possible to demonstrate just the core concepts.
|
||||
|
||||
Real-world examples
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- `kconfig.py
|
||||
<https://github.com/zephyrproject-rtos/zephyr/blob/master/scripts/kconfig/kconfig.py>`_
|
||||
from the `Zephyr <https://www.zephyrproject.org/>`_ project handles
|
||||
``.config`` and header file generation, also doing configuration fragment
|
||||
merging
|
||||
|
||||
- `genrest.py
|
||||
<https://github.com/zephyrproject-rtos/zephyr/blob/master/doc/scripts/genrest.py>`_
|
||||
generates a Kconfig symbol cross-reference, which can be viewed `here
|
||||
<http://docs.zephyrproject.org/reference/kconfig/index.html>`__
|
||||
|
||||
- `CMake and IDE integration
|
||||
<https://github.com/espressif/esp-idf/tree/master/tools/kconfig_new>`_ from
|
||||
the ESP-IDF project, via a configuration server program.
|
||||
|
||||
- `A script for turning on USB-related options
|
||||
<https://github.com/google/syzkaller/blob/master/dashboard/config/kconfiglib-merge-usb-configs.py>`_,
|
||||
from the `syzkaller <https://github.com/google/syzkaller>`_ project.
|
||||
|
||||
- `Various automated checks
|
||||
<https://github.com/zephyrproject-rtos/ci-tools/blob/master/scripts/check_compliance.py>`_,
|
||||
including a check for references to undefined Kconfig symbols in source code.
|
||||
See the ``KconfigCheck`` class.
|
||||
|
||||
- `Various utilities
|
||||
<https://github.com/projectacrn/acrn-hypervisor/tree/master/scripts/kconfig>`_
|
||||
from the `ACRN <https://projectacrn.org/>`_ project
|
||||
|
||||
These use the older Kconfiglib 1 API, which was clunkier and not as general
|
||||
(functions instead of properties, no direct access to the menu structure or
|
||||
properties, uglier ``__str__()`` output):
|
||||
|
||||
- `genboardscfg.py <http://git.denx.de/?p=u-boot.git;a=blob;f=tools/genboardscfg.py;hb=HEAD>`_ from `Das U-Boot <http://www.denx.de/wiki/U-Boot>`_ generates some sort of legacy board database by pulling information from a newly added Kconfig-based configuration system (as far as I understand it :).
|
||||
|
||||
- `gen-manual-lists.py <https://git.busybox.net/buildroot/tree/support/scripts/gen-manual-lists.py?id=5676a2deea896f38123b99781da0a612865adeb0>`_ generated listings for an appendix in the `Buildroot <https://buildroot.org>`_ manual. (The listing has since been removed.)
|
||||
|
||||
- `gen_kconfig_doc.py <https://github.com/espressif/esp-idf/blob/master/docs/gen-kconfig-doc.py>`_ from the `esp-idf <https://github.com/espressif/esp-idf>`_ project generates documentation from Kconfig files.
|
||||
|
||||
- `SConf <https://github.com/CoryXie/SConf>`_ builds an interactive configuration interface (like ``menuconfig``) on top of Kconfiglib, for use e.g. with `SCons <scons.org>`_.
|
||||
|
||||
- `kconfig-diff.py <https://gist.github.com/dubiousjim/5638961>`_ -- a script by `dubiousjim <https://github.com/dubiousjim>`_ that compares kernel configurations.
|
||||
|
||||
- Originally, Kconfiglib was used in chapter 4 of my `master's thesis <http://liu.diva-portal.org/smash/get/diva2:473038/FULLTEXT01.pdf>`_ to automatically generate a "minimal" kernel for a given system. Parts of it bother me a bit now, but that's how it goes with old work.
|
||||
|
||||
Sample ``make iscriptconfig`` session
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following log should give some idea of the functionality available in the API:
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ make iscriptconfig
|
||||
A Kconfig instance 'kconf' for the architecture x86 has been created.
|
||||
>>> kconf # Calls Kconfig.__repr__()
|
||||
<configuration with 13711 symbols, main menu prompt "Linux/x86 4.14.0-rc7 Kernel Configuration", srctree ".", config symbol prefix "CONFIG_", warnings enabled, undef. symbol assignment warnings disabled>
|
||||
>>> kconf.mainmenu_text # Expanded main menu text
|
||||
'Linux/x86 4.14.0-rc7 Kernel Configuration'
|
||||
>>> kconf.top_node # The implicit top-level menu
|
||||
<menu node for menu, prompt "Linux/x86 4.14.0-rc7 Kernel Configuration" (visibility y), deps y, 'visible if' deps y, has child, Kconfig:5>
|
||||
>>> kconf.top_node.list # First child menu node
|
||||
<menu node for symbol SRCARCH, deps y, has next, Kconfig:7>
|
||||
>>> print(kconf.top_node.list) # Calls MenuNode.__str__()
|
||||
config SRCARCH
|
||||
string
|
||||
option env="SRCARCH"
|
||||
default "x86"
|
||||
>>> sym = kconf.top_node.list.next.item # Item contained in next menu node
|
||||
>>> print(sym) # Calls Symbol.__str__()
|
||||
config 64BIT
|
||||
bool "64-bit kernel" if ARCH = "x86"
|
||||
default ARCH != "i386"
|
||||
help
|
||||
Say yes to build a 64-bit kernel - formerly known as x86_64
|
||||
Say no to build a 32-bit kernel - formerly known as i386
|
||||
>>> sym # Calls Symbol.__repr__()
|
||||
<symbol 64BIT, bool, "64-bit kernel", value y, visibility y, direct deps y, arch/x86/Kconfig:2>
|
||||
>>> sym.assignable # Currently assignable values (0, 1, 2 = n, m, y)
|
||||
(0, 2)
|
||||
>>> sym.set_value(0) # Set it to n
|
||||
True
|
||||
>>> sym.tri_value # Check the new value
|
||||
0
|
||||
>>> sym = kconf.syms["X86_MPPARSE"] # Look up symbol by name
|
||||
>>> print(sym)
|
||||
config X86_MPPARSE
|
||||
bool "Enable MPS table" if (ACPI || SFI) && X86_LOCAL_APIC
|
||||
default y if X86_LOCAL_APIC
|
||||
help
|
||||
For old smp systems that do not have proper acpi support. Newer systems
|
||||
(esp with 64bit cpus) with acpi support, MADT and DSDT will override it
|
||||
>>> default = sym.defaults[0] # Fetch its first default
|
||||
>>> sym = default[1] # Fetch the default's condition (just a Symbol here)
|
||||
>>> print(sym)
|
||||
config X86_LOCAL_APIC
|
||||
bool
|
||||
default y
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
select PCI_MSI_IRQ_DOMAIN if PCI_MSI
|
||||
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI
|
||||
>>> sym.nodes # Show the MenuNode(s) associated with it
|
||||
[<menu node for symbol X86_LOCAL_APIC, deps n, has next, arch/x86/Kconfig:1015>]
|
||||
>>> kconfiglib.expr_str(sym.defaults[0][1]) # Print the default's condition
|
||||
'X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI'
|
||||
>>> kconfiglib.expr_value(sym.defaults[0][1]) # Evaluate it (0 = n)
|
||||
0
|
||||
>>> kconf.syms["64BIT"].set_value(2)
|
||||
True
|
||||
>>> kconfiglib.expr_value(sym.defaults[0][1]) # Evaluate it again (2 = y)
|
||||
2
|
||||
>>> kconf.write_config("myconfig") # Save a .config
|
||||
>>> ^D
|
||||
$ cat myconfig
|
||||
# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_X86_64=y
|
||||
CONFIG_X86=y
|
||||
CONFIG_INSTRUCTION_DECODER=y
|
||||
CONFIG_OUTPUT_FORMAT="elf64-x86-64"
|
||||
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
|
||||
CONFIG_LOCKDEP_SUPPORT=y
|
||||
CONFIG_STACKTRACE_SUPPORT=y
|
||||
CONFIG_MMU=y
|
||||
...
|
||||
|
||||
Test suite
|
||||
----------
|
||||
|
||||
The test suite is run with
|
||||
|
||||
.. code::
|
||||
|
||||
$ python(3) Kconfiglib/testsuite.py
|
||||
|
||||
`pypy <https://pypy.org/>`_ works too, and is much speedier for everything except ``allnoconfig.py``/``allnoconfig_simpler.py``/``allyesconfig.py``, where it doesn't have time to warm up since
|
||||
the scripts are run via ``make scriptconfig``.
|
||||
|
||||
The test suite must be run from the top-level kernel directory. It requires that the
|
||||
Kconfiglib git repository has been cloned into it and that the makefile patch has been applied.
|
||||
|
||||
To get rid of warnings generated for the kernel ``Kconfig`` files, add ``2>/dev/null`` to the command to
|
||||
discard ``stderr``.
|
||||
|
||||
**NOTE: Forgetting to apply the Makefile patch will cause some tests that compare generated configurations to fail**
|
||||
|
||||
**NOTE: The test suite overwrites .config in the kernel root, so make sure to back it up.**
|
||||
|
||||
The test suite consists of a set of selftests and a set of compatibility tests that
|
||||
compare configurations generated by Kconfiglib with
|
||||
configurations generated by the C tools, for a number of cases. See
|
||||
`testsuite.py <https://github.com/ulfalizer/Kconfiglib/blob/master/testsuite.py>`_
|
||||
for the available options.
|
||||
|
||||
The `tests/reltest <https://github.com/ulfalizer/Kconfiglib/blob/master/tests/reltest>`_ script runs the test suite
|
||||
and all the example scripts for both Python 2 and Python 3, verifying that everything works.
|
||||
|
||||
Rarely, the output from the C tools is changed slightly (most recently due to a
|
||||
`change <https://www.spinics.net/lists/linux-kbuild/msg17074.html>`_ I added).
|
||||
If you get test suite failures, try running the test suite again against the
|
||||
`linux-next tree <https://www.kernel.org/doc/man-pages/linux-next.html>`_,
|
||||
which has all the latest changes. I will make it clear if any
|
||||
non-backwards-compatible changes appear.
|
||||
|
||||
A lot of time is spent waiting around for ``make`` and the C utilities (which need to reparse all the
|
||||
Kconfig files for each defconfig test). Adding some multiprocessing to the test suite would make sense
|
||||
too.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
* This is version 2 of Kconfiglib, which is not backwards-compatible with
|
||||
Kconfiglib 1. A summary of changes between Kconfiglib 1 and Kconfiglib
|
||||
2 can be found `here
|
||||
<https://github.com/ulfalizer/Kconfiglib/blob/screenshots/kconfiglib-2-changes.txt>`__.
|
||||
|
||||
* I sometimes see people add custom output formats, which is pretty
|
||||
straightforward to do (see the implementations of ``write_autoconf()`` and
|
||||
``write_config()`` for a template, and also the documentation of the
|
||||
``Symbol.config_string`` property). If you come up with something you think
|
||||
might be useful to other people, I'm happy to take it in upstream. Batteries
|
||||
included and all that.
|
||||
|
||||
* Kconfiglib assumes the modules symbol is ``MODULES``, which is backwards-compatible.
|
||||
A warning is printed by default if ``option modules`` is set on some other symbol.
|
||||
|
||||
Let me know if you need proper ``option modules`` support. It wouldn't be that
|
||||
hard to add.
|
||||
|
||||
Thanks
|
||||
------
|
||||
|
||||
- To `RomaVis <https://github.com/RomaVis>`_, for making
|
||||
`pymenuconfig <https://github.com/RomaVis/pymenuconfig>`_ and suggesting
|
||||
the ``rsource`` keyword.
|
||||
|
||||
- To `Mitja Horvat <https://github.com/pinkfluid>`_, for adding support
|
||||
for user-defined styles to the terminal menuconfig.
|
||||
|
||||
- To `Philip Craig <https://github.com/philipc>`_ for adding
|
||||
support for the ``allnoconfig_y`` option and fixing an obscure issue
|
||||
with ``comment``\s inside ``choice``\s (that didn't affect correctness but
|
||||
made outputs differ). ``allnoconfig_y`` is used to force certain symbols
|
||||
to ``y`` during ``make allnoconfig`` to improve coverage.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
See `LICENSE.txt <https://github.com/ulfalizer/Kconfiglib/blob/master/LICENSE.txt>`_. SPDX license identifiers are used in the
|
||||
source code.
|
27
tools/kconfig/alldefconfig.py
Executable file
27
tools/kconfig/alldefconfig.py
Executable file
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Writes a configuration file where all symbols are set to their their default
|
||||
values.
|
||||
|
||||
The default output filename is '.config'. A different filename can be passed in
|
||||
the KCONFIG_CONFIG environment variable.
|
||||
|
||||
Usage for the Linux kernel:
|
||||
|
||||
$ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/alldefconfig.py
|
||||
"""
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
kconf = kconfiglib.standard_kconfig(__doc__)
|
||||
kconf.load_allconfig("alldef.config")
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
46
tools/kconfig/allmodconfig.py
Executable file
46
tools/kconfig/allmodconfig.py
Executable file
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Writes a configuration file where as many symbols as possible are set to 'm'.
|
||||
|
||||
The default output filename is '.config'. A different filename can be passed
|
||||
in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
Usage for the Linux kernel:
|
||||
|
||||
$ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/allmodconfig.py
|
||||
"""
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
kconf = kconfiglib.standard_kconfig(__doc__)
|
||||
|
||||
# See allnoconfig.py
|
||||
kconf.warn = False
|
||||
|
||||
for sym in kconf.unique_defined_syms:
|
||||
if sym.orig_type == kconfiglib.BOOL:
|
||||
# 'bool' choice symbols get their default value, as determined by
|
||||
# e.g. 'default's on the choice
|
||||
if not sym.choice:
|
||||
# All other bool symbols get set to 'y', like for allyesconfig
|
||||
sym.set_value(2)
|
||||
elif sym.orig_type == kconfiglib.TRISTATE:
|
||||
sym.set_value(1)
|
||||
|
||||
for choice in kconf.unique_choices:
|
||||
choice.set_value(2 if choice.orig_type == kconfiglib.BOOL else 1)
|
||||
|
||||
kconf.warn = True
|
||||
|
||||
kconf.load_allconfig("allmod.config")
|
||||
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
45
tools/kconfig/allnoconfig.py
Executable file
45
tools/kconfig/allnoconfig.py
Executable file
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Writes a configuration file where as many symbols as possible are set to 'n'.
|
||||
|
||||
The default output filename is '.config'. A different filename can be passed
|
||||
in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
Usage for the Linux kernel:
|
||||
|
||||
$ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/allnoconfig.py
|
||||
"""
|
||||
|
||||
# See examples/allnoconfig_walk.py for another way to implement this script
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
kconf = kconfiglib.standard_kconfig(__doc__)
|
||||
|
||||
# Avoid warnings that would otherwise get printed by Kconfiglib for the
|
||||
# following:
|
||||
#
|
||||
# 1. Assigning a value to a symbol without a prompt, which never has any
|
||||
# effect
|
||||
#
|
||||
# 2. Assigning values invalid for the type (only bool/tristate symbols
|
||||
# accept 0/1/2, for n/m/y). The assignments will be ignored for other
|
||||
# symbol types, which is what we want.
|
||||
kconf.warn = False
|
||||
for sym in kconf.unique_defined_syms:
|
||||
sym.set_value(2 if sym.is_allnoconfig_y else 0)
|
||||
kconf.warn = True
|
||||
|
||||
kconf.load_allconfig("allno.config")
|
||||
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
56
tools/kconfig/allyesconfig.py
Executable file
56
tools/kconfig/allyesconfig.py
Executable file
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Writes a configuration file where as many symbols as possible are set to 'y'.
|
||||
|
||||
The default output filename is '.config'. A different filename can be passed
|
||||
in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
Usage for the Linux kernel:
|
||||
|
||||
$ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/allyesconfig.py
|
||||
"""
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
kconf = kconfiglib.standard_kconfig(__doc__)
|
||||
|
||||
# See allnoconfig.py
|
||||
kconf.warn = False
|
||||
|
||||
# Try to set all symbols to 'y'. Dependencies might truncate the value down
|
||||
# later, but this will at least give the highest possible value.
|
||||
#
|
||||
# Assigning 0/1/2 to non-bool/tristate symbols has no effect (int/hex
|
||||
# symbols still take a string, because they preserve formatting).
|
||||
for sym in kconf.unique_defined_syms:
|
||||
# Set choice symbols to 'm'. This value will be ignored for choices in
|
||||
# 'y' mode (the "normal" mode), which will instead just get their
|
||||
# default selection, but will set all symbols in m-mode choices to 'm',
|
||||
# which is as high as they can go.
|
||||
#
|
||||
# Here's a convoluted example of how you might get an m-mode choice
|
||||
# even during allyesconfig:
|
||||
#
|
||||
# choice
|
||||
# tristate "weird choice"
|
||||
# depends on m
|
||||
sym.set_value(1 if sym.choice else 2)
|
||||
|
||||
# Set all choices to the highest possible mode
|
||||
for choice in kconf.unique_choices:
|
||||
choice.set_value(2)
|
||||
|
||||
kconf.warn = True
|
||||
|
||||
kconf.load_allconfig("allyes.config")
|
||||
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
43
tools/kconfig/defconfig.py
Executable file
43
tools/kconfig/defconfig.py
Executable file
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Reads a specified configuration file, then writes a new configuration file.
|
||||
This can be used to initialize the configuration from e.g. an arch-specific
|
||||
configuration file. This input configuration file would usually be a minimal
|
||||
configuration file, as generated by e.g. savedefconfig.
|
||||
|
||||
The default output filename is '.config'. A different filename can be passed in
|
||||
the KCONFIG_CONFIG environment variable.
|
||||
"""
|
||||
import argparse
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
"--kconfig",
|
||||
default="Kconfig",
|
||||
help="Top-level Kconfig file (default: Kconfig)")
|
||||
|
||||
parser.add_argument(
|
||||
"config",
|
||||
metavar="CONFIGURATION",
|
||||
help="Input configuration file")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True)
|
||||
print(kconf.load_config(args.config))
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
154
tools/kconfig/genconfig.py
Executable file
154
tools/kconfig/genconfig.py
Executable file
|
@ -0,0 +1,154 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Generates a header file with #defines from the configuration, matching the
|
||||
format of include/generated/autoconf.h in the Linux kernel.
|
||||
|
||||
Optionally, also writes the configuration output as a .config file. See
|
||||
--config-out.
|
||||
|
||||
The --sync-deps, --file-list, and --env-list options generate information that
|
||||
can be used to avoid needless rebuilds/reconfigurations.
|
||||
|
||||
Before writing a header or configuration file, Kconfiglib compares the old
|
||||
contents of the file against the new contents. If there's no change, the write
|
||||
is skipped. This avoids updating file metadata like the modification time, and
|
||||
might save work depending on your build setup.
|
||||
|
||||
By default, the configuration is generated from '.config'. A different
|
||||
configuration file can be passed in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
A custom header string can be inserted at the beginning of generated
|
||||
configuration and header files by setting the KCONFIG_CONFIG_HEADER and
|
||||
KCONFIG_AUTOHEADER_HEADER environment variables, respectively (this also works
|
||||
for other scripts). The string is not automatically made a comment (this is by
|
||||
design, to allow anything to be added), and no trailing newline is added, so
|
||||
add '/* */', '#', and newlines as appropriate.
|
||||
|
||||
See https://www.gnu.org/software/make/manual/make.html#Multi_002dLine for a
|
||||
handy way to define multi-line variables in makefiles, for use with custom
|
||||
headers. Remember to export the variable to the environment.
|
||||
"""
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
DEFAULT_SYNC_DEPS_PATH = "deps/"
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
"--header-path",
|
||||
metavar="HEADER_FILE",
|
||||
help="""
|
||||
Path to write the generated header file to. If not specified, the path in the
|
||||
environment variable KCONFIG_AUTOHEADER is used if it is set, and 'config.h'
|
||||
otherwise.
|
||||
""")
|
||||
|
||||
parser.add_argument(
|
||||
"--config-out",
|
||||
metavar="CONFIG_FILE",
|
||||
help="""
|
||||
Write the configuration to CONFIG_FILE. This is useful if you include .config
|
||||
files in Makefiles, as the generated configuration file will be a full .config
|
||||
file even if .config is outdated. The generated configuration matches what
|
||||
olddefconfig would produce. If you use sync-deps, you can include
|
||||
deps/auto.conf instead. --config-out is meant for cases where incremental build
|
||||
information isn't needed.
|
||||
""")
|
||||
|
||||
parser.add_argument(
|
||||
"--sync-deps",
|
||||
metavar="OUTPUT_DIR",
|
||||
nargs="?",
|
||||
const=DEFAULT_SYNC_DEPS_PATH,
|
||||
help="""
|
||||
Enable generation of symbol dependency information for incremental builds,
|
||||
optionally specifying the output directory (default: {}). See the docstring of
|
||||
Kconfig.sync_deps() in Kconfiglib for more information.
|
||||
""".format(DEFAULT_SYNC_DEPS_PATH))
|
||||
|
||||
parser.add_argument(
|
||||
"--file-list",
|
||||
metavar="OUTPUT_FILE",
|
||||
help="""
|
||||
Write a list of all Kconfig files to OUTPUT_FILE, with one file per line. The
|
||||
paths are relative to $srctree (or to the current directory if $srctree is
|
||||
unset). Files appear in the order they're 'source'd.
|
||||
""")
|
||||
|
||||
parser.add_argument(
|
||||
"--env-list",
|
||||
metavar="OUTPUT_FILE",
|
||||
help="""
|
||||
Write a list of all environment variables referenced in Kconfig files to
|
||||
OUTPUT_FILE, with one variable per line. Each line has the format NAME=VALUE.
|
||||
Only environment variables referenced with the preprocessor $(VAR) syntax are
|
||||
included, and not variables referenced with the older $VAR syntax (which is
|
||||
only supported for backwards compatibility).
|
||||
""")
|
||||
|
||||
parser.add_argument(
|
||||
"kconfig",
|
||||
metavar="KCONFIG",
|
||||
nargs="?",
|
||||
default="Kconfig",
|
||||
help="Top-level Kconfig file (default: Kconfig)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True)
|
||||
kconf.load_config()
|
||||
|
||||
if args.header_path is None:
|
||||
if "KCONFIG_AUTOHEADER" in os.environ:
|
||||
kconf.write_autoconf()
|
||||
else:
|
||||
# Kconfiglib defaults to include/generated/autoconf.h to be
|
||||
# compatible with the C tools. 'config.h' is used here instead for
|
||||
# backwards compatibility. It's probably a saner default for tools
|
||||
# as well.
|
||||
kconf.write_autoconf("config.h")
|
||||
else:
|
||||
kconf.write_autoconf(args.header_path)
|
||||
|
||||
if args.config_out is not None:
|
||||
kconf.write_config(args.config_out, save_old=False)
|
||||
|
||||
if args.sync_deps is not None:
|
||||
kconf.sync_deps(args.sync_deps)
|
||||
|
||||
if args.file_list is not None:
|
||||
with _open_write(args.file_list) as f:
|
||||
for path in kconf.kconfig_filenames:
|
||||
f.write(path + "\n")
|
||||
|
||||
if args.env_list is not None:
|
||||
with _open_write(args.env_list) as f:
|
||||
for env_var in kconf.env_vars:
|
||||
f.write("{}={}\n".format(env_var, os.environ[env_var]))
|
||||
|
||||
|
||||
def _open_write(path):
|
||||
# Python 2/3 compatibility. io.open() is available on both, but makes
|
||||
# write() expect 'unicode' strings on Python 2.
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
return open(path, "w")
|
||||
return open(path, "w", encoding="utf-8")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
157
tools/kconfig/gensdkconfig.py
Executable file
157
tools/kconfig/gensdkconfig.py
Executable file
|
@ -0,0 +1,157 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# @file from https://github.com/Neutree/c_cpp_project_framework
|
||||
# @author neucrack
|
||||
#
|
||||
|
||||
import argparse
|
||||
import os, sys
|
||||
|
||||
kconfig_lib_path = sys.path[0]+"/Kconfiglib"
|
||||
sys.path.append(kconfig_lib_path)
|
||||
|
||||
import kconfiglib
|
||||
from menuconfig import menuconfig
|
||||
|
||||
|
||||
def _cmake_contents(kconfig, header):
|
||||
chunks = [header]
|
||||
add = chunks.append
|
||||
config_vars = []
|
||||
for sym in kconfig.unique_defined_syms:
|
||||
# _write_to_conf is determined when the value is calculated. This
|
||||
# is a hidden function call due to property magic.
|
||||
val = sym.str_value
|
||||
# print("sym: " + sym.name + " val: " + val)
|
||||
if not sym._write_to_conf:
|
||||
continue
|
||||
if sym.orig_type in (kconfiglib.BOOL, kconfiglib.TRISTATE):
|
||||
if val == "n":
|
||||
add("set({}{} 0)\n".format(
|
||||
kconfig.config_prefix, sym.name))
|
||||
else:
|
||||
add("set({}{} 1)\n".format(
|
||||
kconfig.config_prefix, sym.name))
|
||||
else:
|
||||
add("set({}{} \"{}\")\n".format(
|
||||
kconfig.config_prefix, sym.name, val))
|
||||
|
||||
config_vars.append(str(kconfig.config_prefix+sym.name))
|
||||
return "".join(chunks)
|
||||
|
||||
|
||||
def write_config(kconfig):
|
||||
filename = args.projectdir + "/" + "sdkconfig"
|
||||
print("-- Write Project config to: " + filename)
|
||||
kconfig.write_config(filename)
|
||||
|
||||
def write_cmake(kconfig):
|
||||
filename = args.projectdir + "/" + "proj.conf"
|
||||
print("-- Write CMake config to: " + filename)
|
||||
cmake_conf_header = "# Generated by KConfig!\n"
|
||||
cmake_conf_header += "### DO NOT edit this file!! ###\n"
|
||||
cmake_conf_header += "### Run make config instead ###\n\n"
|
||||
cmake_conf_content = _cmake_contents(kconfig, cmake_conf_header)
|
||||
# don't change file info if config no change
|
||||
if os.path.exists(filename):
|
||||
with open(filename) as f:
|
||||
if f.read() == cmake_conf_content:
|
||||
return
|
||||
f = open(filename, "w")
|
||||
f.write(cmake_conf_content)
|
||||
f.close()
|
||||
|
||||
|
||||
def write_header(kconfig):
|
||||
filename = "sdkconfig.h"
|
||||
print("-- write C header file at: " + args.header + "/" + filename)
|
||||
print(kconfig.write_autoconf( args.header + "/" + filename))
|
||||
|
||||
OUTPUT_FORMATS = {
|
||||
"makefile": write_config,
|
||||
"header": write_header,
|
||||
"cmake": write_cmake
|
||||
}
|
||||
|
||||
parser = argparse.ArgumentParser(description='menuconfig tool', prog=os.path.basename(sys.argv[0]))
|
||||
|
||||
parser.add_argument('--sdkpath',
|
||||
help='SDK path',
|
||||
default='../../',
|
||||
required=None,
|
||||
metavar='SDKPATH')
|
||||
|
||||
parser.add_argument('--defaults',
|
||||
action='append',
|
||||
default=["sdkconfig.default"],
|
||||
help='Optional project defaults file. '
|
||||
'Multiple files can be specified using multiple --defaults arguments.',
|
||||
metavar="FILENAME"
|
||||
)
|
||||
|
||||
parser.add_argument('--env',
|
||||
action='append',
|
||||
default=[],
|
||||
help='Environment to set when evaluating the config file',
|
||||
metavar='VAR=VALUE'
|
||||
)
|
||||
|
||||
parser.add_argument("--menuconfig",
|
||||
help="Open menuconfig GUI interface",
|
||||
)
|
||||
|
||||
parser.add_argument("--cmake",
|
||||
help="Generate CMake config file",
|
||||
)
|
||||
|
||||
parser.add_argument("--header",
|
||||
help="Generate C header file",
|
||||
)
|
||||
|
||||
parser.add_argument("--projectdir",
|
||||
default=".",
|
||||
help="Project Directory (for .config and config_default)",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
for env in args.env:
|
||||
env = env.split("=")
|
||||
var = env[0]
|
||||
value = env[1]
|
||||
os.environ[var] = value
|
||||
|
||||
out_format = ["makefile", "header", "cmake"]
|
||||
os.environ["KCONFIG_CONFIG"] = args.projectdir + "/sdkconfig"
|
||||
os.environ["srctree"] = args.projectdir
|
||||
print("Project Config File Path: " + os.environ["KCONFIG_CONFIG"])
|
||||
|
||||
sdkconfig = args.sdkpath + "/cmake/SDKconfig"
|
||||
|
||||
kconfig = kconfiglib.Kconfig(sdkconfig)
|
||||
kconfig.warn = True
|
||||
|
||||
if args.defaults:
|
||||
for path in args.defaults:
|
||||
path = args.projectdir + "/" + path
|
||||
print("Attemping to load default config: " + path)
|
||||
if os.path.exists(path):
|
||||
print("Load Default config: " + path)
|
||||
kconfig.load_config(path, replace=False)
|
||||
else:
|
||||
print("Warning: Default Config file not found: " + path)
|
||||
|
||||
if os.path.exists(args.projectdir + "/sdkconfig"):
|
||||
print("Load Project config: " + args.projectdir + "/sdkconfig")
|
||||
kconfig.load_config(args.projectdir + "/sdkconfig")
|
||||
|
||||
|
||||
if args.menuconfig:
|
||||
menuconfig(kconfig)
|
||||
|
||||
write_config(kconfig)
|
||||
|
||||
if args.cmake:
|
||||
write_cmake(kconfig)
|
||||
if args.header:
|
||||
write_header(kconfig)
|
2324
tools/kconfig/guiconfig.py
Executable file
2324
tools/kconfig/guiconfig.py
Executable file
File diff suppressed because it is too large
Load diff
7160
tools/kconfig/kconfiglib.py
Normal file
7160
tools/kconfig/kconfiglib.py
Normal file
File diff suppressed because it is too large
Load diff
76
tools/kconfig/listnewconfig.py
Executable file
76
tools/kconfig/listnewconfig.py
Executable file
|
@ -0,0 +1,76 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Lists all user-modifiable symbols that are not given a value in the
|
||||
configuration file. Usually, these are new symbols that have been added to the
|
||||
Kconfig files.
|
||||
|
||||
The default configuration filename is '.config'. A different filename can be
|
||||
passed in the KCONFIG_CONFIG environment variable.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, BOOL, TRISTATE, INT, HEX, STRING, TRI_TO_STR
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
"--show-help", "-l",
|
||||
action="store_true",
|
||||
help="Show any help texts as well")
|
||||
|
||||
parser.add_argument(
|
||||
"kconfig",
|
||||
metavar="KCONFIG",
|
||||
nargs="?",
|
||||
default="Kconfig",
|
||||
help="Top-level Kconfig file (default: Kconfig)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
kconf = Kconfig(args.kconfig, suppress_traceback=True)
|
||||
# Make it possible to filter this message out
|
||||
print(kconf.load_config(), file=sys.stderr)
|
||||
|
||||
for sym in kconf.unique_defined_syms:
|
||||
# Only show symbols that can be toggled. Choice symbols are a special
|
||||
# case in that sym.assignable will be (2,) (length 1) for visible
|
||||
# symbols in choices in y mode, but they can still be toggled by
|
||||
# selecting some other symbol.
|
||||
if sym.user_value is None and \
|
||||
(len(sym.assignable) > 1 or
|
||||
(sym.visibility and (sym.orig_type in (INT, HEX, STRING) or
|
||||
sym.choice))):
|
||||
|
||||
# Don't reuse the 'config_string' format for bool/tristate symbols,
|
||||
# to show n-valued symbols as 'CONFIG_FOO=n' instead of
|
||||
# '# CONFIG_FOO is not set'. This matches the C tools.
|
||||
if sym.orig_type in (BOOL, TRISTATE):
|
||||
s = "{}{}={}\n".format(kconf.config_prefix, sym.name,
|
||||
TRI_TO_STR[sym.tri_value])
|
||||
else:
|
||||
s = sym.config_string
|
||||
|
||||
print(s, end="")
|
||||
if args.show_help:
|
||||
for node in sym.nodes:
|
||||
if node.help is not None:
|
||||
# Indent by two spaces. textwrap.indent() is not
|
||||
# available in Python 2 (it's 3.3+).
|
||||
print("\n".join(" " + line
|
||||
for line in node.help.split("\n")))
|
||||
break
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
3278
tools/kconfig/menuconfig.py
Executable file
3278
tools/kconfig/menuconfig.py
Executable file
File diff suppressed because it is too large
Load diff
246
tools/kconfig/oldconfig.py
Executable file
246
tools/kconfig/oldconfig.py
Executable file
|
@ -0,0 +1,246 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Implements oldconfig functionality.
|
||||
|
||||
1. Loads existing .config
|
||||
2. Prompts for the value of all modifiable symbols/choices that
|
||||
aren't already set in the .config
|
||||
3. Writes an updated .config
|
||||
|
||||
The default input/output filename is '.config'. A different filename can be
|
||||
passed in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
When overwriting a configuration file, the old version is saved to
|
||||
<filename>.old (e.g. .config.old).
|
||||
|
||||
Entering '?' displays the help text of the symbol/choice, if any.
|
||||
|
||||
Unlike 'make oldconfig', this script doesn't print menu titles and comments,
|
||||
but gives Kconfig definition locations. Printing menus and comments would be
|
||||
pretty easy to add: Look at the parents of each item, and print all menu
|
||||
prompts and comments unless they have already been printed (assuming you want
|
||||
to skip "irrelevant" menus).
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
from kconfiglib import Symbol, Choice, BOOL, TRISTATE, HEX, standard_kconfig
|
||||
|
||||
|
||||
# Python 2/3 compatibility hack
|
||||
if sys.version_info[0] < 3:
|
||||
input = raw_input
|
||||
|
||||
|
||||
def _main():
|
||||
# Earlier symbols in Kconfig files might depend on later symbols and become
|
||||
# visible if their values change. This flag is set to True if the value of
|
||||
# any symbol changes, in which case we rerun the oldconfig to check for new
|
||||
# visible symbols.
|
||||
global conf_changed
|
||||
|
||||
kconf = standard_kconfig(__doc__)
|
||||
print(kconf.load_config())
|
||||
|
||||
while True:
|
||||
conf_changed = False
|
||||
|
||||
for node in kconf.node_iter():
|
||||
oldconfig(node)
|
||||
|
||||
if not conf_changed:
|
||||
break
|
||||
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
def oldconfig(node):
|
||||
"""
|
||||
Prompts the user for a value if node.item is a visible symbol/choice with
|
||||
no user value.
|
||||
"""
|
||||
# See main()
|
||||
global conf_changed
|
||||
|
||||
# Only symbols and choices can be configured
|
||||
if not isinstance(node.item, (Symbol, Choice)):
|
||||
return
|
||||
|
||||
# Skip symbols and choices that aren't visible
|
||||
if not node.item.visibility:
|
||||
return
|
||||
|
||||
# Skip symbols and choices that don't have a prompt (at this location)
|
||||
if not node.prompt:
|
||||
return
|
||||
|
||||
if isinstance(node.item, Symbol):
|
||||
sym = node.item
|
||||
|
||||
# Skip symbols that already have a user value
|
||||
if sym.user_value is not None:
|
||||
return
|
||||
|
||||
# Skip symbols that can only have a single value, due to selects
|
||||
if len(sym.assignable) == 1:
|
||||
return
|
||||
|
||||
# Skip symbols in choices in y mode. We ask once for the entire choice
|
||||
# instead.
|
||||
if sym.choice and sym.choice.tri_value == 2:
|
||||
return
|
||||
|
||||
# Loop until the user enters a valid value or enters a blank string
|
||||
# (for the default value)
|
||||
while True:
|
||||
val = input("{} ({}) [{}] ".format(
|
||||
node.prompt[0], _name_and_loc_str(sym),
|
||||
_default_value_str(sym)))
|
||||
|
||||
if val == "?":
|
||||
_print_help(node)
|
||||
continue
|
||||
|
||||
# Substitute a blank string with the default value the symbol
|
||||
# would get
|
||||
if not val:
|
||||
val = sym.str_value
|
||||
|
||||
# Automatically add a "0x" prefix for hex symbols, like the
|
||||
# menuconfig interface does. This isn't done when loading .config
|
||||
# files, hence why set_value() doesn't do it automatically.
|
||||
if sym.type == HEX and not val.startswith(("0x", "0X")):
|
||||
val = "0x" + val
|
||||
|
||||
old_str_val = sym.str_value
|
||||
|
||||
# Kconfiglib itself will print a warning here if the value
|
||||
# is invalid, so we don't need to bother
|
||||
if sym.set_value(val):
|
||||
# Valid value input. We're done with this node.
|
||||
|
||||
if sym.str_value != old_str_val:
|
||||
conf_changed = True
|
||||
|
||||
return
|
||||
|
||||
else:
|
||||
choice = node.item
|
||||
|
||||
# Skip choices that already have a visible user selection...
|
||||
if choice.user_selection and choice.user_selection.visibility == 2:
|
||||
# ...unless there are new visible symbols in the choice. (We know
|
||||
# they have y (2) visibility in that case, because m-visible
|
||||
# symbols get demoted to n-visibility in y-mode choices, and the
|
||||
# user-selected symbol had visibility y.)
|
||||
for sym in choice.syms:
|
||||
if sym is not choice.user_selection and sym.visibility and \
|
||||
sym.user_value is None:
|
||||
# New visible symbols in the choice
|
||||
break
|
||||
else:
|
||||
# No new visible symbols in the choice
|
||||
return
|
||||
|
||||
# Get a list of available selections. The mode of the choice limits
|
||||
# the visibility of the choice value symbols, so this will indirectly
|
||||
# skip choices in n and m mode.
|
||||
options = [sym for sym in choice.syms if sym.visibility == 2]
|
||||
|
||||
if not options:
|
||||
# No y-visible choice value symbols
|
||||
return
|
||||
|
||||
# Loop until the user enters a valid selection or a blank string (for
|
||||
# the default selection)
|
||||
while True:
|
||||
print("{} ({})".format(node.prompt[0], _name_and_loc_str(choice)))
|
||||
|
||||
for i, sym in enumerate(options, 1):
|
||||
print("{} {}. {} ({})".format(
|
||||
">" if sym is choice.selection else " ",
|
||||
i,
|
||||
# Assume people don't define choice symbols with multiple
|
||||
# prompts. That generates a warning anyway.
|
||||
sym.nodes[0].prompt[0],
|
||||
sym.name))
|
||||
|
||||
sel_index = input("choice[1-{}]: ".format(len(options)))
|
||||
|
||||
if sel_index == "?":
|
||||
_print_help(node)
|
||||
continue
|
||||
|
||||
# Pick the default selection if the string is blank
|
||||
if not sel_index:
|
||||
choice.selection.set_value(2)
|
||||
break
|
||||
|
||||
try:
|
||||
sel_index = int(sel_index)
|
||||
except ValueError:
|
||||
print("Bad index", file=sys.stderr)
|
||||
continue
|
||||
|
||||
if not 1 <= sel_index <= len(options):
|
||||
print("Bad index", file=sys.stderr)
|
||||
continue
|
||||
|
||||
# Valid selection
|
||||
|
||||
if options[sel_index - 1].tri_value != 2:
|
||||
conf_changed = True
|
||||
|
||||
options[sel_index - 1].set_value(2)
|
||||
break
|
||||
|
||||
# Give all of the non-selected visible choice symbols the user value n.
|
||||
# This makes it so that the choice is no longer considered new once we
|
||||
# do additional passes, if the reason that it was considered new was
|
||||
# that it had new visible choice symbols.
|
||||
#
|
||||
# Only giving visible choice symbols the user value n means we will
|
||||
# prompt for the choice again if later user selections make more new
|
||||
# choice symbols visible, which is correct.
|
||||
for sym in choice.syms:
|
||||
if sym is not choice.user_selection and sym.visibility:
|
||||
sym.set_value(0)
|
||||
|
||||
|
||||
def _name_and_loc_str(sc):
|
||||
# Helper for printing the name of the symbol/choice 'sc' along with the
|
||||
# location(s) in the Kconfig files where it is defined. Unnamed choices
|
||||
# return "choice" instead of the name.
|
||||
|
||||
return "{}, defined at {}".format(
|
||||
sc.name or "choice",
|
||||
", ".join("{}:{}".format(node.filename, node.linenr)
|
||||
for node in sc.nodes))
|
||||
|
||||
|
||||
def _print_help(node):
|
||||
print("\n" + (node.help or "No help text\n"))
|
||||
|
||||
|
||||
def _default_value_str(sym):
|
||||
# Returns the "m/M/y" string in e.g.
|
||||
#
|
||||
# TRISTATE_SYM prompt (TRISTATE_SYM, defined at Kconfig:9) [n/M/y]:
|
||||
#
|
||||
# For string/int/hex, returns the default value as-is.
|
||||
|
||||
if sym.type in (BOOL, TRISTATE):
|
||||
return "/".join(("NMY" if sym.tri_value == tri else "nmy")[tri]
|
||||
for tri in sym.assignable)
|
||||
|
||||
# string/int/hex
|
||||
return sym.str_value
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_main()
|
28
tools/kconfig/olddefconfig.py
Executable file
28
tools/kconfig/olddefconfig.py
Executable file
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Updates an old .config file or creates a new one, by filling in default values
|
||||
for all new symbols. This is the same as picking the default selection for all
|
||||
symbols in oldconfig, or entering the menuconfig interface and immediately
|
||||
saving.
|
||||
|
||||
The default input/output filename is '.config'. A different filename can be
|
||||
passed in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
When overwriting a configuration file, the old version is saved to
|
||||
<filename>.old (e.g. .config.old).
|
||||
"""
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
kconf = kconfiglib.standard_kconfig(__doc__)
|
||||
print(kconf.load_config())
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
49
tools/kconfig/savedefconfig.py
Executable file
49
tools/kconfig/savedefconfig.py
Executable file
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Saves a minimal configuration file that only lists symbols that differ in value
|
||||
from their defaults. Loading such a configuration file is equivalent to loading
|
||||
the "full" configuration file.
|
||||
|
||||
Minimal configuration files are handy to start from when editing configuration
|
||||
files by hand.
|
||||
|
||||
The default input configuration file is '.config'. A different input filename
|
||||
can be passed in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
Note: Minimal configurations can also be generated from within the menuconfig
|
||||
interface.
|
||||
"""
|
||||
import argparse
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
"--kconfig",
|
||||
default="Kconfig",
|
||||
help="Top-level Kconfig file (default: Kconfig)")
|
||||
|
||||
parser.add_argument(
|
||||
"--out",
|
||||
metavar="MINIMAL_CONFIGURATION",
|
||||
default="defconfig",
|
||||
help="Output filename for minimal configuration (default: defconfig)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True)
|
||||
print(kconf.load_config())
|
||||
print(kconf.write_min_config(args.out))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
92
tools/kconfig/setconfig.py
Executable file
92
tools/kconfig/setconfig.py
Executable file
|
@ -0,0 +1,92 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
"""
|
||||
Simple utility for setting configuration values from the command line.
|
||||
|
||||
Sample usage:
|
||||
|
||||
$ setconfig FOO_SUPPORT=y BAR_BITS=8
|
||||
|
||||
Note: Symbol names should not be prefixed with 'CONFIG_'.
|
||||
|
||||
The exit status on errors is 1.
|
||||
|
||||
The default input/output configuration file is '.config'. A different filename
|
||||
can be passed in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
When overwriting a configuration file, the old version is saved to
|
||||
<filename>.old (e.g. .config.old).
|
||||
"""
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
"--kconfig",
|
||||
default="Kconfig",
|
||||
help="Top-level Kconfig file (default: Kconfig)")
|
||||
|
||||
parser.add_argument(
|
||||
"--no-check-exists",
|
||||
dest="check_exists",
|
||||
action="store_false",
|
||||
help="Ignore assignments to non-existent symbols instead of erroring "
|
||||
"out")
|
||||
|
||||
parser.add_argument(
|
||||
"--no-check-value",
|
||||
dest="check_value",
|
||||
action="store_false",
|
||||
help="Ignore assignments that didn't \"take\" (where the symbol got a "
|
||||
"different value, e.g. due to unsatisfied dependencies) instead "
|
||||
"of erroring out")
|
||||
|
||||
parser.add_argument(
|
||||
"assignments",
|
||||
metavar="ASSIGNMENT",
|
||||
nargs="*",
|
||||
help="A 'NAME=value' assignment")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True)
|
||||
print(kconf.load_config())
|
||||
|
||||
for arg in args.assignments:
|
||||
if "=" not in arg:
|
||||
sys.exit("error: no '=' in assignment: '{}'".format(arg))
|
||||
name, value = arg.split("=", 1)
|
||||
|
||||
if name not in kconf.syms:
|
||||
if not args.check_exists:
|
||||
continue
|
||||
sys.exit("error: no symbol '{}' in configuration".format(name))
|
||||
|
||||
sym = kconf.syms[name]
|
||||
|
||||
if not sym.set_value(value):
|
||||
sys.exit("error: '{}' is an invalid value for the {} symbol {}"
|
||||
.format(value, kconfiglib.TYPE_TO_STR[sym.orig_type],
|
||||
name))
|
||||
|
||||
if args.check_value and sym.str_value != value:
|
||||
sys.exit("error: {} was assigned the value '{}', but got the "
|
||||
"value '{}'. Check the symbol's dependencies, and make "
|
||||
"sure that it has a prompt."
|
||||
.format(name, value, sym.str_value))
|
||||
|
||||
print(kconf.write_config())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Add table
Reference in a new issue