S3C2440 用C语言点亮LED

发布者:JoyfulExplorer最新更新时间:2024-07-25 来源: cnblogs关键字:S3C2440  C语言  点亮LED 手机看文章 扫描二维码
随时随地手机看文章

一、从汇编到C函数

1、设置栈

为什么从汇编调用C函数需要设置栈?
1、因为arm汇编调用C函数参数要遵循APCS规则。即参数小于等于4个可以用R0-R3来传参;多于4个的参数,前四个参数用R0-R3传参,第五个参数开始使用栈来传参
2、C函数内部使用到的局部变量,它所存储的空间就是栈空间
3、C函数里面调用C函数时,需要用栈来保存返回地址(LR寄存器的值)。

二、怎么设置堆栈

1、设置SP寄存器

设置栈,本质就是将SP(堆栈寄存器)指向一块内存。在S3C2440处理器里,要指向那块内存呢?
由于S3C2440在上电启动的时候,外部内存还没有初始化,我们只能将SP指向它内部4Kb的SRAM
又因为S3C2440支持nand flash启动和nor flash启动两种方式启动,而且两种方式的启动,内部SRAM的映射地址不一样,所以里两种方式设置地址不一样

2、nand flash启动

从下面的内存映射图可以看出;从nand flash启动的时候,内部SRAM被映射到了0x0000 0000地址;因为编译器编译的使用的是递减栈变编译的,所以通常我们将SP指向内部SRAM的最高地址处0x1000 (4096)

2、nor flash启动

从下面的内存映射图可以看出;从nand flash启动的时候,内部SRAM被映射到了0x4000 0000地址,所以通常我们将SP指向内部SRAM的最高地址处0x40001000 (0x40000000+0x1000)

三、程序

下面还是以点亮LED为例程,通过调用C函数来点亮一盏LED灯,在S3C2440启动流程已经给出了硬件原理图,这里就不贴出来了


1、启动程序(汇编程序 Startup.S)



.text                     /*定义代码段*/

.global _start            /*标号_start是GNU连接器用来指定第一个要执行所必须的(只能出现在一个模块),.global将_start声明为全局可见*/


_start:

    /* 设置栈 */

    /* nand flash 启动的设置方法 */

    ldr sp, =0x1000  /* 将栈设置在4k处 */

    /* nor flash 启动的设置方法 */

    //ldr sp, =0x40000000+0x1000  /* 将栈设置在0x40000000 + 4k处 (本程序使用nand flash启动,所以这里注释掉)*/

    /*调用C函数*/

    b main

loop:

    b loop

2、C函数(main.c)

/* 定义GPFCON 寄存器 */

#define  GPFCON    *((volatile unsigned long*)0x56000050)


/* 定义GPFDAT 寄存器 */

#define  GPFDAT    *((volatile unsigned long*)0x56000054)

int main(){

/* 清零 */

GPFCON &= ~(0x03 << 8);

/* 设置为output */

GPFCON |= (0x01<<8);

/* 将 GPF4 输出低电平 */

GPFDAT &= ~(1<<4);

while(1);

return 0;

}

3、Makefile

all:

arm-linux-gcc -c Startup.S -o Startup.o

arm-linux-gcc -c main.c -o main.o

arm-linux-ld -Ttext 0 Startup.o main.o -o Led.elf

arm-linux-objcopy -O binary -S Led.elf Led.bin

arm-linux-objdump -D Led.elf > led.dis

clean:

rm *.o *.elf *.bin *.dis

4、反汇编程序

在看反汇编的时候,可能会遇到sl,ip,fp,a1-a4,v1-v6这些寄存器,这些寄存器只是在APCS规则下的别名。他们对应的关系: sl->r10, fp->r11, ip->r12, a1-a4->r0-r3, v1-v6->r4-r9。


Led.elf:     file format elf32-littlearm


Disassembly of section .text:


00000000 <_start>:

   0: e3a0da01 mov sp, #4096 ; 0x1000   /* 设置sp */

   4: ea000000 b c

        /* 跳到 C语言的main函数执行 */


