ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

S3C2440逻辑程序--从点灯开始

2021-07-21 21:58:18  阅读:289  来源: 互联网

标签:led ldr -- 逻辑程序 elf int linux S3C2440 arm


前言

有了2440开发板环境搭建基于韦东山S3C2440开发板搭建arm-linux-gcc交叉编译环境基础,环境已经搭起来了,可以做些逻辑试验了,最经典的是点灯、按键、定时器、中断程序。

那就从点灯开始,我们的重点是linux嵌入式开发,逻辑程序只是热身用的,不要花太多时间。

实验1 汇编点灯

实验内容:点开发板上的LED1。

硬件原理图:

 

S3C2440芯片手册:

配置GPF4为输出模式(GPFCON),设置输出电平为0(GPFDAT).

 

 

汇编文件

/*
 * 点亮LED1: gpf4
 */

.text
.global _start

_start:

/* 配置GPF4为输出引脚
 * 把0x100写到地址0x56000050
 */
	ldr r1, =0x56000050
	ldr r0, =0x100	/* mov r0, #0x100 */
	str r0, [r1]


/* 设置GPF4输出高电平 
 * 把0写到地址0x56000054
 */
	ldr r1, =0x56000054
	ldr r0, =0	/* mov r0, #0 */
	str r0, [r1]

	/* 死循环 */
halt:
	b halt
记录:
ldr A, B //A = B
str A, B //B = A

Makefiel文件

all:
	arm-linux-gcc -c -o led_on.o led_on.S
	arm-linux-ld -Ttext 0 led_on.o -o led_on.elf
	arm-linux-objcopy -O binary -S led_on.elf led_on.bin
	arm-linux-objdump -D led_on.elf > led_on.dis
clean:
	rm *.bin *.o *.elf
	

arm-linux-ld -Ttext 0 led_on.o -o led_on.elf设置程序从地址0处存放代码段,递增存放数据段、bss段

arm-linux-objcopy常用于文件格式转换,这里将elf格式文件转化为bin文件。

参考:arm-linux-objcopy; arm-linux-ld命令

实验2 C代码点灯

同实验1.

汇编码:

注意: C代码必须设置堆栈大小(SP)

.text
.global _start

_start:

	/* 设置内存: sp 栈 */
	ldr sp, =4096  /* nand启动 */
//	ldr sp, =0x40000000+4096  /* nor启动 */

	/* 调用main */
	bl main

halt:
	b halt

C代码:

int main()
{
	unsigned int *pGPFCON = (unsigned int *)0x56000050;
	unsigned int *pGPFDAT = (unsigned int *)0x56000054;

	/* 配置GPF4为输出引脚 */
	//*pGPFCON = 0x100;
	*pGPFCON = 0x400;
	
	/* 设置GPF4输出0 */
	*pGPFDAT = 0;

	return 0;
}

Makefile脚本

这里比汇编点灯多了一行:将.c转化为.o

all:
	arm-linux-gcc -c -o led.o led.c
	arm-linux-gcc -c -o start.o start.S
	arm-linux-ld -Ttext 0 start.o led.o -o led.elf
	arm-linux-objcopy -O binary -S led.elf led.bin
	arm-linux-objdump -D led.elf > led.dis
clean:
	rm *.bin *.o *.elf *.dis

实验3 汇编传参C点灯

实验内容:循环点LED0、LED1,中间延时一段时间。

原理图、S3C3440手册:参考实验1

汇编码:

.text
.global _start

_start:

	/* 设置内存: sp 栈 */
	ldr sp, =4096  /* nand启动 */
//	ldr sp, =0x40000000+4096  /* nor启动 */

	mov r0, #4
	bl led_on

	ldr r0, =100000
	bl delay

	mov r0, #5
	bl led_on

halt:
	b halt

C代码:

注意: 这里没有main函数,在汇编码中直接跳转到led_on,汇编码中在函数跳转前,将参数保存在r0中.

void delay(volatile int d)
{
	while (d--);
}

int led_on(int which)
{
	unsigned int *pGPFCON = (unsigned int *)0x56000050;
	unsigned int *pGPFDAT = (unsigned int *)0x56000054;

	if (which == 4)
	{
		/* 配置GPF4为输出引脚 */
		*pGPFCON = 0x100;
	}
	else if (which == 5)
	{
		/* 配置GPF5为输出引脚 */
		*pGPFCON = 0x400;
	}
	
	/* 设置GPF4/5输出0 */
	*pGPFDAT = 0;

	return 0;
}

