拿到一个新的芯片之后做的事

林爱琦 / 2023-08-16 / 原文

一、首先,看半导体厂商是否有对应的开发板,有的话就直接用厂商的,I.MX6ULL是有的,没有的话就要看芯片手册自己画PCB制作。

二、看芯片手册注意上电时序、串口 1 RXD 上拉、 启动方式。

三、1、尝试点灯,看芯片手册,看引脚寄存器的地址、功能,参照STM32的程序设计此芯片的程序。使能时钟、设置复用功能、哪个引脚、模式(上下拉、速度等)、输入输出、高低电平。

2、使用汇编语言进行编写,注意GNU汇编与intel汇编的区别,直接对芯片的地址进行操作

1 ldr r0, =0X020C4068 
2 ldr r1, =0XFFFFFFFF
3 str r1, [r0]

使用交叉编译器arm-linux-gnueabihf-gcc,可能由于版本不一而不好用,尝试降低版本。

只编译但是不链接

1 arm-linux-gnueabihf-gcc -g -c led.s -o led.o

链接.o文件

2 arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf

格式转换为二进制

3 arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin

进行反汇编来查看其汇编代码来调试代码

4 arm-linux-gnueabihf-objdump -D led.elf > led.dis

也可直接使用Makefile,要注意使用Tab,不使用空格

1 led.bin:led.s
2     arm-linux-gnueabihf-gcc -g -c led.s -o led.o
3     arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
4     arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
5     arm-linux-gnueabihf-objdump -D led.elf > led.dis
6 clean:
7     rm -rf *.o led.bin led.elf led.dis

要注意第三行的链接地址的选择。这个链接地址是在DDR中

通过烧写工具将led.bin文件烧写进SD卡中,也可以其他方式,主要看选择的启动方式是怎样的。


 

四、以上是用汇编语言写的代码,我们大多数用C语言写,需要用汇编语言搭一个环境,就是SP指针

 1 .global _start /* 全局标号 */
 2 
 3 /*
 4 * 描述: _start 函数,程序从此函数开始执行,此函数主要功能是设置 C
 5 * 运行环境。
 6 */
 7 _start:
 8 /* 进入 SVC 模式 */
 9     mrs r0, cpsr
10     bic r0, r0, #0x1f /* 将 r0 的低 5 位清零,也就是 cpsr 的 M0~M4 */
11     orr r0, r0, #0x13 /* r0 或上 0x13,表示使用 SVC 模式 */
12     msr cpsr, r0 /* 将 r0 的数据写入到 cpsr_c 中 */
13 
14     ldr sp, =0X80200000 /* 设置栈指针 */
15     b main /* 跳转到 main 函数 */

main.h以宏定义的形式定义寄存器,

1 #define SW_MUX_GPIO1_IO03 *((volatile unsigned int *)0X020E0068)

main.c定义函数进行应用。

1 SW_MUX_GPIO1_IO03 = 0x5;

对以上的Makefile和链接进行升级

 1 objs := start.o main.o
 2 
 3 ledc.bin:$(objs)
 4     arm-linux-gnueabihf-ld -Timx6ul.lds -o ledc.elf $^
 5     arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
 6     arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
 7 
 8 %.o:%.s
 9     arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
10 
11 %.o:%.S
12     arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
13 
14 %.o:%.c
15     arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
16 
17 clean:
18     rm -rf *.o ledc.bin ledc.elf ledc.dis

在Makefile同目录下新建一个名为“imx6ul.lds”的文件,此为链接脚本。

 1 SECTIONS{
 2     . = 0X87800000;
 3     .text :
 4     {
 5         start.o
 6         main.o
 7         *(.text)
 8      }
 9     .rodata ALIGN(4) : {*(.rodata*)}
10     .data ALIGN(4) : { *(.data) }
11     __bss_start = .;
12     .bss ALIGN(4) : { *(.bss) *(COMMON) }
13     __bss_end = .;
14 }                    

五、如果半导体厂商提供SDK包,可以改一改,增删文件进行使用,如果没有,就要自己写SDK包。

六、由于文件个数比较多,要对程序进行分功能管理,使其美观、功能模块清晰、易于阅读。BSP(board support package)板级支持包。

七、编译和链接终极模板:

1、编译

 1 CROSS_COMPILE ?= arm-linux-gnueabihf-    #编译器名
 2 TARGET ?= bsp                            #文件名或者例程名,注意更改
 3 
 4 CC := $(CROSS_COMPILE)gcc
 5 LD := $(CROSS_COMPILE)ld
 6 OBJCOPY := $(CROSS_COMPILE)objcopy
 7 OBJDUMP := $(CROSS_COMPILE)objdump
 8 
 9 INCDIRS := imx6ul \                    #头文件目录,添加新的
10            bsp/clk \
11            bsp/led \
12            bsp/delay
13 
14 SRCDIRS := project \                   #.c或.s目录,添加新的
15            bsp/clk \
16            bsp/led \
17            bsp/delay
18 
19 INCLUDE := $(patsubst %, -I %, $(INCDIRS))
20 SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
21 CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
22 
23 SFILENDIR := $(notdir $(SFILES))
24 CFILENDIR := $(notdir $(CFILES))
25 
26 SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
27 COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))
28 OBJS := $(SOBJS) $(COBJS)
29 
30 VPATH := $(SRCDIRS)
31 
32 .PHONY: clean
33 
34 $(TARGET).bin : $(OBJS)
35     $(LD) -Timx6ul.lds -o $(TARGET).elf $^
36     $(OBJCOPY) -O binary -S $(TARGET).elf $@
37     $(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis
38 
39     $(SOBJS) : obj/%.o : %.S
40     $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<
41 
42 $(COBJS) : obj/%.o : %.c
43     $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<
44 clean:
45     rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)    

2、链接

 1 SECTIONS{
 2 . = 0X87800000;
 3 .text :
 4  {
 5      obj/start.o             
 6      *(.text)
 7  }
 8 .rodata ALIGN(4) : {*(.rodata*)}
 9 .data ALIGN(4) : { *(.data) }
10 __bss_start = .;
11 .bss ALIGN(4) : { *(.bss) *(COMMON) }
12 __bss_end = .;
13 }