00000008 :

   8: eafffffe b 8


0000000c

:

   c: e1a0c00d mov ip, sp          /* 将sp的值保存起来,这里的ip寄存器其实是R12 */

  10: e92dd800 stmdb sp!, {fp, ip, lr, pc} /* 先将pc,lr,ip, fp 寄存器的值压入栈 */

  14: e24cb004 sub fp, ip, #4 ; 0x4 

  18: e3a02456 mov r2, #1442840576 ; 0x56000000    /* 下面的汇编语言就是操作GPF的寄存器的操作了 */

  1c: e2822050 add r2, r2, #80 ; 0x50

  20: e3a03456 mov r3, #1442840576 ; 0x56000000

  24: e2833050 add r3, r3, #80 ; 0x50

  28: e5933000 ldr r3, [r3]

  2c: e3c33c03 bic r3, r3, #768 ; 0x300

  30: e5823000 str r3, [r2]                       

  34: e3a02456 mov r2, #1442840576 ; 0x56000000

  38: e2822050 add r2, r2, #80 ; 0x50

  3c: e3a03456 mov r3, #1442840576 ; 0x56000000

  40: e2833050 add r3, r3, #80 ; 0x50

  44: e5933000 ldr r3, [r3]

  48: e3833c01 orr r3, r3, #256 ; 0x100

  4c: e5823000 str r3, [r2]

  50: e3a02456 mov r2, #1442840576 ; 0x56000000

  54: e2822054 add r2, r2, #84 ; 0x54

  58: e3a03456 mov r3, #1442840576 ; 0x56000000

  5c: e2833054 add r3, r3, #84 ; 0x54

  60: e5933000 ldr r3, [r3]

  64: e3c33010 bic r3, r3, #16 ; 0x10

  68: e5823000 str r3, [r2]

  6c: eafffffe b 6c     /* 死循环 */

Disassembly of section .comment:


00000000 <.comment>:

   0: 43434700 cmpmi r3, #0 ; 0x0

   4: 4728203a undefined

   8: 2029554e eorcs r5, r9, lr, asr #10

   c: 2e342e33 mrccs 14, 1, r2, cr4, cr3, {1}

  10: Address 0x10 is out of bounds.

四、实验现象

实验现象也是点亮一盏LED灯,就不贴图上来了。


关键字:S3C2440  C语言  点亮LED 引用地址:S3C2440 用C语言点亮LED

上一篇:S3C2440 启动和点亮第一盏LED
下一篇:S3C2440 初始化时钟

推荐阅读最新更新时间:2024-11-09 08:49