Makefile文件:同实验2

实验4 按键控制点灯

实验内容:按键1、2、3控制LED1、2、3亮灭。按键按下,灯亮;按键释放,灯灭。

硬件原理图(按键):

 

 S3C2440芯片手册:

GPF的前面已经截图了,这里只截图K3用到的GPG寄存器

 

 

汇编代码:

这里关闭了看门狗;判断了是从Nand/Nor启动,从而设置堆栈起始地址,可以不用关心。


.text
.global _start

_start:

	/* 关闭看门狗 */
	ldr r0, =0x53000000
	ldr r1, =0
	str r1, [r0]

	/* 设置内存: sp 栈 */
	/* 分辨是nor/nand启动
	 * 写0到0地址, 再读出来
	 * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
	 * 否则就是nor启动
	 */
	mov r1, #0
	ldr r0, [r1] /* 读出原来的值备份 */
	str r1, [r1] /* 0->[0] */ 
	ldr r2, [r1] /* r2=[0] */
	cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
	ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
	moveq sp, #4096  /* nand启动 */
	streq r0, [r1]   /* 恢复原来的值 */
	

	bl main

halt:
	b halt
	

C代码:

#include "s3c2440_soc.h"

void delay(volatile int d)
{
	while (d--);
}

int main(void)
{
	int val1, val2;
	
	/* 设置GPFCON让GPF4/5/6配置为输出引脚 */
	GPFCON &= ~((3<<8) | (3<<10) | (3<<12));
	GPFCON |=  ((1<<8) | (1<<10) | (1<<12));

	/* 配置3个按键引脚为输入引脚:
	 * GPF0(S2),GPF2(S3),GPG3(S4)
	 */
	GPFCON &= ~((3<<0) | (3<<4));  /* gpf0,2 */
	GPGCON &= ~((3<<6));  /* gpg3 */

	/* 循环点亮 */
	while (1)
	{
		val1 = GPFDAT;
		val2 = GPGDAT;

		if (val1 & (1<<0)) /* s2 --> gpf6 */
		{
			/* 松开 */
			GPFDAT |= (1<<6);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1<<6);
		}

		if (val1 & (1<<2)) /* s3 --> gpf5 */
		{
			/* 松开 */
			GPFDAT |= (1<<5);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1<<5);
		}

		if (val2 & (1<<3)) /* s4 --> gpf4 */
		{
			/* 松开 */
			GPFDAT |= (1<<4);
		}
		else
		{
			/* 按下 */
			GPFDAT &= ~(1<<4);
		}

		
	}

	return 0;
}

头文件s3c2440_soc.h:

这里将芯片寄存器封装了一下。

#ifndef  __S3C2440_SOC_H
#define  __S3C2440_SOC_H

#define     __REG(x)					(*(volatile unsigned int *)(x)) 
  
/*I/O port*/                              
#define     GPFCON                   __REG(0x56000050)  //Port F control                                   
#define     GPFDAT                   __REG(0x56000054)  //Port F data                                      
#define     GPFUP                    __REG(0x56000058)  //Pull-up control F                                
#define     GPGCON                   __REG(0x56000060)  //Port G control                                   
#define     GPGDAT                   __REG(0x56000064)  //Port G data                                      
#define     GPGUP                    __REG(0x56000068)  //Pull-up control G                                
#define     GPHCON                   __REG(0x56000070)  //Port H control                                   
#define     GPHDAT                   __REG(0x56000074)  //Port H data    
#endif

Makefile代码:

all:
	arm-linux-gcc -c -o key_led.o key_led.c
	arm-linux-gcc -c -o start.o start.S
	arm-linux-ld -Ttext 0 start.o key_led.o -o key_led.elf
	arm-linux-objcopy -O binary -S key_led.elf key_led.bin
	arm-linux-objdump -D key_led.elf > key_led.dis
clean:
	rm *.bin *.o *.elf *.dis

标签:led,ldr,--,逻辑程序,elf,int,linux,S3C2440,arm
来源: https://blog.csdn.net/u010743406/article/details/118976685

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有