您尚未登录。

楼主 # 2022-12-28 22:43:58

ifree64
会员
注册时间: 2019-06-27
已发帖子: 74
积分: 143.5

F1C100s最简单裸机点灯

论坛上分享了很多F1C100s的裸机工程,但基本都是包含了这样那样RTOS系统的代码,对我这样的小白来说,感觉很复杂,缺少一个简单的裸机程序,帮助初学者入门。经过几天研究,成功的用最简单代码完成了裸机点灯,现在把笔记分享一下,高手请飘过。

## 开发环境搭建

在ubuntu下搭建开发环境很简单,只需要安装交叉编译工具链和sunxi-tools

### 1. 安装交叉编译工具链

$ sudo apt install gcc-arm-none-eabi

### 2. 安装sunxi-tools

克隆sunxi-tools仓库,签出f1c100s-spiflash分支

$ git clone https://github.com/Icenowy/sunxi-tools.git
$ git checkout f1c100s-spiflash
$ sudo make sunxi-fel && sudo make install 

安装好以后,将nano的SPI Flash CS接地,进入FEL模式

$ sudo sunxi-fel ver
AWUSBFEX soc=00001663(F1C100s) 00000001 ver=0001 44 08 scratchpad=00007e00 00000000 00000000

烧录裸机程序

$ sudo sunxi-fel -p spiflash-write 0 blinkled.bin


编写裸机点亮LED程序



1. 启动代码 start.s

.text
	.arm

	.global	_start
_start:
	/* Boot head information for BROM */
	.long 0xea000006
	.byte 'e', 'G', 'O', 'N', '.', 'B', 'T', '0'
	.long 0, __bootloader_size
	.byte 'S', 'P', 'L', 2
	.long 0, 0

_reset:
	/* Initialize stacks. Interrupts disabled */
	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr r0, r0, #0xdb
	msr cpsr, r0
	ldr sp, _stack_und_end

	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr r0, r0, #0xd7
	msr cpsr, r0
	ldr sp, _stack_abt_end

	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr r0, r0, #0xd2
	msr cpsr, r0
	ldr sp, _stack_irq_end

	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr r0, r0, #0xd1
	msr cpsr, r0
	ldr sp, _stack_fiq_end

	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr r0, r0, #0xdf
	msr cpsr, r0
	ldr sp, _stack_sys_end

	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr r0, r0, #0xd3
	msr cpsr, r0
	ldr sp, _stack_srv_end

	/* Set vector to the low address */
//	mrc p15, 0, r0, c1, c0, 0
//	bic r0, #0x20000
//	mcr p15, 0, r0, c1, c0, 0

//
	/* Call main */
	ldr r1, =main
	mov pc, r1

/*
 * The location of section
 */
 	.align 4
_stack_und_end:
	.long 0x00006C00
_stack_abt_end:
	.long 0x00007000
_stack_irq_end:
	.long 0x00007400
_stack_fiq_end:
	.long 0x00007800
_stack_sys_end:
	.long 0x00008000
_stack_srv_end:
	.long 0x00007C00

这段程序包括这样几个方面的内容:

1. Boot head information for BROM

   SPL代码必须按照BROM要求的格式,提供文件头信息,包含特定的信息,否则BROM会认为代码不是有效的SPL引导程序,将不加载。

   __bootloader_size是由连接脚本计算出来的代码尺寸。

2. 堆栈初始化

	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr r0, r0, #0xd3
	msr cpsr, r0
	ldr sp, _stack_srv_end

类似这样的代码,是设置arm处理器各种模式的堆栈指针。_stack_srv_end是定义在文件末尾的。

3. 跳转到main程序

### 2. main程序

由于仅仅是让LED闪烁,所以程序没有对时钟、存储器等进行初始化,只是操作了GPIOA的寄存器,实现设置引脚状态。代码如下

#define PORTA_CFG0_REG        ((volatile unsigned int *)(0x01C20800))
#define PORTA_DATA_REG        ((volatile unsigned int *)(0x01C20810))

void port_a_init(void)
{
  //Setup all port A pint for output
  *PORT_A_CFG_REG = (*PORT_A_CFG_REG & 0xFFFF0000) | 0x00001111;
}