S3C2440 USB 设备控制器
s3c2440 soc集成了一个usb1.1设备控制器,可以进行全速/低速的控制,中断与批量传输。除了端点0,具有四个端点,每个端点都可以作为中断与批量的端点,每个端点具有128 byte的FIFO,所以端点最大packet可以设置成128byte。并且支持DMA传输。任何一种设备控制器对于软件来说都是一组寄存器:数据,状态,控制。usb 设备控制器也不例外。设置好相应的控制寄存器,并且在数据来时读取数据寄存器,需要发送数据的时候将数据写入输出寄存器。而这种数据的通信建立在对状态寄存器的读取上,往往还会有中断与DMA的操作。s3c2440 usb设备控制器的寄存器分为以下几组: (1):电源管理寄存器 PWR_REG
[单片机]
S3C2440 gpio
WATCHDOG TIMER 原理图 手册 举例 start.S .globl _start _start:/* 关看门狗 *//* 往WTCON(0x53000000)写0 */ ldr r0, =0x53000000 mov r1, #0 str r1, @ str, store, /* 设置GPFCON让GPF5作为输出引脚 */ ldr r1, =0x56000050 mov r0, #(1 10) str r0, /* 设置GPFDAT让GPF5输出0 */ ldr r1, =0x56000054 mov r0, #0 str r0, /* 无限循环 */halt: b h
[单片机]
<font color='red'>S3C2440</font> gpio
ARM9(S3C2440) ADC
模拟信号/数字信号 (1)、模拟信号是一种在时间上连续,数值上也连续的物理量,具有无穷多的数值,从自然界感知的大部分物理量都是模拟性质的,如速度,压力,温度,声音等。 (2)、数字信号在时间上和数值上均是离散的,而离散信号的值只有真与假,是或不是,因此可以使用二进制中的0与1来表示 。 ADC驱动流程 ADC主要驱动程序 main.c #define ADC_FREQ 2500000 void Main(void) { /*时钟初始化*/ Set_Clk(); /*adc初始化*/ adc_init(); while(1) {
[单片机]
s3c2440裸机-电阻触摸屏编程(4.isr设计_4.1获取触摸屏坐标)
1.进入自动测量模式 上一节介绍了TSC的初始化,以及中断服务程序框架,能够对的触摸屏进行基本的按下松开检测。 那让bit =1, bit =00,则会进入auto measurement。如果bit =0,则需配置bit =01 or 10是手动测量x,y坐标。 #define AUTO_PST (1 2) /*自动转换*/ #define WAIT_INT_MODE (3) /*等待中断模式*/ #define NO_OPR_MODE (0) /*禁止模式*/ void enter_auto_measure_mode(void) {   ADCTSC = AUTO_PST | NO_OPR_M
[单片机]
<font color='red'>s3c2440</font>裸机-电阻触摸屏编程(4.isr设计_4.1获取触摸屏坐标)
STM32如何新建工程+寄存器点亮LED
STM32新建工程跟51差不多的,但是32会多点东西,比如加载芯片支持包啦,启动文件啦。还有一个很重要的 你得有KEIL5 是吧哈哈 我这里就不写如何安装KEIL5了 网上挺多资源的,这里就主要写一下如何新建工程点亮一个LED灯。 我这里用STM32F103C8T6 我这里用STM32F103C8T6 一: 如何新建工程 1:下载芯片支持包Keil.STM32Fxxxx.pack文件 1.进入KEIL5官网。 找到自己的型号 这样就下载了 芯片支持包了。 2:打开KEIL5 加载Keil.STM32Fxxxx.pack文件 .打开KEIL5 把 下载的 Keil.STM32Fxxxx.pack文件
[单片机]
STM32如何新建工程+寄存器<font color='red'>点亮</font><font color='red'>LED</font>灯
u-boot-2011.06在基于s3c2440开发板的移植之NorFlash启动
在移植之前,我们还需要安装、配置eldk,用于编译u-boot。下面我们就先介绍一下eldk的安装与配置: 1.下载eldk 在 这里 选择任一版本的eldk并下载,我选择的是eldk4.2版本的arm-2008-11-24.iso文件。把该文件下载到/home/zhaocj/download/目录下。 2.在root权限下安装eldk 创建挂载点: mkdir /mnt/dvdrom 挂载光驱: mount –o loop /home/zhaocj/download/arm-2008-11-24.iso/mnt/dvdrom 安装eldk: cd /mnt/dvdrom ./install –d /opt/eldk4.2/
[单片机]
S3C2440 存储器控制器分析
首先说一下,S3C2440 存储器空间并不包括NAND FLASH ,NAND FLASH只是一个外设而已。 S3C2440存储器控制器的寻址范围是0~0x3fff ffff,共1G。这1G空间分为8个BANK,BANK0~BANK7。 在产品开发阶段,一般使用BANK0控制NOR FLASH,BANK6控制SDRAM;对于成品,则会去掉NOR FLASH,而将固件放在NAND FLASH上,SDRAM不变。 对于代码存储,如NOR FLASH,是没有必要访问到具体字节;而对于SDRAM,因为可能保存有字节变量,必须得支持访问到字节。这里就说一下,在32位总线宽度下,存储器控制器是如何访问SDR
[单片机]
Linux驱动之内核自带的S3C2440的LCD驱动分析
先来看一下应用程序是怎么操作屏幕的:Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。FrameBuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过Framebuffer的读写直接对显存进行操作。用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节,这些都是由Framebuffer设备驱动来完成的。 文字说明可能不是很明白,下
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved