栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux S3C2440 学习笔记02

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux S3C2440 学习笔记02

文章目录

开发板接口和串口连接

MobaXterm设置eoploadTool 安装USB下载系统启动流程 Ping设置汇编指令

汇编指令示例

拓展:哈佛结构和冯诺依曼结构 汇编指令点灯示例linux上编译指令

反编译后的文件分析 Makefilewindows快速在当前路径执行cmd命令的小技巧程序上传过程 字节序C语言点灯示例

设置main入口 示例交替点灯按键控制led示例
(韦东山老师课程)


韦老师官网链接


开发板接口和串口连接
    使用串口观察信息使用JTAG烧写程序
MobaXterm设置

Session
Serial
Serial Port 设置
Speed(bps)115200

Flow control流量控制一定要设置为None

eoploadTool 安装

管理员打开


bin文件烧写
对应文件路径

oflash 文件名.bin

然后 01000 
0 OpenJTAG
1 S3C2440
0 Nand
0 Nand
0 0地址开始

开关设置为Nand
拔掉排线
按电源重启
USB下载

使用排线烧写u-boot到Nor
重启电源,立刻在MobaXterm中按下空格
输入n
使用zadig 安装libusb
使用dnw传输文件

系统启动流程

PC
BIOS
启动内容
windows操作系统
识别挂载C盘,内含APP
存储:硬盘

Linux
bootloader(uboot是其中最广泛的一种)
引导启动LInux内核
挂载根文件系统 内含APP
存储:flash
Nor flash 1~2M : bootloader
Nand flash 256M : bootloader params kernel rootfs

恢复出厂系统

    烧写uboot Nor/Nand op/eop烧写烧写 Kernal USB下载烧写 重启电源,立刻在MobaXterm中按下空格 输入k DNW传输uImage_3.5烧写文件系统 输入y DNW传输fs_qtopia.yaffs2删除para 使用默认参数 输入q 再输入mtd
nand erase params
Ping设置
set ipaddr 192.168.1.122
汇编指令
指令全称中文
ldrload读内存
strstore写内存
b跳转
movmove移动
BLbranch and link跳转到某一个地址并把返回地址(下一条指令的地址)保存在lr寄存器
ldmm->many读内存,写入多个寄存器
stmm->many把多个寄存器的值,写入内存
汇编指令示例

sub r0,r1,#4
r0 = r1-4


add r0,r1,#4
r0 = r1+4





MOV
1.可以寄存器与寄存器之间传递数据

2.可以常数传递到寄存器中(常数不能超过32位)

LDR

1.可以地址与寄存器之间的数据传递

2.也可以常数传递到寄存器中

R0~R14 CPU中的寄存器
a1~pc 寄存器的别名


pc Program Counter 程序计数器 只要把地址写进这个寄存器,程序就会跳到那个地址 用来存储指向下一条指令的地址,也即将要执行的指令代码
pc地址 = 当前指令+8
因为arm架构可以理解为流水线,在上一个命令执行a+4时,已经开始解释下一条命令a+8


lr link Register 用来保存返回地址


sp Stack Pointer 栈指针

拓展:哈佛结构和冯诺依曼结构

引用自这里
哈佛结构认为CPU应该分别通过2组独立的总线来对接指令和数据


冯诺依曼结构认为CPU通过1组总线来分时获取指令和数据即可。


51单片机、典型的STM32单片机(核心是ARM Cortex-M系列的)都是哈佛结构


PC和服务器芯片(譬如Intel AMD那些出的),ARMCortex-A系列嵌入式芯片(譬如核心是ARM CortexA8的三星S5PV210,譬如华为的麒麟970等手机芯片)等都是冯诺依曼结构。这些系统都需要大量内存,所以工作内存都是DRAM,因为他们更适合使用冯诺依曼系统。


现代的CPU(准确说叫SoC)基本都不是纯粹的哈佛结构或冯诺依曼机构,而都是混合结构的。

ldr r0,[r1]
读取地址r1上的数据,存到r0

str r0,[r1]
把r0的值写到r1这个地址上面

mov r0,r1
把r0的值赋给r1 r0=r1

mov r0,#0x100
r0 = 0x100

ldr r0,=0x12345678

伪指令,它会拆分成几条指令
r0=0x12345678

ARM 指令值的大小<32位

汇编指令点灯示例


.text

//.global关键字用来让一个符号对链接器可见,可以供其他链接对象模块使用。
//.global _start 让 _start 符号成为可见的标识符,这样链接器就知道跳转到程序中的什么地方并开始执行。linux寻找这个 _start 标签作为程序的默认进入点。
.global _start

_start:


// 使用伪指令把0x5600050放到r1里面
    ldr r1, =0x56000050
    ldr r0, =0x100

//  把r0赋值到r1这个地址上面
    str r0,[r1]


 
      ldr r1, =0x56000054
      ldr r0, =0
      str r0,[r1]

//死循环
halt:
    //跳转到死循环
    b halt
linux上编译指令

一定要注意空格

    预编译
arm-linux-gcc -c -o led_on.o led_on.S

-c 预编译,只编译不链接
-o output 输出目标文件

    链接
arm-linux-ld -Ttext 0 led_on.o -o led_on.elf

arm-linux-ld
简称(link editor)
是一个链接程序工具,其作用主要是将汇编过的多个二进制文件进行链接,成为一个可执行的二进制文件.
-Ttext ADDRESS 代码段链接地址

    转换成二进制bin文件
 arm-linux-objcopy -O binary -S led_on.elf led_on.bin

arm-linux-objcopy用于复制一个目标文件的内容到另一个文件中,可以使用不同于原目标文件的格式来输出目的文件,即其可以进行格式转换。
-O 大写 output 输出

反汇编

	arm-linux-objdump -D led_on.elf > led_on.dis

查看目标文件(.o文件)和库文件(.a文件)信息
-D 显示文件中所有汇编信息
‘>’ 表示将这个程序的反汇编程序写入到led.dis这个文件中,在终端中不显示出来.

反编译后的文件分析

led_on.elf:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_start>:

  //从内存pc,#20中读取值,就是从地址1c读取56000050到r1里面
  //r1 = pc+20 因为pc 从当前指令0开始+8 r1=0+8+20=0x1c,去0x1c这个地址读取内存的值
   0:	e59f1014 	ldr	r1, [pc, #20]	; 1c <.text+0x1c>

   //把256放到r0 r0=0x100
   4:	e3a00c01 	mov	r0, #256	; 0x100

   //把r0即0x100写入r1对应的地址
   8:	e5810000 	str	r0, [r1]

   //从内存pc,#12中读取值,就是从地址20读取56000054到r1里面
   //r1 = pc+20 因为pc 从当前指令地址c开始,所以 r1=c+8+12=32=0x20,去0x20这个地址读取内存的值存到r1
   c:	e59f100c 	ldr	r1, [pc, #12]	; 20 <.text+0x20>
  10:	e3a00000 	mov	r0, #0	; 0x0
  14:	e5810000 	str	r0, [r1]

00000018 :
  18:	eafffffe 	b	18 
  1c:	56000050 	undefined
  20:	56000054 	undefined


Makefile
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
clean:
	rm *.bin *.o *.elf

进行编译

make

进行删除

make clean
windows快速在当前路径执行cmd命令的小技巧

程序上传过程

我个人感觉完全没必要使用网线通过nfs传输。。

程序项目文件使用vsCode编写,存到window&linux共享文件夹,然后在虚拟机ubuntu上面使用arm-gcc编译,编译好了在window共享文件夹上用oflash通过排线将bin文件烧录到开发板

linux环境作用:arm-linux gcc方便使用linux头文件进行编译
windows环境作用:日常电脑系统,主要使用上位机软件oflash烧录程序到开发板

字节序

小字节序存储:低位存在低地址
大字节序存储:高位存在低地址

C语言点灯示例
int main()
{
    unsigned int* pGPFCON = 0x56000050;
    unsigned int* pGPFDAT = 0x56000054;

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

    //设置GPF4输出0
    *pGPFDAT=0;

    return 0;
}
设置main入口

//.text 指定了后续编译出来的内容放在代码段
.text
.global _start

//_start是一个函数的起始地址,也是编译、链接后程序的起始地址。由于程序是通过加载器来加载的,必须要找到 _start名字的函数,
//因此_start必须定义成全局的,以便存在于编译后的全局符合表中,供属其它程序【如加载器】寻找到。
_start:

//设置内存 sp 栈 nand启动时,nand大小是4K,所以把栈设置在内存的顶部
    ldr sp, =4096
    
//nor 启动
    ldr sp, = 0x40000000+4096

//调用Main 跳转过去执行Main 并把返回的地址保存到lr里面
    bl main

// 死循环 b常用于不返回的跳转
halt:
    b halt


拓展:栈为什么是从高地址往低地址分配内存的?

示例交替点灯
int led_on(int which)
{
    unsigned int* pGPFCON = 0x56000050;
    unsigned int* pGPFDAT = 0x56000054;

    if(which==4)
    {
      *pGPFCON = 0x100;
    }
    else if(which==5)
    {
      *pGPFCON = 0x400;
    }

   *pGPFDAT=0;
}

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

int main()
{


    return 0;
}

汇编文件

//.text 指定了后续编译出来的内容放在代码段
.text
.global _start

//_start是一个函数的起始地址,也是编译、链接后程序的起始地址。由于程序是通过加载器来加载的,必须要找到 _start名字的函数,
//因此_start必须定义成全局的,以便存在于编译后的全局符合表中,供属其它程序【如加载器】寻找到。
_start:

//设置内存 sp 栈 nand启动时,nand大小是4K,所以把栈设置在内存的顶部
    ldr sp, =4096
    
//nor 启动
    ldr sp, = 0x40000000+4096

//传参
    mov r0,#4 
//调用Main 跳转过去执行Main 并把返回的地址保存到lr里面
    bl led_on

    ldr r0,=100000
    bl delay

    mov r0,#5  
    bl led_on

// 死循环 b常用于不返回的跳转
halt:
    b halt

按键控制led示例
#include "s3c2440_soc.h"
void delay(int d)
{
    while(d--);
}

int main()
{

    int val=1;

    GPFCON &=~((3<<8) | (3<<10) |(3<<12));
    GPFCON |=((1<<8) | (1<<10) |(1<<12));
    
    //配置3个按键引脚为输入 GPF0,2,GPG3
    GPFCON &=~((3<<0) | (3<<4));
    GPGCON &=~(3<<6);

   
   
    while(1)
    {
      int i = 0;
      for (i = 0; i < 3; i++)
      {
        int keyOn[3] = {~GPFDAT&(0x1<<0),~GPFDAT&(0x1<<2),~GPGDAT&(0x1<<3)};
        if(keyOn[i])
        {
          GPFDAT&=~((i==0?1:i*2)<<4);
        }
        else
        {
          GPFDAT|=(7<<4);
        }
      }
      // if(~GPFDAT&(0x1<<0))
      // {
      //   GPFDAT&=~(1<<4);
      // }
      // else if(~GPFDAT&(0x1<<2))
      // {
      //   GPFDAT&=~(2<<4);  
      // }
      // else if(~GPGDAT&(0x1<<3))
      // {
      //   GPFDAT&=~(4<<4);
      // }
      // else
      // {
      //   GPFDAT|=(7<<4);
      // }

      
    }

    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/728657.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号