void port_a_output(unsigned char data)
{
  *PORTA_DATA_REG = (*PORTA_DATA_REG & 0xFFFFFFF0) | (data & 0x0000000F);
}

int main(void)
{
	int i;
	port_a_init();
	for(i=0;i<10000;i++);
	while(1)
	{
		port_a_output(0x00);
		for(i=0;i<10000;i++);
		port_a_output(0x0F);
		for(i=0;i<10000;i++);
	}
}

* PORTA_CFG0_REG寄存器设置引脚的工作模式
* PORTA_DATA_REG设置引脚的值

### 3. 链接脚本

MEMORY
{
	ram  : org = 0x000000000, len = 32K
}

SECTIONS
{
  . = ORIGIN(ram);
  .text : 
  {
    start.o (.text)
    *(.text);
  } >ram

	__bootloader_size = SIZEOF(.text);
}

由于程序非常简单,小巧,链接脚本仅仅是指出将代码定位到0x0000_0000的SRAM位置,将start.o放置到程序的开始的位置。

### 4. Makefile

# Object Files
OBJECTFILES= \
	blinkled.o \
	start.o

AS=arm-none-eabi-gcc
CC=arm-none-eabi-gcc
RM=rm

# C Compiler Flags
CFLAGS=-Wall -Wno-write-strings -Wno-char-subscripts -fno-stack-protector -DNO_STDLIB=1 -mcpu='arm926ej-s' -O0

# CC Compiler Flags
CCFLAGS=
CXXFLAGS=

# Assembler Flags
ASFLAGS=-x assembler-with-cpp -c -O0 -mcpu='arm926ej-s' -mthumb -Wall -fmessage-length=0

# Link Libraries and Options
LDLIBSOPTIONS=

all: blinkled.elf
	arm-none-eabi-objcopy -O binary blinkled.elf blinkled.bin
	./mksunxi blinkled.bin

blinkled.elf: ${OBJECTFILES}
	$(CC) -o blinkled.elf  ${OBJECTFILES} ${LDLIBSOPTIONS} -T./blinkled.ld -nostdlib

blinkled.o: blinkled.c
	${RM} "$@.d"
	$(CC) $(CFLAGS) -c -g -MMD -MP -MF "$@.d" -o blinkled.o blinkled.c

start.o: start.S
	$(AS) $(ASFLAGS) -g -o start.o start.S

Makefile写的也是最笨的方法,需要注意的是在编译.c文件时,需要指定不连接标准库。

程序生成完以后,需要使用mksunxi这个工具处理得到的bin文件,使得它成为一个“合法”的启动代码。

剩下的就是下载到开发板,就可以观察到LED在欢快的闪烁了。



## 简要说明下程序的加载过程

1. 芯片上电,运行片内固化的BROM
2. BROM在SD卡、SPI Nor Flash搜索“合法”的SPL
3. BROM将SPL加载到片内0000_0000开始的SRAM中(32K)
4. 跳转到SPL开始执行

离线

#1 2023-01-16 10:18:17

lzw
会员
注册时间: 2022-07-31
已发帖子: 20
积分: -7

Re: F1C100s最简单裸机点灯

直接写到寄存器里面

离线

#2 2023-02-01 17:27:17

宁.
会员
注册时间: 2022-03-13
已发帖子: 7
积分: 2

Re: F1C100s最简单裸机点灯

请问mksunxi去哪下载呀?

离线

#4 2023-05-28 10:10:14

2689616493
会员
注册时间: 2023-05-28
已发帖子: 1
积分: 1

Re: F1C100s最简单裸机点灯

sfd@ubuntu:~/桌面$ sudo make sunxi-fel && sudo make install
make: *** 没有规则可制作目标“sunxi-fel”。 停止。


这个怎么弄啊,大佬

离线

#6 2024-07-09 10:40:30

村民
会员
注册时间: 2019-03-06
已发帖子: 42
积分: 12

Re: F1C100s最简单裸机点灯

2689616493 说:

sfd@ubuntu:~/桌面$

$号前的"桌面"是什么鬼?源码放到A目录,你去B目录make吗?

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn