基于NANO 9K 开发板加载PICORV32软核,并建立交叉编译环境

目录

0. 环境准备

1. 安装交叉编译器 

2. 理解makefile工作机理

3. 熟悉示例程序的代码结构,理解软核代码的底层驱动原理

4. 熟悉烧录环节的工作机理, 建立下载环境 

5. 编写例子blink, printf等, 加载运行

6. 后续任务

 


0. 环境准备

NANO 9K低成本体验FPGA开发,还是挺香的,官方例子有加载PICORV32软核的例子,可以建立简单的ISP编程环境,通过串口就可以加载程序,很方便。 

Tang Nano 9K picoRV 简单示例 - Sipeed Wiki

运行效果 

可以通过命令行进行点灯喝运行benchmark等操作。 

相当于例子包括了: 

  • 串口打印,
  • 串口接收指令
  • GPIO控制

等基本操作。 

如果要基于RISCV软核,进一步熟悉工作机制和编程环境,需要参考例子建立交叉编译环境。 

step by step.......,以下基于虚拟机运行ubuntu18.04环境,少一点干扰。 

为帮助理解, 可以看看高云的官方文档对于picorv32内核架构的介绍: 

1. 安装交叉编译器 

 在虚拟机环境下,解压toolchain到目标目录即可。编译器路径可以在makefile文件里进行指定。 

当然,虚拟机依赖环境至少需要安装make工具,gcc也一起

sudo apt-get install make gcc 

下载地址: 

riscv32交叉编译器,ubuntu18.04亲测可用资源-CSDN文库

2. 理解makefile工作机理

参考文章: 

 从零开始:一步步教你如何写Makefile_makefile菜鸟教程-CSDN博客

makefile组成三要素:目标,依赖, 命令 

picotiny工作示例里有两层makefile, 先看主目录下的: 

PYTHON_NAME ?= python
RISCV_NAME 	?= riscv-none-embed
RISCV_PATH 	?= /home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004
MAKE		?= makeFW_FILE 	 = fw/fw-flash/build/fw-flash.vPROG_FILE	?= $(FW_FILE)
COMx	 	?= COM14export PYTHON_NAME
export RISCV_NAME
export RISCV_PATH.PHONY: all brom flash clean programall: brom flash$(FW_FILE): flashbrom:$(MAKE) -C fw/fw-bromflash:$(MAKE) -C fw/fw-flashclean:$(MAKE) -C fw/fw-brom clean$(MAKE) -C fw/fw-flash cleanprogram: $(PROG_FILE)$(PYTHON_NAME) sw/pico-programmer.py $(PROG_FILE) $(COMx)

第一部分:指定环境变量

第二部分:指定分支

第三部分:分支命令编写

这个根目录下的makefile主要功能:一是执行不同的子目录下 ,二是program命令分支。 

真正编译项目代码的makefile是在子目录下。 

再来看子目录下的makefile

PROJ_NAME=blink-flash
DEBUG=no
BENCH=no
MULDIV=no
COMPRESSED=noSRCS = 	$(wildcard *.c)       		\$(wildcard *.S)LDSCRIPT = ./linker_flash.ldRISCV_NAME ?= riscv-none-embed
RISCV_PATH ?= /home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004MABI=ilp32
MARCH := rv32i
ifeq ($(MULDIV),yes)MARCH := $(MARCH)m
endif
ifeq ($(COMPRESSED),yes)MARCH := $(MARCH)ac
endifCFLAGS += -march=$(MARCH)  -mabi=$(MABI)  -ffunction-sections -fdata-sections
LDFLAGS += -march=$(MARCH)  -mabi=$(MABI)  -Wl,--gc-sectionsifeq ($(DEBUG),yes)CFLAGS += -g3 -O0 
endififeq ($(DEBUG),no)CFLAGS += -g -O3 
endififeq ($(BENCH),yes)CFLAGS += -fno-inline  
endifRISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/$(MARCH)/$(MABI)/RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy
RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump
RISCV_CC = $(RISCV_PATH)/bin/$(RISCV_NAME)-gccCFLAGS +=  -MD -fstrict-volatile-bitfields 
LDFLAGS +=  -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usageOBJDIR = build
OBJS := $(SRCS)
OBJS := $(OBJS:.c=.o)
OBJS := $(OBJS:.cpp=.o)
OBJS := $(OBJS:.S=.o)
OBJS := $(addprefix $(OBJDIR)/,$(OBJS))SUBOBJ := $(addprefix $(OBJDIR)/,$(SUBDIRS))
SUBOBJ := $(addsuffix /*.o,$(SUBOBJ))export RISCV_CC CFLAGS LDFLAGS OBJDIRall: $(SUBDIRS) $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).v$(SUBDIRS): ECHOmake -C $@ECHO:@echo $(SUBDIRS)$(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)$(RISCV_CC) $(CFLAGS) -o $@ $^ $(SUBOBJ) $(LDFLAGS) $(LIBS)%.hex: %.elf$(RISCV_OBJCOPY) -O ihex $^ $@%.bin: %.elf$(RISCV_OBJCOPY) -O binary $^ $@%.v: %.elf$(RISCV_OBJCOPY) -O verilog $^ $@%.asm: %.elf$(RISCV_OBJDUMP) -S -d $^ > $@$(OBJDIR)/%.o: %.cmkdir -p $(dir $@)$(RISCV_CC) -c $(CFLAGS)  $(INC) -o $@ $^$(OBJDIR)/%.o: %.cppmkdir -p $(dir $@)$(RISCV_CC) -c $(CFLAGS)  $(INC) -o $@ $^	$(OBJDIR)/%.o: %.Smkdir -p $(dir $@)$(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1$(OBJDIR):mkdir -p $@clean:rm -f $(OBJDIR)/$(PROJ_NAME).elfrm -f $(OBJDIR)/$(PROJ_NAME).hexrm -f $(OBJDIR)/$(PROJ_NAME).maprm -f $(OBJDIR)/$(PROJ_NAME).vrm -f $(OBJDIR)/$(PROJ_NAME).asmfind $(OBJDIR) -type f -name '*.d' -print0 | xargs -0 -r rmfind $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm.SECONDARY: $(OBJS)

主要完成的工作: 指定了环境变量,编译输出目标文件,编译后的处理(文件转换等) 。 

编写完示例代码后,可以在子目录下运行make命令,执行响应的makefile即可完成目标代码编译。 

3. 熟悉示例程序的代码结构,理解软核代码的底层驱动原理

4. 熟悉烧录环节的工作机理, 建立下载环境 

 烧录的riscv软核支持ISP(串口在线烧录)功能。 所以make program xxx命令调用的python脚本主要是握手协议和烧录固件的传输。 

简单理解: 软核的ISP功能完成了flash固件的调用启动和程序引导运行工作。 

小知识: 理解ISP

ISP的全称是:In System Programming,即在系统编程,该操作是通过MCU厂商出厂BootLoader来实现,通过ISP可以对主flash区域进行擦除、编程操作,还可以修改芯片的选项字节等。

ISP的实现逻辑是出厂“芯片”(我们这里是软核)自带了BootLoader程序,即出厂引导程序,通过BootLoader可以将程序从串口(上位机)下载到Flash中,实际的时序是通过RST来区分正常启动还是烧录状态,然后上位机的烧录脚本来控制串口时序, 用户程序实际上是通过串口最终下载到了FLASH中,然后程序从flash启动。

5. 编写例子blink, printf等, 加载运行

 1)点灯--blink

blink主要是调用GPIO寄存器写入功能

#include <stdint.h>
#include <stdbool.h>// a pointer to this is a null pointer, but the compiler does not
// know that because "sram" is a linker symbol from sections.lds.
extern uint32_t sram;typedef struct {volatile uint32_t OUT;volatile uint32_t IN;volatile uint32_t OE;
} PICOGPIO;// 寄存器地址
#define GPIO0 ((PICOGPIO*)0x82000000)#define FLASHIO_ENTRY_ADDR ((void *)0x80000054)volatile int i;
// --------------------------------------------------------void main()
{GPIO0->OE = 0x3F;GPIO0->OUT = 0x3F;while (1){for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x01;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x02;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x04;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x08;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x10;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x20;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x00;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F;for ( i = 0 ; i < 10000; i++);}}void irqCallback() {}

 makefile,其实之修改了PROJ_NAME

PROJ_NAME=blink-demo
DEBUG=no
BENCH=no
MULDIV=no
COMPRESSED=noSRCS = 	$(wildcard *.c)       		\$(wildcard *.S)LDSCRIPT = ./linker_flash.ldRISCV_NAME ?= riscv-none-embed
RISCV_PATH ?= /home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004MABI=ilp32
MARCH := rv32i
ifeq ($(MULDIV),yes)MARCH := $(MARCH)m
endif
ifeq ($(COMPRESSED),yes)MARCH := $(MARCH)ac
endifCFLAGS += -march=$(MARCH)  -mabi=$(MABI)  -ffunction-sections -fdata-sections
LDFLAGS += -march=$(MARCH)  -mabi=$(MABI)  -Wl,--gc-sectionsifeq ($(DEBUG),yes)CFLAGS += -g3 -O0 
endififeq ($(DEBUG),no)CFLAGS += -g -O3 
endififeq ($(BENCH),yes)CFLAGS += -fno-inline  
endifRISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/$(MARCH)/$(MABI)/RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy
RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump
RISCV_CC = $(RISCV_PATH)/bin/$(RISCV_NAME)-gccCFLAGS +=  -MD -fstrict-volatile-bitfields 
LDFLAGS +=  -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usageOBJDIR = build
OBJS := $(SRCS)
OBJS := $(OBJS:.c=.o)
OBJS := $(OBJS:.cpp=.o)
OBJS := $(OBJS:.S=.o)
OBJS := $(addprefix $(OBJDIR)/,$(OBJS))SUBOBJ := $(addprefix $(OBJDIR)/,$(SUBDIRS))
SUBOBJ := $(addsuffix /*.o,$(SUBOBJ))export RISCV_CC CFLAGS LDFLAGS OBJDIRall: $(SUBDIRS) $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).v$(SUBDIRS): ECHOmake -C $@ECHO:@echo $(SUBDIRS)$(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)$(RISCV_CC) $(CFLAGS) -o $@ $^ $(SUBOBJ) $(LDFLAGS) $(LIBS)%.hex: %.elf$(RISCV_OBJCOPY) -O ihex $^ $@%.bin: %.elf$(RISCV_OBJCOPY) -O binary $^ $@%.v: %.elf$(RISCV_OBJCOPY) -O verilog $^ $@%.asm: %.elf$(RISCV_OBJDUMP) -S -d $^ > $@$(OBJDIR)/%.o: %.cmkdir -p $(dir $@)$(RISCV_CC) -c $(CFLAGS)  $(INC) -o $@ $^$(OBJDIR)/%.o: %.cppmkdir -p $(dir $@)$(RISCV_CC) -c $(CFLAGS)  $(INC) -o $@ $^	$(OBJDIR)/%.o: %.Smkdir -p $(dir $@)$(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1$(OBJDIR):mkdir -p $@clean:rm -f $(OBJDIR)/$(PROJ_NAME).elfrm -f $(OBJDIR)/$(PROJ_NAME).hexrm -f $(OBJDIR)/$(PROJ_NAME).maprm -f $(OBJDIR)/$(PROJ_NAME).vrm -f $(OBJDIR)/$(PROJ_NAME).asmfind $(OBJDIR) -type f -name '*.d' -print0 | xargs -0 -r rmfind $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm.SECONDARY: $(OBJS)

项目目录下编译: 

/blink-demo$ make
mkdir -p build/
/home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/bin/riscv-none-embed-gcc -c -march=rv32i  -mabi=ilp32  -ffunction-sections -fdata-sections -g -O3  -MD -fstrict-volatile-bitfields    -o build/main.o main.c
/home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/bin/riscv-none-embed-gcc -march=rv32i  -mabi=ilp32  -ffunction-sections -fdata-sections -g -O3  -MD -fstrict-volatile-bitfields  -o build/blink-demo.elf build/main.o build/crt_flash.o  -march=rv32i  -mabi=ilp32  -Wl,--gc-sections -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,./linker_flash.ld,-Map,build/blink-demo.map,--print-memory-usage 
Memory region         Used Size  Region Size  %age UsedFLASH:         728 B         8 MB      0.01%RAM:        1040 B         8 KB     12.70%
/home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/bin/riscv-none-embed-objcopy -O ihex build/blink-demo.elf build/blink-demo.hex
/home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/bin/riscv-none-embed-objdump -S -d build/blink-demo.elf > build/blink-demo.asm
/home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/bin/riscv-none-embed-objcopy -O verilog build/blink-demo.elf build/blink-demo.v

生成的.v文件即用于执行的文件。 

执行根目录下的make program来烧录

 烧录成功: 

...../picotiny$ make programBlink
python sw/pico-programmer.py fw/blink-demo/build/blink-demo.v /dev/ttyUSB1
Read program with 736 bytes- Waiting for reset -...
Total sectors 1
Total pages 3
Flashing 1 / 1Flashing completed

 RISCV例程执行--blink-CSDN直播

 

 2)单独编写串口交互: 

main.c: 

#include <stdint.h>
#include <stdbool.h>// a pointer to this is a null pointer, but the compiler does not
// know that because "sram" is a linker symbol from sections.lds.
extern uint32_t sram;typedef struct {volatile uint32_t DATA;volatile uint32_t CLKDIV;
} PICOUART;typedef struct {volatile uint32_t OUT;volatile uint32_t IN;volatile uint32_t OE;
} PICOGPIO;typedef struct {union {volatile uint32_t REG;volatile uint16_t IOW;struct {volatile uint8_t IO;volatile uint8_t OE;volatile uint8_t CFG;volatile uint8_t EN; };};
} PICOQSPI;#define QSPI0 ((PICOQSPI*)0x81000000)
#define GPIO0 ((PICOGPIO*)0x82000000)
#define UART0 ((PICOUART*)0x83000000)#define FLASHIO_ENTRY_ADDR ((void *)0x80000054)void (*spi_flashio)(uint8_t *pdata, int length, int wren) = FLASHIO_ENTRY_ADDR;int putchar(int c)
{	if (c == '\n')UART0->DATA = '\r';UART0->DATA = c;return c;
}void print(const char *p)
{while (*p)putchar(*(p++));
}void print_hex(uint32_t v, int digits)
{for (int i = 7; i >= 0; i--) {char c = "0123456789abcdef"[(v >> (4*i)) & 15];if (c == '0' && i >= digits) continue;putchar(c);digits = i;}
}void print_dec(uint32_t v)
{if (v >= 100) {print(">=100");return;}if      (v >= 90) { putchar('9'); v -= 90; }else if (v >= 80) { putchar('8'); v -= 80; }else if (v >= 70) { putchar('7'); v -= 70; }else if (v >= 60) { putchar('6'); v -= 60; }else if (v >= 50) { putchar('5'); v -= 50; }else if (v >= 40) { putchar('4'); v -= 40; }else if (v >= 30) { putchar('3'); v -= 30; }else if (v >= 20) { putchar('2'); v -= 20; }else if (v >= 10) { putchar('1'); v -= 10; }if      (v >= 9) { putchar('9'); v -= 9; }else if (v >= 8) { putchar('8'); v -= 8; }else if (v >= 7) { putchar('7'); v -= 7; }else if (v >= 6) { putchar('6'); v -= 6; }else if (v >= 5) { putchar('5'); v -= 5; }else if (v >= 4) { putchar('4'); v -= 4; }else if (v >= 3) { putchar('3'); v -= 3; }else if (v >= 2) { putchar('2'); v -= 2; }else if (v >= 1) { putchar('1'); v -= 1; }else putchar('0');
}char getchar_prompt(char *prompt)
{int32_t c = -1;uint32_t cycles_begin, cycles_now, cycles;__asm__ volatile ("rdcycle %0" : "=r"(cycles_begin));if (prompt)print(prompt);// if (prompt)// GPIO0->OUT = ~0;// reg_leds = ~0;while (c == -1) {__asm__ volatile ("rdcycle %0" : "=r"(cycles_now));cycles = cycles_now - cycles_begin;if (cycles > 12000000) {if (prompt)print(prompt);cycles_begin = cycles_now;// if (prompt)// GPIO0->OUT = ~GPIO0->OUT;// reg_leds = ~reg_leds;}c = UART0->DATA;}// if (prompt)// GPIO0->OUT = 0;// reg_leds = 0;return c;
}char getchar()
{return getchar_prompt(0);
}#define QSPI_REG_CRM  0x00100000
#define QSPI_REG_DSPI 0x00400000void cmd_set_crm(int on)
{if (on) {QSPI0->REG |= QSPI_REG_CRM;} else {QSPI0->REG &= ~QSPI_REG_CRM;}
}int cmd_get_crm() {return QSPI0->REG & QSPI_REG_CRM;
}volatile int i;
// --------------------------------------------------------#define CLK_FREQ        25175000
#define UART_BAUD       115200void main()
{UART0->CLKDIV = CLK_FREQ / UART_BAUD - 2;GPIO0->OE = 0x3F;GPIO0->OUT = 0x3F;cmd_set_crm(1);print("\n");print("  ____  _          ____         ____\n");print(" |  _ \\(_) ___ ___/ ___|  ___  / ___|\n");print(" | |_) | |/ __/ _ \\___ \\ / _ \\| |\n");print(" |  __/| | (_| (_) |__) | (_) | |___\n");print(" |_|   |_|\\___\\___/____/ \\___/ \\____|\n");print("\n");print("        On Lichee Tang Nano-9K\n");print("\n");for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x01;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x02;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x04;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x08;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x10;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F ^ 0x20;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x00;for ( i = 0 ; i < 10000; i++);GPIO0->OUT = 0x3F;for ( i = 0 ; i < 10000; i++);while (1){print("\n");print("Select an action:\n");print("\n");print("   [1] Toggle led 1\n");print("   [2] Toggle led 2\n");print("   [3] Toggle led 3\n");print("   [4] Toggle led 4\n");print("   [5] Toggle led 5\n");print("   [6] Toggle led 6\n");for (int rep = 10; rep > 0; rep--){print("\n");print("IO State: ");print_hex(GPIO0->IN, 8);print("\n");print("\n");print("Command> ");char cmd = getchar();if (cmd > 32 && cmd < 127)putchar(cmd);print("\n");switch (cmd){case '1':GPIO0->OUT ^= 0x00000001;break;case '2':GPIO0->OUT ^= 0x00000002;break;case '3':GPIO0->OUT ^= 0x00000004;break;case '4':GPIO0->OUT ^= 0x00000008;break;case '5':GPIO0->OUT ^= 0x00000010;break;case '6':GPIO0->OUT ^= 0x00000020;break;default:continue;}}}
}void irqCallback() {}

makefile: 

PROJ_NAME=uart-demo
DEBUG=no
BENCH=no
MULDIV=no
COMPRESSED=noSRCS = 	$(wildcard *.c)       		\$(wildcard *.S)LDSCRIPT = ./linker_flash.ldRISCV_NAME ?= riscv-none-embed
RISCV_PATH ?= /home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004MABI=ilp32
MARCH := rv32i
ifeq ($(MULDIV),yes)MARCH := $(MARCH)m
endif
ifeq ($(COMPRESSED),yes)MARCH := $(MARCH)ac
endifCFLAGS += -march=$(MARCH)  -mabi=$(MABI)  -ffunction-sections -fdata-sections
LDFLAGS += -march=$(MARCH)  -mabi=$(MABI)  -Wl,--gc-sectionsifeq ($(DEBUG),yes)CFLAGS += -g3 -O0 
endififeq ($(DEBUG),no)CFLAGS += -g -O3 
endififeq ($(BENCH),yes)CFLAGS += -fno-inline  
endifRISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/$(MARCH)/$(MABI)/RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy
RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump
RISCV_CC = $(RISCV_PATH)/bin/$(RISCV_NAME)-gccCFLAGS +=  -MD -fstrict-volatile-bitfields 
LDFLAGS +=  -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usageOBJDIR = build
OBJS := $(SRCS)
OBJS := $(OBJS:.c=.o)
OBJS := $(OBJS:.cpp=.o)
OBJS := $(OBJS:.S=.o)
OBJS := $(addprefix $(OBJDIR)/,$(OBJS))SUBOBJ := $(addprefix $(OBJDIR)/,$(SUBDIRS))
SUBOBJ := $(addsuffix /*.o,$(SUBOBJ))export RISCV_CC CFLAGS LDFLAGS OBJDIRall: $(SUBDIRS) $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).v$(SUBDIRS): ECHOmake -C $@ECHO:@echo $(SUBDIRS)$(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)$(RISCV_CC) $(CFLAGS) -o $@ $^ $(SUBOBJ) $(LDFLAGS) $(LIBS)%.hex: %.elf$(RISCV_OBJCOPY) -O ihex $^ $@%.bin: %.elf$(RISCV_OBJCOPY) -O binary $^ $@%.v: %.elf$(RISCV_OBJCOPY) -O verilog $^ $@%.asm: %.elf$(RISCV_OBJDUMP) -S -d $^ > $@$(OBJDIR)/%.o: %.cmkdir -p $(dir $@)$(RISCV_CC) -c $(CFLAGS)  $(INC) -o $@ $^$(OBJDIR)/%.o: %.cppmkdir -p $(dir $@)$(RISCV_CC) -c $(CFLAGS)  $(INC) -o $@ $^	$(OBJDIR)/%.o: %.Smkdir -p $(dir $@)$(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1$(OBJDIR):mkdir -p $@clean:rm -f $(OBJDIR)/$(PROJ_NAME).elfrm -f $(OBJDIR)/$(PROJ_NAME).hexrm -f $(OBJDIR)/$(PROJ_NAME).maprm -f $(OBJDIR)/$(PROJ_NAME).vrm -f $(OBJDIR)/$(PROJ_NAME).asmfind $(OBJDIR) -type f -name '*.d' -print0 | xargs -0 -r rmfind $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm.SECONDARY: $(OBJS)

项目子目录下编译结果,生成目标文件: 

/uart-demo$ make
mkdir -p build/
/home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/bin/riscv-none-embed-gcc -c -march=rv32i  -mabi=ilp32  -ffunction-sections -fdata-sections -g -O3  -MD -fstrict-volatile-bitfields    -o build/main.o main.c
mkdir -p build/
/home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/bin/riscv-none-embed-gcc -c -march=rv32i  -mabi=ilp32  -ffunction-sections -fdata-sections -g -O3  -MD -fstrict-volatile-bitfields  -o build/crt_flash.o crt_flash.S -D__ASSEMBLY__=1
/home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/bin/riscv-none-embed-gcc -march=rv32i  -mabi=ilp32  -ffunction-sections -fdata-sections -g -O3  -MD -fstrict-volatile-bitfields  -o build/uart-demo.elf build/main.o build/crt_flash.o  -march=rv32i  -mabi=ilp32  -Wl,--gc-sections -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,./linker_flash.ld,-Map,build/uart-demo.map,--print-memory-usage 
Memory region         Used Size  Region Size  %age UsedFLASH:        3152 B         8 MB      0.04%RAM:        1040 B         8 KB     12.70%
/home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/bin/riscv-none-embed-objcopy -O ihex build/uart-demo.elf build/uart-demo.hex
/home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/bin/riscv-none-embed-objdump -S -d build/uart-demo.elf > build/uart-demo.asm
/home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004/bin/riscv-none-embed-objcopy -O verilog build/uart-demo.elf build/uart-demo.v

根目录下烧录运行: 

makefile增加选项programUart: 


PYTHON_NAME ?= python
RISCV_NAME 	?= riscv-none-embed
RISCV_PATH 	?= /home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004
MAKE		?= makeFW_FILE_BLINK 	 = fw/blink-demo/build/blink-demo.v
FW_FILE_UART	 = fw/uart-demo/build/uart-demo.vPROG_FILE_BLINK	?= $(FW_FILE_BLINK)
PROG_FILE_UART	?= $(FW_FILE_UART)COMx	 	?= /dev/ttyUSB1export PYTHON_NAME
export RISCV_NAME
export RISCV_PATH.PHONY: all brom flash clean programall: brom flash$(FW_FILE): flashbrom:$(MAKE) -C fw/fw-bromflash:$(MAKE) -C fw/blink-democlean:$(MAKE) -C fw/fw-brom clean$(MAKE) -C fw/fw-flash cleanprogram: $(PROG_FILE)$(PYTHON_NAME) sw/pico-programmer.py $(PROG_FILE) $(COMx)programBlink: $(PROG_FILE_BLINK)$(PYTHON_NAME) sw/pico-programmer.py $(PROG_FILE_BLINK) $(COMx)	programUart: $(PROG_FILE_UART)$(PYTHON_NAME) sw/pico-programmer.py $(PROG_FILE_UART) $(COMx)		

运行烧录: 

/picotiny$ make programUart
python sw/pico-programmer.py fw/uart-demo/build/uart-demo.v /dev/ttyUSB1
Read program with 3152 bytes- Waiting for reset -..
Total sectors 1
Total pages 13
Flashing 1 / 1Flashing completed

调用cutecom运行页面: 

 

输入框输入1-6可以控制对应的LED亮灭。 

6. 后续任务

1)延申理解,通过官方开发包,编写更易于移植和开发的库

2)理解配合软核的SDK架构(理解指令集) 和HAL库的基本逻辑。 理解SDK应该按什么逻辑来规划

3)移植FREERTOS, 理解操作系统移植的基本逻辑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/23449.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年华为OD机试真题-多段线数据压缩-C++-OD统一考试(C卷D卷)

2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C++合集)​ 题目描述: 下图中,每个方块代表一个像素,每个像素用其行号和列号表示。 为简化处理,多段线的走向只能是水平、竖直、斜向45度。 上图中的多段线可以用下面的坐标串表示:(2, 8), (3…

Modbus TCP转CanOpen网关携手FANUC机器人助力新能源汽车

Modbus TCP转CanOpen网关与FANUC机器手臂的现场应用可以实现FANUC机器手臂与其他设备之间的数据交换和通信。CANopen是一种常见的网络协议&#xff0c;用于处理机器和设备之间的通信&#xff0c;并广泛应用于自动化领域。而Modbus TCP是一种基于TCP/IP协议的通信协议&#xff0…

智慧互联网医院系统开发指南:从源码到在线问诊APP

近期&#xff0c;互联网医院系统的热度非常高&#xff0c;很多人跟小编提问如何开发&#xff0c;今天小编将从零开始为大家详解互联网医院系统源码&#xff0c;以及在线问诊APP开发技术。 一、需求分析与系统设计 1.1 需求分析 用户管理 预约挂号 在线问诊 电子病历 药品…

定个小目标之每天刷LeetCode热题(11)

这是道简单题&#xff0c;只想到了暴力解法&#xff0c;就是用集合存储起来&#xff0c;然后找出其中的众数&#xff0c;看了一下题解&#xff0c;发现有多种解法&#xff0c;我觉得Boyer-Moore 投票算法是最优解&#xff0c;看了官方对这个算法的解释&#xff0c;我是这样理解…

手把手教你用Spring Boot搭建AI原生应用

作者 | 文心智能体平台 导读 本文以快速开发一个 AI 原生应用为目的&#xff0c;介绍了 Spring AI 的包括对话模型、提示词模板、Function Calling、结构化输出、图片生成、向量化、向量数据库等全部核心功能&#xff0c;并介绍了检索增强生成的技术。依赖 Spring AI 提供的功能…

进阶之格式化qDebug()输出

创作灵感 刚刚在看qt帮助手册时&#xff0c;无意间在<QtGlobal>中看见了这个函数void qSetMessagePattern(const QString &pattern)&#xff0c;该函数的精华在于&#xff0c;你可以直接重定义qDebug()的输出结果格式。以往打印调试内容&#xff0c;调试内容所在的行…

00-macOS和Linux安装和管理多个Python版本

在 Mac 上安装多个 Python 版本可通过几种不同方法实现。 1 Homebrew 1.1 安装 Homebrew 若安装过&#xff0c;跳过该步。 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 1.2 安装 Python 如安装 Python …

计算机毕业设计 | SSM 校园线上订餐系统 外卖购物网站(附源码)

1&#xff0c; 概述 1.1 项目背景 传统的外卖方式就是打电话预定&#xff0c;然而&#xff0c;在这种方式中&#xff0c;顾客往往通过餐厅散发的传单来获取餐厅的相关信息&#xff0c;通过电话来传达自己的订单信息&#xff0c;餐厅方面通过电话接受订单后&#xff0c;一般通…

纷享销客集成平台(IPaaS)解决方案

针对传统对接方式中的痛点&#xff0c;集成平台提炼了一套成熟的解决方案和配套工具。 痛点&#xff11;&#xff1a;编码工作量大。 每个功能点&#xff0c;和众多的容错分支&#xff0c;都需要逐行编码实现。日志打少了影响问题排查&#xff0c;打多了浪费大量存储。 集成…

Django里的ModelForm组件

ModelForm组件 自动生成HTML标签 自动读取关联数据表单验证 错误提示数据库进行&#xff1a;新建&#xff0c;修改 步骤如下&#xff1a; 创建类 # 在 views.py 文件里# 创建一个类 class AssetModelForm(forms.ModelForm):class Meta:model models.AssetSet #fields [n…

k8s 对外服务之 Ingress(HTTPS/HTTP 代理访问 以及Nginx 进行 BasicAuth )

目录 一 Ingress HTTP 代理访问虚拟主机 &#xff08;一&#xff09;原理 &#xff08;二&#xff09;实验 1&#xff0c;准备 2&#xff0c;创建虚拟主机1资源 3&#xff0c;创建虚拟主机2资源 4&#xff0c;创建ingress资源 5&#xff0c;查看相关参数 6&#xff0…

【文末附gpt升级秘笈】埃隆·马斯克芯片调配策略对特斯拉股价的影响分析

埃隆马斯克芯片调配策略对特斯拉股价的影响分析 一、引言 在现代商业环境中&#xff0c;企业间的资源调配与策略布局往往对其股价产生深远影响。据外媒CNBC报道&#xff0c;埃隆马斯克在芯片资源分配上的决策引起了业界的广泛关注。他秘密要求英伟达将原本预留给特斯拉的高端…

如何为律师制作专业的商务名片?含电子名片二维码

律师关注细节&#xff0c;律师名片也不例外。它们不仅仅是身份的象征&#xff0c;更是律师专业形象的代表&#xff0c;传递专业知识和信任。今天就来和我们一起来看看制作律师商务名片的注意事项&#xff0c;以及如何制作商务名片上的电子名片二维码&#xff1f; 一、名片的主…

【Text2SQL】评估 LLM 的 Text2SQL 能力

论文&#xff1a;Evaluating the Text-to-SQL Capabilities of Large Language Models ⭐⭐⭐⭐ arXiv:2204.00498 一、论文速读 本论文尝试了多种 prompt 结构&#xff0c;并且评估了他们在 Codex 和 GPT-3 上的表现。下面介绍这些 prompt 结构&#xff1a; 二、不同的 prom…

优思学院|谈汽车零部件企业生产精益及现场管理

精益生产&#xff08;Lean Production&#xff09;和现场管理作为现代制造企业的核心管理理念&#xff0c;正在越来越多的企业中得到应用。尤其是在中国&#xff0c;许多汽车零部件企业通过精益管理和六西格玛方法&#xff0c;显著提高了生产效率&#xff0c;降低了生产成本&am…

大数据之CDH对Hdfs做Balance数据均衡/数据平衡/数据倾斜

问题的来源: 由于在hive工具运行sql,出现sql卡顿的情况,去cdh上查看yarn资源的分布情况,发现了整个cdh平台中hdfs和yarn资源分布不均匀,大量的爆红显示: 以下 DataNode 数据目录 位于小于其可用空间 10.0 吉字节 的文件系统中。 /data1/dfs/dn&#xff08;可用&#xff1a;7.2 …

C++的类和new和delete和菱形继承机制

文章目录 参考虚函数使用虚函数的class结构相关实现源码IDA反编译子类虚表和父类虚表调用函数菱形继承 参考 https://showlinkroom.me/2017/08/21/C-%E9%80%86%E5%90%91%E5%88%86%E6%9E%90/ https://www.cnblogs.com/bonelee/p/17299985.html https://xz.aliyun.com/t/5242?t…

hadoop疑难问题解决_NoClassDefFoundError: org/apache/hadoop/fs/adl/AdlFileSystem

1、问题描述 impala执行查询&#xff1a;select * from stmta_raw limit 10; 报错信息如下&#xff1a; Query: select * from sfmta_raw limit 10 Query submitted at: 2018-04-11 14:46:29 (Coordinator: http://mrj001:25000) ERROR: AnalysisException: Failed to load …

Linux进程无法被kill

说明&#xff1a;记录一次应用进程无法被kill的错误&#xff1b; 场景 在一次导出MySQL数据时&#xff0c;使用下面的命令&#xff0c;将数据库数据导出为.sql文件&#xff0c;数据量大&#xff0c;导出时间长&#xff0c;于是我就将服务器重启了。 mysqldump -u username -…

springboot大学生就业管理系统-计算机毕业设计源码89344

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对大学生就业管理系统等问题&#xff0c;对大…