当前位置:   article > 正文

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

基于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, 先看主目录下的: 

  1. PYTHON_NAME ?= python
  2. RISCV_NAME ?= riscv-none-embed
  3. RISCV_PATH ?= /home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004
  4. MAKE ?= make
  5. FW_FILE = fw/fw-flash/build/fw-flash.v
  6. PROG_FILE ?= $(FW_FILE)
  7. COMx ?= COM14
  8. export PYTHON_NAME
  9. export RISCV_NAME
  10. export RISCV_PATH
  11. .PHONY: all brom flash clean program
  12. all: brom flash
  13. $(FW_FILE): flash
  14. brom:
  15. $(MAKE) -C fw/fw-brom
  16. flash:
  17. $(MAKE) -C fw/fw-flash
  18. clean:
  19. $(MAKE) -C fw/fw-brom clean
  20. $(MAKE) -C fw/fw-flash clean
  21. program: $(PROG_FILE)
  22. $(PYTHON_NAME) sw/pico-programmer.py $(PROG_FILE) $(COMx)

第一部分:指定环境变量

第二部分:指定分支

第三部分:分支命令编写

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

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

再来看子目录下的makefile

  1. PROJ_NAME=blink-flash
  2. DEBUG=no
  3. BENCH=no
  4. MULDIV=no
  5. COMPRESSED=no
  6. SRCS = $(wildcard *.c) \
  7. $(wildcard *.S)
  8. LDSCRIPT = ./linker_flash.ld
  9. RISCV_NAME ?= riscv-none-embed
  10. RISCV_PATH ?= /home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004
  11. MABI=ilp32
  12. MARCH := rv32i
  13. ifeq ($(MULDIV),yes)
  14. MARCH := $(MARCH)m
  15. endif
  16. ifeq ($(COMPRESSED),yes)
  17. MARCH := $(MARCH)ac
  18. endif
  19. CFLAGS += -march=$(MARCH) -mabi=$(MABI) -ffunction-sections -fdata-sections
  20. LDFLAGS += -march=$(MARCH) -mabi=$(MABI) -Wl,--gc-sections
  21. ifeq ($(DEBUG),yes)
  22. CFLAGS += -g3 -O0
  23. endif
  24. ifeq ($(DEBUG),no)
  25. CFLAGS += -g -O3
  26. endif
  27. ifeq ($(BENCH),yes)
  28. CFLAGS += -fno-inline
  29. endif
  30. RISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/$(MARCH)/$(MABI)/
  31. RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy
  32. RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump
  33. RISCV_CC = $(RISCV_PATH)/bin/$(RISCV_NAME)-gcc
  34. CFLAGS += -MD -fstrict-volatile-bitfields
  35. LDFLAGS += -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usage
  36. OBJDIR = build
  37. OBJS := $(SRCS)
  38. OBJS := $(OBJS:.c=.o)
  39. OBJS := $(OBJS:.cpp=.o)
  40. OBJS := $(OBJS:.S=.o)
  41. OBJS := $(addprefix $(OBJDIR)/,$(OBJS))
  42. SUBOBJ := $(addprefix $(OBJDIR)/,$(SUBDIRS))
  43. SUBOBJ := $(addsuffix /*.o,$(SUBOBJ))
  44. export RISCV_CC CFLAGS LDFLAGS OBJDIR
  45. all: $(SUBDIRS) $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).v
  46. $(SUBDIRS): ECHO
  47. make -C $@
  48. ECHO:
  49. @echo $(SUBDIRS)
  50. $(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)
  51. $(RISCV_CC) $(CFLAGS) -o $@ $^ $(SUBOBJ) $(LDFLAGS) $(LIBS)
  52. %.hex: %.elf
  53. $(RISCV_OBJCOPY) -O ihex $^ $@
  54. %.bin: %.elf
  55. $(RISCV_OBJCOPY) -O binary $^ $@
  56. %.v: %.elf
  57. $(RISCV_OBJCOPY) -O verilog $^ $@
  58. %.asm: %.elf
  59. $(RISCV_OBJDUMP) -S -d $^ > $@
  60. $(OBJDIR)/%.o: %.c
  61. mkdir -p $(dir $@)
  62. $(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
  63. $(OBJDIR)/%.o: %.cpp
  64. mkdir -p $(dir $@)
  65. $(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
  66. $(OBJDIR)/%.o: %.S
  67. mkdir -p $(dir $@)
  68. $(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1
  69. $(OBJDIR):
  70. mkdir -p $@
  71. clean:
  72. rm -f $(OBJDIR)/$(PROJ_NAME).elf
  73. rm -f $(OBJDIR)/$(PROJ_NAME).hex
  74. rm -f $(OBJDIR)/$(PROJ_NAME).map
  75. rm -f $(OBJDIR)/$(PROJ_NAME).v
  76. rm -f $(OBJDIR)/$(PROJ_NAME).asm
  77. find $(OBJDIR) -type f -name '*.d' -print0 | xargs -0 -r rm
  78. find $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm
  79. .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寄存器写入功能

  1. #include <stdint.h>
  2. #include <stdbool.h>
  3. // a pointer to this is a null pointer, but the compiler does not
  4. // know that because "sram" is a linker symbol from sections.lds.
  5. extern uint32_t sram;
  6. typedef struct {
  7. volatile uint32_t OUT;
  8. volatile uint32_t IN;
  9. volatile uint32_t OE;
  10. } PICOGPIO;
  11. // 寄存器地址
  12. #define GPIO0 ((PICOGPIO*)0x82000000)
  13. #define FLASHIO_ENTRY_ADDR ((void *)0x80000054)
  14. volatile int i;
  15. // --------------------------------------------------------
  16. void main()
  17. {
  18. GPIO0->OE = 0x3F;
  19. GPIO0->OUT = 0x3F;
  20. while (1)
  21. {
  22. for ( i = 0 ; i < 10000; i++);
  23. GPIO0->OUT = 0x3F ^ 0x01;
  24. for ( i = 0 ; i < 10000; i++);
  25. GPIO0->OUT = 0x3F ^ 0x02;
  26. for ( i = 0 ; i < 10000; i++);
  27. GPIO0->OUT = 0x3F ^ 0x04;
  28. for ( i = 0 ; i < 10000; i++);
  29. GPIO0->OUT = 0x3F ^ 0x08;
  30. for ( i = 0 ; i < 10000; i++);
  31. GPIO0->OUT = 0x3F ^ 0x10;
  32. for ( i = 0 ; i < 10000; i++);
  33. GPIO0->OUT = 0x3F ^ 0x20;
  34. for ( i = 0 ; i < 10000; i++);
  35. GPIO0->OUT = 0x3F;
  36. for ( i = 0 ; i < 10000; i++);
  37. GPIO0->OUT = 0x00;
  38. for ( i = 0 ; i < 10000; i++);
  39. GPIO0->OUT = 0x3F;
  40. for ( i = 0 ; i < 10000; i++);
  41. }
  42. }
  43. void irqCallback() {
  44. }

 makefile,其实之修改了PROJ_NAME

  1. PROJ_NAME=blink-demo
  2. DEBUG=no
  3. BENCH=no
  4. MULDIV=no
  5. COMPRESSED=no
  6. SRCS = $(wildcard *.c) \
  7. $(wildcard *.S)
  8. LDSCRIPT = ./linker_flash.ld
  9. RISCV_NAME ?= riscv-none-embed
  10. RISCV_PATH ?= /home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004
  11. MABI=ilp32
  12. MARCH := rv32i
  13. ifeq ($(MULDIV),yes)
  14. MARCH := $(MARCH)m
  15. endif
  16. ifeq ($(COMPRESSED),yes)
  17. MARCH := $(MARCH)ac
  18. endif
  19. CFLAGS += -march=$(MARCH) -mabi=$(MABI) -ffunction-sections -fdata-sections
  20. LDFLAGS += -march=$(MARCH) -mabi=$(MABI) -Wl,--gc-sections
  21. ifeq ($(DEBUG),yes)
  22. CFLAGS += -g3 -O0
  23. endif
  24. ifeq ($(DEBUG),no)
  25. CFLAGS += -g -O3
  26. endif
  27. ifeq ($(BENCH),yes)
  28. CFLAGS += -fno-inline
  29. endif
  30. RISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/$(MARCH)/$(MABI)/
  31. RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy
  32. RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump
  33. RISCV_CC = $(RISCV_PATH)/bin/$(RISCV_NAME)-gcc
  34. CFLAGS += -MD -fstrict-volatile-bitfields
  35. LDFLAGS += -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usage
  36. OBJDIR = build
  37. OBJS := $(SRCS)
  38. OBJS := $(OBJS:.c=.o)
  39. OBJS := $(OBJS:.cpp=.o)
  40. OBJS := $(OBJS:.S=.o)
  41. OBJS := $(addprefix $(OBJDIR)/,$(OBJS))
  42. SUBOBJ := $(addprefix $(OBJDIR)/,$(SUBDIRS))
  43. SUBOBJ := $(addsuffix /*.o,$(SUBOBJ))
  44. export RISCV_CC CFLAGS LDFLAGS OBJDIR
  45. all: $(SUBDIRS) $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).v
  46. $(SUBDIRS): ECHO
  47. make -C $@
  48. ECHO:
  49. @echo $(SUBDIRS)
  50. $(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)
  51. $(RISCV_CC) $(CFLAGS) -o $@ $^ $(SUBOBJ) $(LDFLAGS) $(LIBS)
  52. %.hex: %.elf
  53. $(RISCV_OBJCOPY) -O ihex $^ $@
  54. %.bin: %.elf
  55. $(RISCV_OBJCOPY) -O binary $^ $@
  56. %.v: %.elf
  57. $(RISCV_OBJCOPY) -O verilog $^ $@
  58. %.asm: %.elf
  59. $(RISCV_OBJDUMP) -S -d $^ > $@
  60. $(OBJDIR)/%.o: %.c
  61. mkdir -p $(dir $@)
  62. $(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
  63. $(OBJDIR)/%.o: %.cpp
  64. mkdir -p $(dir $@)
  65. $(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
  66. $(OBJDIR)/%.o: %.S
  67. mkdir -p $(dir $@)
  68. $(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1
  69. $(OBJDIR):
  70. mkdir -p $@
  71. clean:
  72. rm -f $(OBJDIR)/$(PROJ_NAME).elf
  73. rm -f $(OBJDIR)/$(PROJ_NAME).hex
  74. rm -f $(OBJDIR)/$(PROJ_NAME).map
  75. rm -f $(OBJDIR)/$(PROJ_NAME).v
  76. rm -f $(OBJDIR)/$(PROJ_NAME).asm
  77. find $(OBJDIR) -type f -name '*.d' -print0 | xargs -0 -r rm
  78. find $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm
  79. .SECONDARY: $(OBJS)

项目目录下编译: 

  1. /blink-demo$ make
  2. mkdir -p build/
  3. /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
  4. /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
  5. Memory region Used Size Region Size %age Used
  6. FLASH: 728 B 8 MB 0.01%
  7. RAM: 1040 B 8 KB 12.70%
  8. /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
  9. /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
  10. /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来烧录

 烧录成功: 

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

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

 

 2)单独编写串口交互: 

main.c: 

  1. #include <stdint.h>
  2. #include <stdbool.h>
  3. // a pointer to this is a null pointer, but the compiler does not
  4. // know that because "sram" is a linker symbol from sections.lds.
  5. extern uint32_t sram;
  6. typedef struct {
  7. volatile uint32_t DATA;
  8. volatile uint32_t CLKDIV;
  9. } PICOUART;
  10. typedef struct {
  11. volatile uint32_t OUT;
  12. volatile uint32_t IN;
  13. volatile uint32_t OE;
  14. } PICOGPIO;
  15. typedef struct {
  16. union {
  17. volatile uint32_t REG;
  18. volatile uint16_t IOW;
  19. struct {
  20. volatile uint8_t IO;
  21. volatile uint8_t OE;
  22. volatile uint8_t CFG;
  23. volatile uint8_t EN;
  24. };
  25. };
  26. } PICOQSPI;
  27. #define QSPI0 ((PICOQSPI*)0x81000000)
  28. #define GPIO0 ((PICOGPIO*)0x82000000)
  29. #define UART0 ((PICOUART*)0x83000000)
  30. #define FLASHIO_ENTRY_ADDR ((void *)0x80000054)
  31. void (*spi_flashio)(uint8_t *pdata, int length, int wren) = FLASHIO_ENTRY_ADDR;
  32. int putchar(int c)
  33. {
  34. if (c == '\n')
  35. UART0->DATA = '\r';
  36. UART0->DATA = c;
  37. return c;
  38. }
  39. void print(const char *p)
  40. {
  41. while (*p)
  42. putchar(*(p++));
  43. }
  44. void print_hex(uint32_t v, int digits)
  45. {
  46. for (int i = 7; i >= 0; i--) {
  47. char c = "0123456789abcdef"[(v >> (4*i)) & 15];
  48. if (c == '0' && i >= digits) continue;
  49. putchar(c);
  50. digits = i;
  51. }
  52. }
  53. void print_dec(uint32_t v)
  54. {
  55. if (v >= 100) {
  56. print(">=100");
  57. return;
  58. }
  59. if (v >= 90) { putchar('9'); v -= 90; }
  60. else if (v >= 80) { putchar('8'); v -= 80; }
  61. else if (v >= 70) { putchar('7'); v -= 70; }
  62. else if (v >= 60) { putchar('6'); v -= 60; }
  63. else if (v >= 50) { putchar('5'); v -= 50; }
  64. else if (v >= 40) { putchar('4'); v -= 40; }
  65. else if (v >= 30) { putchar('3'); v -= 30; }
  66. else if (v >= 20) { putchar('2'); v -= 20; }
  67. else if (v >= 10) { putchar('1'); v -= 10; }
  68. if (v >= 9) { putchar('9'); v -= 9; }
  69. else if (v >= 8) { putchar('8'); v -= 8; }
  70. else if (v >= 7) { putchar('7'); v -= 7; }
  71. else if (v >= 6) { putchar('6'); v -= 6; }
  72. else if (v >= 5) { putchar('5'); v -= 5; }
  73. else if (v >= 4) { putchar('4'); v -= 4; }
  74. else if (v >= 3) { putchar('3'); v -= 3; }
  75. else if (v >= 2) { putchar('2'); v -= 2; }
  76. else if (v >= 1) { putchar('1'); v -= 1; }
  77. else putchar('0');
  78. }
  79. char getchar_prompt(char *prompt)
  80. {
  81. int32_t c = -1;
  82. uint32_t cycles_begin, cycles_now, cycles;
  83. __asm__ volatile ("rdcycle %0" : "=r"(cycles_begin));
  84. if (prompt)
  85. print(prompt);
  86. // if (prompt)
  87. // GPIO0->OUT = ~0;
  88. // reg_leds = ~0;
  89. while (c == -1) {
  90. __asm__ volatile ("rdcycle %0" : "=r"(cycles_now));
  91. cycles = cycles_now - cycles_begin;
  92. if (cycles > 12000000) {
  93. if (prompt)
  94. print(prompt);
  95. cycles_begin = cycles_now;
  96. // if (prompt)
  97. // GPIO0->OUT = ~GPIO0->OUT;
  98. // reg_leds = ~reg_leds;
  99. }
  100. c = UART0->DATA;
  101. }
  102. // if (prompt)
  103. // GPIO0->OUT = 0;
  104. // reg_leds = 0;
  105. return c;
  106. }
  107. char getchar()
  108. {
  109. return getchar_prompt(0);
  110. }
  111. #define QSPI_REG_CRM 0x00100000
  112. #define QSPI_REG_DSPI 0x00400000
  113. void cmd_set_crm(int on)
  114. {
  115. if (on) {
  116. QSPI0->REG |= QSPI_REG_CRM;
  117. } else {
  118. QSPI0->REG &= ~QSPI_REG_CRM;
  119. }
  120. }
  121. int cmd_get_crm() {
  122. return QSPI0->REG & QSPI_REG_CRM;
  123. }
  124. volatile int i;
  125. // --------------------------------------------------------
  126. #define CLK_FREQ 25175000
  127. #define UART_BAUD 115200
  128. void main()
  129. {
  130. UART0->CLKDIV = CLK_FREQ / UART_BAUD - 2;
  131. GPIO0->OE = 0x3F;
  132. GPIO0->OUT = 0x3F;
  133. cmd_set_crm(1);
  134. print("\n");
  135. print(" ____ _ ____ ____\n");
  136. print(" | _ \\(_) ___ ___/ ___| ___ / ___|\n");
  137. print(" | |_) | |/ __/ _ \\___ \\ / _ \\| |\n");
  138. print(" | __/| | (_| (_) |__) | (_) | |___\n");
  139. print(" |_| |_|\\___\\___/____/ \\___/ \\____|\n");
  140. print("\n");
  141. print(" On Lichee Tang Nano-9K\n");
  142. print("\n");
  143. for ( i = 0 ; i < 10000; i++);
  144. GPIO0->OUT = 0x3F ^ 0x01;
  145. for ( i = 0 ; i < 10000; i++);
  146. GPIO0->OUT = 0x3F ^ 0x02;
  147. for ( i = 0 ; i < 10000; i++);
  148. GPIO0->OUT = 0x3F ^ 0x04;
  149. for ( i = 0 ; i < 10000; i++);
  150. GPIO0->OUT = 0x3F ^ 0x08;
  151. for ( i = 0 ; i < 10000; i++);
  152. GPIO0->OUT = 0x3F ^ 0x10;
  153. for ( i = 0 ; i < 10000; i++);
  154. GPIO0->OUT = 0x3F ^ 0x20;
  155. for ( i = 0 ; i < 10000; i++);
  156. GPIO0->OUT = 0x3F;
  157. for ( i = 0 ; i < 10000; i++);
  158. GPIO0->OUT = 0x00;
  159. for ( i = 0 ; i < 10000; i++);
  160. GPIO0->OUT = 0x3F;
  161. for ( i = 0 ; i < 10000; i++);
  162. while (1)
  163. {
  164. print("\n");
  165. print("Select an action:\n");
  166. print("\n");
  167. print(" [1] Toggle led 1\n");
  168. print(" [2] Toggle led 2\n");
  169. print(" [3] Toggle led 3\n");
  170. print(" [4] Toggle led 4\n");
  171. print(" [5] Toggle led 5\n");
  172. print(" [6] Toggle led 6\n");
  173. for (int rep = 10; rep > 0; rep--)
  174. {
  175. print("\n");
  176. print("IO State: ");
  177. print_hex(GPIO0->IN, 8);
  178. print("\n");
  179. print("\n");
  180. print("Command> ");
  181. char cmd = getchar();
  182. if (cmd > 32 && cmd < 127)
  183. putchar(cmd);
  184. print("\n");
  185. switch (cmd)
  186. {
  187. case '1':
  188. GPIO0->OUT ^= 0x00000001;
  189. break;
  190. case '2':
  191. GPIO0->OUT ^= 0x00000002;
  192. break;
  193. case '3':
  194. GPIO0->OUT ^= 0x00000004;
  195. break;
  196. case '4':
  197. GPIO0->OUT ^= 0x00000008;
  198. break;
  199. case '5':
  200. GPIO0->OUT ^= 0x00000010;
  201. break;
  202. case '6':
  203. GPIO0->OUT ^= 0x00000020;
  204. break;
  205. default:
  206. continue;
  207. }
  208. }
  209. }
  210. }
  211. void irqCallback() {
  212. }

makefile: 

  1. PROJ_NAME=uart-demo
  2. DEBUG=no
  3. BENCH=no
  4. MULDIV=no
  5. COMPRESSED=no
  6. SRCS = $(wildcard *.c) \
  7. $(wildcard *.S)
  8. LDSCRIPT = ./linker_flash.ld
  9. RISCV_NAME ?= riscv-none-embed
  10. RISCV_PATH ?= /home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004
  11. MABI=ilp32
  12. MARCH := rv32i
  13. ifeq ($(MULDIV),yes)
  14. MARCH := $(MARCH)m
  15. endif
  16. ifeq ($(COMPRESSED),yes)
  17. MARCH := $(MARCH)ac
  18. endif
  19. CFLAGS += -march=$(MARCH) -mabi=$(MABI) -ffunction-sections -fdata-sections
  20. LDFLAGS += -march=$(MARCH) -mabi=$(MABI) -Wl,--gc-sections
  21. ifeq ($(DEBUG),yes)
  22. CFLAGS += -g3 -O0
  23. endif
  24. ifeq ($(DEBUG),no)
  25. CFLAGS += -g -O3
  26. endif
  27. ifeq ($(BENCH),yes)
  28. CFLAGS += -fno-inline
  29. endif
  30. RISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/$(MARCH)/$(MABI)/
  31. RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy
  32. RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump
  33. RISCV_CC = $(RISCV_PATH)/bin/$(RISCV_NAME)-gcc
  34. CFLAGS += -MD -fstrict-volatile-bitfields
  35. LDFLAGS += -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usage
  36. OBJDIR = build
  37. OBJS := $(SRCS)
  38. OBJS := $(OBJS:.c=.o)
  39. OBJS := $(OBJS:.cpp=.o)
  40. OBJS := $(OBJS:.S=.o)
  41. OBJS := $(addprefix $(OBJDIR)/,$(OBJS))
  42. SUBOBJ := $(addprefix $(OBJDIR)/,$(SUBDIRS))
  43. SUBOBJ := $(addsuffix /*.o,$(SUBOBJ))
  44. export RISCV_CC CFLAGS LDFLAGS OBJDIR
  45. all: $(SUBDIRS) $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).v
  46. $(SUBDIRS): ECHO
  47. make -C $@
  48. ECHO:
  49. @echo $(SUBDIRS)
  50. $(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)
  51. $(RISCV_CC) $(CFLAGS) -o $@ $^ $(SUBOBJ) $(LDFLAGS) $(LIBS)
  52. %.hex: %.elf
  53. $(RISCV_OBJCOPY) -O ihex $^ $@
  54. %.bin: %.elf
  55. $(RISCV_OBJCOPY) -O binary $^ $@
  56. %.v: %.elf
  57. $(RISCV_OBJCOPY) -O verilog $^ $@
  58. %.asm: %.elf
  59. $(RISCV_OBJDUMP) -S -d $^ > $@
  60. $(OBJDIR)/%.o: %.c
  61. mkdir -p $(dir $@)
  62. $(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
  63. $(OBJDIR)/%.o: %.cpp
  64. mkdir -p $(dir $@)
  65. $(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
  66. $(OBJDIR)/%.o: %.S
  67. mkdir -p $(dir $@)
  68. $(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1
  69. $(OBJDIR):
  70. mkdir -p $@
  71. clean:
  72. rm -f $(OBJDIR)/$(PROJ_NAME).elf
  73. rm -f $(OBJDIR)/$(PROJ_NAME).hex
  74. rm -f $(OBJDIR)/$(PROJ_NAME).map
  75. rm -f $(OBJDIR)/$(PROJ_NAME).v
  76. rm -f $(OBJDIR)/$(PROJ_NAME).asm
  77. find $(OBJDIR) -type f -name '*.d' -print0 | xargs -0 -r rm
  78. find $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm
  79. .SECONDARY: $(OBJS)

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

  1. /uart-demo$ make
  2. mkdir -p build/
  3. /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
  4. mkdir -p build/
  5. /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
  6. /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
  7. Memory region Used Size Region Size %age Used
  8. FLASH: 3152 B 8 MB 0.04%
  9. RAM: 1040 B 8 KB 12.70%
  10. /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
  11. /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
  12. /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: 

  1. PYTHON_NAME ?= python
  2. RISCV_NAME ?= riscv-none-embed
  3. RISCV_PATH ?= /home/hy/riscv/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.2-20190521-0004
  4. MAKE ?= make
  5. FW_FILE_BLINK = fw/blink-demo/build/blink-demo.v
  6. FW_FILE_UART = fw/uart-demo/build/uart-demo.v
  7. PROG_FILE_BLINK ?= $(FW_FILE_BLINK)
  8. PROG_FILE_UART ?= $(FW_FILE_UART)
  9. COMx ?= /dev/ttyUSB1
  10. export PYTHON_NAME
  11. export RISCV_NAME
  12. export RISCV_PATH
  13. .PHONY: all brom flash clean program
  14. all: brom flash
  15. $(FW_FILE): flash
  16. brom:
  17. $(MAKE) -C fw/fw-brom
  18. flash:
  19. $(MAKE) -C fw/blink-demo
  20. clean:
  21. $(MAKE) -C fw/fw-brom clean
  22. $(MAKE) -C fw/fw-flash clean
  23. program: $(PROG_FILE)
  24. $(PYTHON_NAME) sw/pico-programmer.py $(PROG_FILE) $(COMx)
  25. programBlink: $(PROG_FILE_BLINK)
  26. $(PYTHON_NAME) sw/pico-programmer.py $(PROG_FILE_BLINK) $(COMx)
  27. programUart: $(PROG_FILE_UART)
  28. $(PYTHON_NAME) sw/pico-programmer.py $(PROG_FILE_UART) $(COMx)

运行烧录: 

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

调用cutecom运行页面: 

 

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

6. 后续任务

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/651083
推荐阅读
相关标签
  

闽ICP备14008679号