iTop-4412 裸机程序(五)- 调用C语言程序


源码

GitHub:https://github.com/Kilento/4412NoOS

预备知识

学习本篇博客,需要以下的一些预备知识:

  1. ARM 的七种工作模式
  2. ARM 的 37 个 寄存器
  3. ATPCS(ARM-Thumb Procedure Call Standard, ARM-Thumb 过程调用标准)

设置C语言运行时环境

系统在复位时默认处于 ARM 七种工作模式 SVC(Supervisor,监管)模式。这个时候只需要将 sp 寄存器设置到合适的位置即可。ATPCS 规定 ARM 的栈为满减栈。所以我们在 SRAM 中找到一个合适的内存地址。由数据手册可知,Exynos4412 的 SRAM 的 内存地址是 0x0202000 ~ 0x02060000 共 256K。由于手册中并未明确说明 SVC 的 推荐地址。我大致测试了下 0x02027400 ~ 0x0205EEE0 都可以使用(比0x02027400小就不建议使用了,比 0x0205EEE0大试了下也不行)。我这里推荐使用 0x0205000。

设置 SVC 模式下 sp 寄存器地址很简单

ldr sp, = 0x02050000

在这之后就可以调用 C 函数了

bl <C_FUNC>

start.S

#include "s3c4412_gpio.h"

#define POW_MNG_UNIT_BASE 0x10020000 
#define PS_HOLD_CONTROL (POW_MNG_UNIT_BASE + 0x330C)

/* 占位符 4字共16字节,预留用来加 bl1 校验头,填充什么数据无所谓 */
.word 0x0
.word 0x0
.word 0x0
.word 0x0

_start:
	
	/* 将 PS_HOLD_CONTRO 置为输出模式且使能。如果不设置在设备冷启动时程序运行一遍后就停止,重新按复位才会重新运行程序。详细原因后面再介绍 */
	ldr r0, =PS_HOLD_CONTROL
	ldr r1, [r0]
	#orr r1, r1, #0x300
	ldr r1, =0x0300
	str r1, [r0]

	/* 将 GPX0PUD Disable上下拉模式,如果不设置发现程序每隔几秒重新运行。这里原理还没理解,知道后再补充 */
	ldr r0, =GPX0PUD
	ldr r1, =0x0
	str r1, [r0]

    ldr sp, =0x02050000
	
	bl led_blink
	
b .

led.c

#define  	GPL2CON     (*(volatile unsigned long *) 0x11000100)
#define		GPL2DAT     (*(volatile unsigned long *) 0x11000104)

#define 	GPK1CON 	(*(volatile unsigned long *) 0x11000060)
#define 	GPK1DAT		(*(volatile unsigned long *) 0x11000064)

void delay(int r0)
{
    volatile int count = r0;
    while (count--)
        ;
}

void led_blink(void)
{
	GPL2CON = 0x00000001;
	GPK1CON = 0x00000010;

	while(1)
	{
		GPL2DAT = 0b00000001;
		GPK1DAT = 0b00000000;
		delay(0x80000);
		GPL2DAT = 0b00000000;
		GPK1DAT = 0b00000010;
		delay(0x80000);
	}	
}

C 可以使用指针来表示寄存器地址,使用宏定义就可以很方便地表示一个寄存器的地址,同时 volatile 关键字的作用就是告诉编译器不要因优化而省略此指令,必须每次都直接读写其值,这样就能确保每次读或者写寄存器都可以真正执行。

Makefile 修改

由于增加了一个文件,在编译的时候必须把 led.c 编译进去,修改 Makefile 如下

$(TARGET) : start.o led.o
CFLAGS := -nostdlib -O0
TARGET := led.bin
LOCATION := /dev/sdb 
CROSS_COMPILE := arm-none-linux-gnueabi-
Q := @
$(TARGET) : start.o led.o
	$(Q)$(CROSS_COMPILE)ld -T link.lds -o led.elf $^
	$(Q)$(CROSS_COMPILE)objcopy -O binary led.elf $@
	$(Q)$(CROSS_COMPILE)objdump -D led.elf > led.dis

%.o : %.S
	$(Q)$(CROSS_COMPILE)gcc -o $@ $< -c

%.o : %.c
	$(Q)$(CROSS_COMPILE)gcc $(CFLAGS) -o $@ $< -c

.PHONY:clean install
clean:
	rm -rf *.o *.elf *.bin *.dis mkbl1

install:
	$(Q)gcc ./mkbl1.c -static -o mkbl1
	$(Q)./mkbl1 $(TARGET) 
	$(Q)if [ -b $(LOCATION) ]; then \
	#sudo mkfs.vfat -F 32 -I $(LOCATION); \
	dd if=/dev/zero of=$(LOCATION) bs=512 seek=1 iflag=dsync oflag=dsync count=16; \
	dd if=./$(TARGET) of=$(LOCATION) bs=512 seek=1 iflag=dsync oflag=dsync; \
	fi

2021年8月29日

Kilento

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值