1. 8051核¶
1.1. 8051核¶
LubanCat-P1基于Sophgo SG2000 SoC,多核架构信息:
一个T-Head C906 64-bit RISC-V CPU核(1GHz)
一个ARM Cortex-A53 CPU核(1GHz)
一个T-Head C906 64位RISC-V核(700Mhz)
一个8051 8-bit低功耗mcu核(25-300MHz)
C906 riscv大核和A53核可以运行Linux系统,C906 riscv小核可以运行Freertos,8051核可以运行裸机。
8051子系统位于由RTC独立供电的模块中,该子系统配置有8051、I2C/UART/SPI NOR/SD 控制器、定时器/WDT、中断管理和Mailbox IP。 系统软件可以使用8051管理唤醒条件并在睡眠模式下唤醒系统,并通过外设控制器与外部设备通信。
默认分配给8051核的运行内存为512kb,可修改SDK进行调整。
1.2. 8051核运行测试¶
1.2.1. 获取源码¶
1 | git clone https://gitee.com/LubanCat/lubancat_sg2000_code_storage.git
|
8051部分代码为于:lubancat_sg2000_code_storage/quick_start/8051/
目录说明如下:
doc:d8051手册
firmware:编译好的固件
sdcc:驱动文件和测试代码
tools:编译工具和核心启动源码
1.2.2. 编译程序¶
在firmware目录下已经有编译好的固件,可直接使用测试,以下介绍如何编译源码:
1、8051_up
8051_up用于自动更新固件并启动8051核。
进入lubancat_sg2000_code_storage/quick_start/8051/tools/8051_up目录,执行编译:
1 2 3 4 5 6 7 8 | #编译
make
#如果是交叉编译,需指定TOOLCHAIN_PREFIX变量,修改makefile,指定编译器绝对路径
TOOLCHAIN_PREFIX = /home/guest/sg200x/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-
CC = $(TOOLCHAIN_PREFIX)gcc
#编译
make
|
生成的8051_up就是需要的可执行程序。
2、mars_mcu_fw.bin
mars_mcu_fw.bin为8051程序固件,需要在虚拟机或者服务器进行编译,在板卡无法编译。
进入lubancat_sg2000_code_storage/quick_start/8051/sdcc/mars/project/base_project目录,执行编译:
1 2 | #编译
make
|
生成的output/mars_mcu_fw.bin就是需要的固件。
其中8051/sdcc/mars/project/base_project/src/main.c就是程序的主体部分。
1.2.3. 运行测试¶
如果没有编译,可直接使用lubancat_sg2000_code_storage/quick_start/8051/firmware目录下编译好的。
1、将mars_mcu_fw.bin放到板卡的 /lib/firmware/ 目录下。
2、将8051_up传输到板卡任意目录,lubancat_sg2000_code_storage/quick_start/8051/firmware/8051_boot_cfg.ini放到与8051_up同级目录下。
1 2 3 4 5 6 7 8 9 | #添加执行权限并运行
sudo chmod 777 8051_up
sudo ./8051_up
#信息输出如下
8051 will boot on address 9ff80000
load mcu fw: /lib/firmware/mars_mcu_fw.bin
size = 7827
done
|
其中8051_boot_cfg.ini定义了8051核启动的地址,为0x9ff80000,加载固件/lib/firmware/mars_mcu_fw.bin
3、创建blink.sh,内容如下:
1 2 3 4 5 6 7 | while true
do
devmem 0x05026020 w 6
sleep 1
devmem 0x05026020 w 7
sleep 1
done
|
4、运行:
由于Linux驱动层已经占用sys_led,需要先释放占用,执行以下命令:
1 2 3 4 5 | #释放占用
sudo sh -c "echo 0 > /sys/class/leds/sys_status_led/brightness"
#如果需要恢复则执行
sudo sh -c "echo heartbeat > /sys/class/leds/sys_status_led/trigger"
|
运行blink.sh:
1 2 3 4 5 6 7 8 9 | #添加执行权限并运行
sudo chmod 777 blink.sh
sudo ./blink.sh
#信息输出如下
LED_GPIO->HIGH
LED_GPIO->LOW
LED_GPIO->HIGH
LED_GPIO->LOW
|
5、实验现象
系统sys_led会1s周期交替亮灭。
1.2.4. 程序说明¶
8051/sdcc/mars/project/base_project/src/main.c就是程序的主体部分,截取部分内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | void main(void)
{
uint32_t i2c_cmd = 0xffffffff;
uint32_t suspend_mode = 0x0;
uint8_t rw = 0xff;
uint8_t reg = 0xff;
uint8_t value = 0xff;
uint32_t reg_val = 0xff;
uint32_t fsm_state = 0x0;
//CKCON = 0x7;
/* init dw uart*/
#ifdef CONFIG_PUTCHAR_DW_UART
//dw_uart_init();
#endif
// printf("cvitek mcu init2 %s\n", __TIME__);
mmio_write_32(RTC_INFO0, 0x8051);
/* init interrupt controller */
dw_ictl_init();
/* enable interrupt controller*/
ap2rtc_irq_init();
irq_enable();
while(1) {
rw = mmio_read_32(RTC_INFO1); // 0x05026020
//printf("case1 uart test\n");
switch (rw) {
case 0x0: /* uart test */
printf("case1 uart test\n");
mmio_write_32(RTC_INFO1, 0xff);
break;
case 0x1: /* i2c test */
#if 1
cv_i2c_pinmux_io_switch(1);
reset_i2c_cmd();
if (!cv_i2c_is_busy()) {
delay_us(2);
cv_i2c_master_write(0x90, 0x11);
} else {
mmio_write_32(RTC_INFO2, 0x66666666);
printf("RTC_I2C is busy or corrupted\n");
}
mmio_write_32(RTC_INFO1, 0xff);
#endif
break;
case 0x2: /* wdg test */
pwr_wdt_start();
mmio_write_32(RTC_INFO1, 0xff);
break;
case 0x3: /* wdg test */
dw_wdt_ping();
mmio_write_32(RTC_INFO1, 0xff);
break;
case 0x4: /* wdg test */
dw_wdt_rst();
mmio_write_32(RTC_INFO1, 0xff);
break;
case 0x5: /* wdg test */
dw_wdt_rst_realease();
mmio_write_32(RTC_INFO1, 0xff);
break;
case 0x6: /* gpio_high */
set_gpio_direction(GPIO1_BASE,11,GPIO_DIRECTION_OUT);
set_gpio_level(GPIO1_BASE,11,GPIO_LEVEL_HIGH);
mmio_write_32(RTC_INFO1, 0xff);
printf("LED_GPIO->HIGH\n");
break;
case 0x7: /* gpio_low */
set_gpio_direction(GPIO1_BASE,11,GPIO_DIRECTION_OUT);
set_gpio_level(GPIO1_BASE,11,GPIO_LEVEL_LOW);
mmio_write_32(RTC_INFO1, 0xff);
printf("LED_GPIO->LOW\n");
break;
default:
break;
}
}
}
|
初始化完成后会不断读取RTC_INFO1寄存器的值,然后执行对于的代码。
RTC_INFO1寄存器值可以查阅sg2000_trm_cn.pdf手册找到相关地址定义,手册在资料网盘/5-数据手册目录中。
RTC_INFO1寄存器位于RTC寄存器,基地址为0x05026000,偏移地址为0x020。
所以blink.sh中通过devmem工具修改0x05026020寄存器地址的值为6/7,就会执行led控制部分程序,控制引脚高低电平。