MOV R0 #X;第一个立即数的低32位
MOV R1 #Y;第二个立即数的低32位
ADD R2 R1 R0;低位相加
MOV R0 #X>>32;第一个立即数的高32位
MOV R1 #Y>>32;第二个立即数的高32位
ADC R1 R0;带进位的高位相加
MOV R0 #NUM;内存单元NUM地址送入R0
STR R2 [R0];存储低32位结果
STR R1 [R0,#32];存储高32位结果
keil 里面的stdioh
和PC上的一样只是个头文件而已
库里面的printf函数不是用来显示的
而是你 如果51单片机的串口初始化了
printf函数会把你的数据从串口输出而已
你软件仿真查看串口那边的输出就知道了
存在问题:“普通电脑显示器”可能比较难,需要了解CRT或LCD显示器的接口。一般是驱动TFT等类型的LCD显示器。
前期基础:了解ARM核基本使用、了解C/C++语言基础及一点ARM汇编、了解开发工具链基本使用;还需要了解一些简单的硬件基础。
基本条件:有原理图,有相应芯片的datasheet。
开始:(各种ARM芯片流程大致类似)
1 ARM启动代码:异常向量、中断初始化;(代码搬移,可选);堆、栈初始化;CPU、MMU、时钟等的初始化,C运行环境的其他准备。
2 进入C后,基本驱动编写:需要了解ARM芯片是否有LCD控制器,然后根据情况编写这部分驱动代码(第一回配置可能不太容易,可参考样例程序),如果没有LCD控制器就有点麻烦了(其他芯片做?自己写?);其他驱动程序(存储器,如SDRAM、FLASH等),根据需要编写。
3 基本库程序:可以自写,也可以找现成的,主要涉及字符串处理、IO处理(printf)等,其他基本库(内存分配等)。
4 编写应用程序:你的这个例子就是在显示驱动基础上,写“Hello world”。
5 编写连接脚本:根据内存分配情况和程序存储情况写,有模板,连接时用。
开发流程:
1 编写程序;
2 编译;
3 连接;
4 加载或下载;
5 调试/运行;
6 反复执行1~5步骤,直到实现你的功能。
参考:
1 各芯片厂商的application note,有应用程序样例及代码,也可以找到相关驱动程序的样例;
2 网上搜索或看书学习开发过程;
3 可以参考uboot早期一些的代码,比较简单好懂。
你可以自己写一个汇编的程序,把Nand Flash 中的程序搬到SDRAM中。因为S3C2410有Nor Flash和Nand Flash有两种启动方式,所以在搬移过程中略有不同。如果用Nand Flash启动可以使用下面的代码,至于Nor Flash启动就相对简单了,你可以自己研究一下。
文件1heads
@ 文件 heads
@ 作用:关闭看门狗、SDRAM 的初始化设置、搬移 Nand Flash 4K 以后
@ 的代码到 SDRAM 的指定位置、执行 SDRAM 中的代码
text
global _start
_start:
ldr r0, =0x53000000 @ Close Watch Dog Timer
mov r1, #0x0
str r1, [r0]
bl memory_setup @ Initialize memory setting
bl flash_to_sdram @ Copy code to sdram
ldr sp, =0x34000000 @ Set stack pointer
ldr pc, =main @ execute the code in SDRAM
文件2:flashs
@ 文件 flashs
@ 作用:设置 Nand Flash 的控制寄存器、读取 Nand Flash
@ 中的代码到 SDRAM 的指定位置
equ NFCONF, 0x4e000000
equ NFCMD, 0x4e000004
equ NFADDR, 0x4e000008
equ NFDATA, 0x4e00000c
equ NFSTAT, 0x4e000010
equ NFECC, 0x4e000014
global flash_to_sdram
flash_to_sdram:
@ Save return addr
mov r10,lr
@ Initialize Nand Flash
mov r0,#NFCONF
ldr r1,=0xf830
str r1,[r0]
@ First reset and enable Nand Flash
ldr r1,[r0]
bic r1, r1, #0x800
str r1,[r0]
ldr r2,=NFCMD
mov r3,#0xff
str r3,[r2]
@ for delay
mov r3, #0
1:
subs r3, r3, #1
bne 1b
@ Wait until Nand Flash bit0 is 1
wait_nfstat:
ldr r2,=NFSTAT
ldr r3,[r2]
tst r3,#0x01
beq wait_nfstat
@ Disable Nand Flash
ldr r0,=NFCONF
ldr r1,[r0]
orr r1,r1,#0x8000
str r1,[r0]
@ Initialzie stack
ldr sp,=4096
@ Set arguments and call
@ function nand_read defined in nand_readc
ldr r0,=0x30000000
mov r1,#4096
mov r2,#1024
bl nand_read
@ return
mov pc,r10
文件3:interruptc
/
文件 interruptc
作用:设置并响应按键中断
/
#include "printfh"
#define GPECON ((volatile unsigned long )0x56000040)
#define GPEDAT ((volatile unsigned long )0x56000044)
#define GPEUP ((volatile unsigned long )0x56000048)
#define GPFCON ((volatile unsigned long )0x56000050)
#define GPFDAT ((volatile unsigned long )0x56000054)
#define GPFUP ((volatile unsigned long )0x56000058)
#define GPGCON ((volatile unsigned long )0x56000060)
#define GPGDAT ((volatile unsigned long )0x56000064)
#define GPGUP ((volatile unsigned long )0x56000068)
#define EINTMASK ((volatile unsigned long )0x560000a4)
#define INTMSK ((volatile unsigned long )0X4a000008)
#define PRIORITY ((volatile unsigned long )0x4a00000c)
#define EINTPEND ((volatile unsigned long )0x560000a8)
#define INTPND ((volatile unsigned long )0X4a000010)
#define SRCPND ((volatile unsigned long )0X4a000000)
#define BIT_EINT0 (0x1 << 0)
#define BIT_EINT2 (0x1 << 2)
#define BIT_EINT8_23 (0x1 << 5)
#define SET_KEY_INTERRUPT_REG() ({ \
GPGCON = (GPGCON & (~((3<<12)|(3<<4)))) | ((1<<12)|(1<<4)) ; \
GPGDAT = GPGDAT & (~((1<<6)|(1<<2))); \
GPECON = (GPECON & (~((3<<26)|(3<<22)))) | ((1<<26)|(1<<22)); \
GPEDAT = GPEDAT & (~((1<<13)|(1<<11))); \
GPGCON = (GPGCON & (~((3<<22)|(3<<6)))) | ((2<<22)|(2<<6)) ; \
GPFCON = (GPFCON & (~((3<<4)|(3<<0)))) | ((2<<4)|(2<<0)) ; \
})
__inline void ClearPending(int bit)
{
SRCPND = bit;
INTPND = bit;
}
void init_irq( ) {
GPFCON = ((0x1<<8) | (0x1 << 10) | (0x1 << 12) | (0x1 << 14)); // Set the led D9~D12 output
/
GPGCON = (GPGCON & (~((3<<12)|(3<<4)))) | ((1<<12)|(1<<4)) ; // GPGCON6,2 set output
// GPGCON6:KSCAN1
// GPGCON2:KSCAN3
GPGDAT = GPGDAT & (~((1<<6)|(1<<2))); // GPGDAT6,2 output 0
GPECON = (GPECON & (~((3<<26)|(3<<22)))) | ((1<<26)|(1<<22)); // GPECON13,11 set output
GPEDAT = GPEDAT & (~((1<<13)|(1<<11))); // GPEDAT13,11 output 0
GPGCON = (GPGCON & (~((3<<22)|(3<<6)))) | ((2<<22)|(2<<6)) ; // GPGCON11,3 set EINT
GPFCON = (GPFCON & (~((3<<4)|(3<<0)))) | ((2<<4)|(2<<0)) ; // GPFDAT2,0 set EINT
/
// Use the defined micro instead of above code
SET_KEY_INTERRUPT_REG();
GPFUP |= (1<<0) | (1<<2); // Up
GPGUP |= (1<<3) | (1<<11); // Up
EINTPEND |= (1 << 19) | (1 << 11); // Clear eint 11,19
EINTMASK &= (~((1 << 19) | (1 << 11))); // Enable EINT11,19
ClearPending(BIT_EINT0|BIT_EINT2|BIT_EINT8_23); // Enable EINT0,2 and the EINT8_23
INTMSK &= (~0x25);
return;
}
int Key_Scan( void )
{
int i;
for(i = 0; i < 1000 ;i++) ;
GPGDAT = (GPGDAT &(~((1<<6)|(1<<2)))) | (1<<6) | (0<<2) ; //GPG6,2 output 0
GPEDAT = (GPEDAT &(~((1<<13)|(1<<11)))) | (1<<13) | (1<<11) ; //GPE13,11 output 0
if( (GPFDAT&(1<< 0)) == 0 ) return 16 ;
else if( (GPFDAT&(1<< 2)) == 0 ) return 15 ;
else if( (GPGDAT&(1<< 3)) == 0 ) return 14 ;
else if( (GPGDAT&(1<<11)) == 0 ) return 13 ;
GPGDAT = (GPGDAT &(~((1<<6)|(1<<2)))) | (0<<6) | (1<<2) ; //GPG6,2 output 0
GPEDAT = (GPEDAT & (~((1<<13)|(1<<11)))) | (1<<13) | (1<<11) ; //GPE13,11 output 0
if( (GPFDAT&(1<< 0)) == 0 ) return 11 ;
else if( (GPFDAT&(1<< 2)) == 0 ) return 8 ;
else if( (GPGDAT&(1<< 3)) == 0 ) return 5 ;
else if( (GPGDAT&(1<<11)) == 0 ) return 2 ;
GPGDAT = (GPGDAT & (~((1<<6)|(1<<2)))) | (1<<6) | (1<<2) ; //GPG6,2 output 0
GPEDAT = (GPEDAT & (~((1<<13)|(1<<11)))) | (1<<13) | (0<<11) ; //GPE13,11 output 0
if( (GPFDAT&(1<< 0)) == 0 ) return 10 ;
else if( (GPFDAT&(1<< 2)) == 0 ) return 7 ;
else if( (GPGDAT&(1<< 3)) == 0 ) return 4 ;
else if( (GPGDAT&(1<<11)) == 0 ) return 1 ;
GPGDAT = (GPGDAT & (~((1<<6)|(1<<2)))) | (1<<6) | (1<<2) ; //GPG6,2 output 0
GPEDAT = (GPEDAT & (~((1<<13)|(1<<11)))) | (0<<13) | (1<<11) ; //GPE13,11 output 0
if( (GPFDAT&(1<< 0)) == 0 ) return 12 ;
else if( (GPFDAT&(1<< 2)) == 0 ) return 9 ;
else if( (GPGDAT&(1<< 3)) == 0 ) return 6 ;
else if( (GPGDAT&(1<<11)) == 0 ) return 3 ;
else return 0xff ;
}
void EINT_Handle( void ) {
GPGCON = (GPGCON & (~((3<<22)|(3<<6)))) | ((0<<22)|(0<<6)) ; //GPG11,3 set input
GPFCON = (GPFCON & (~((3<<4)|(3<<0)))) | ((0<<4)|(0<<0)) ; //GPF2, 0 set input
if(INTPND==BIT_EINT8_23) {
if(EINTPEND&(1<<11))
EINTPEND |= 1<< 11;
if(EINTPEND&(1<<19))
EINTPEND |= 1<< 19;
ClearPending(BIT_EINT8_23);
}
else if(INTPND==BIT_EINT0) {
ClearPending(BIT_EINT0);
} else if(INTPND==BIT_EINT2) {
ClearPending(BIT_EINT2);
}
int key = Key_Scan() ;
if( key != 0xff ) {
uart_printf( "K%d is pressed!\n", key ) ;
GPFDAT = ~(key << 4);
}
SET_KEY_INTERRUPT_REG();
return;
}
文件4:mems
@ 文件 mems
@ 作用:SDRAM 的初始化设置
@ 关于初始化的更多细节,请参考我的前一篇随笔
global memory_setup @ 导出 memory_setup, 使其对链接器可见
memory_setup:
mov r1, #0x48000000
adrl r2, mem_cfg_val
add r3, r1, #134
1:
@ write initial values to registers
ldr r4, [r2], #4
str r4, [r1], #4
cmp r1, r3
bne 1b
mov pc, lr
align 4
mem_cfg_val:
long 0x22111110 @ BWSCON
long 0x00000700 @ BANKCON0
long 0x00000700 @ BANKCON1
long 0x00000700 @ BANKCON2
long 0x00000700 @ BANKCON3
long 0x00000700 @ BANKCON4
long 0x00000700 @ BANKCON5
long 0x00018005 @ BANKCON6
long 0x00018005 @ BANKCON7 9bit
long 0x008e07a3 @ REFRESH
long 0x000000b2 @ BANKSIZE
long 0x00000030 @ MRSRB6
long 0x00000030 @ MRSRB7
文件5:nand_readc
/ 文件 nand_readc
作用:从 Nand Flash 中读取一块数据到 SDRAM 中的指定位置
/
#define NFCONF ((volatile unsigned long )0x4e000000)
#define NFCMD ((volatile unsigned long )0x4e000004)
#define NFADDR ((volatile unsigned long )0x4e000008)
#define NFDATA ((volatile unsigned long )0x4e00000c)
#define NFSTAT ((volatile unsigned long )0x4e000010)
#define NFECC ((volatile unsigned long )0x4e000014)
#define NAND_SECTOR_SIZE 512
#define NAND_BLOCK_MASK 0x1ff
void wait_idle() {
int i;
for (i = 0; i < 50000; ++i) ;
}
int nand_read(unsigned char buf, unsigned long start_addr, int size){
int i, j;
/
detect the argument
/
if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
return -1;
}
/ chip Enable /
NFCONF &= ~0x800;
for (i=0; i<10; i++) {
;
}
for (i=start_addr; i < (start_addr + size); i+=NAND_SECTOR_SIZE) {
NFCMD = 0;
/ Write Address /
NFADDR = i & 0xff;
NFADDR = (i >> 9) & 0xff;
NFADDR = (i >> 17) & 0xff;
NFADDR = (i >> 25) & 0xff;
wait_idle();
for(j=0; j < NAND_SECTOR_SIZE; j++) {
buf++ = (NFDATA & 0xff);
}
}
NFCONF |= 0x800; / chip disable /
return 0;
}
文件6:sdramc
/ 文件 sdramc
作用:循环点 FS2410 开发板上的 D9、D10、D11、D12
四个发光二极管。
/
#define GPFCON ((volatile unsigned long )0x56000050)
#define GPFDAT ((volatile unsigned long )0x56000054)
int main()
{
int i,j;
while(1) {
for (i = 0; i <4; ++i) {
GPFCON = 0x1<<(8+i2);
GPFDAT = 0x0;
// for delay
for(j=0;j<50000;++j) ;
}
}
}
文件7:nandlds
SECTIONS {
first 0x00000000 : { heado memo flasho nand_reado }
second 0x30000000 : AT(4096) { sdramo }
}
文件8:Makefile
sdram:heads flashs mems sdramc
arm-linux-gcc -c -o heado heads
arm-linux-gcc -c -o memo mems
arm-linux-gcc -c -o flasho flashs
arm-linux-gcc -c -o nand_reado nand_readc
arm-linux-gcc -c -o sdramo sdramc
arm-linux-ld -Tnandlds heado memo flasho nand_reado sdramo -o sdram_tmpo
arm-linux-objcopy -O binary -S sdram_tmpo sdram
clean:
rm -f o
rm -f sdram
好了,你把这些文件拷下去,执行make命令就能生成可执行的二进制代码sdram,把sdram烧写到板子上就能运行了。祝你好运
原理
辗转相除法.
当两个数都较大时,采用辗转相除法比较方便.其方法是:
以小数除大数,如果能整除,那么小数就是所求的最大公约数.否则就用余数来除刚才的除数;再用这新除法的余数去除刚才的余数.依此类推,直到一个除法能够整除,这时作为除数的数就是所求的最大公约数.
CMP r0,r1
MOVCC r3,r0
MOVCC r0,r1
MOVCC r1,r3
S0
CMP r1,#0
BEQ S3
S1
CMP r0,r1
BCC S2
SUB r0,r0,r1
B S1
S2 MOV r3,r0
MOV r0,r1
MOV r1,r3
B S0
S3
END
没调试过,不知道程序有什么错误没有。
怎么说呢,不管是用汇编或C语言编程,都与单片机硬件结构有关,程序都要对硬件进行 *** 作,两种单片机在结构上相差较大,程序肯定也差别很大
但用C语言编程时,一些通用数学运算和硬件无关,包括一些对外部器件 *** 作的函数也可以认为与硬件无关,因此许多子程序是有通用性的,因此开发程序时,还是要分层 *** 作,就是将一些与硬件结构有关的 *** 作单独写成子程序,由这些子程序组成高一层函数,硬件变化时,底层函数要修改,而一些上层函数可以不用修改
如读写W25Q16 FLASH 基本 *** 作是发送一个字节数据和接收字一个节数据,这在不同的单片机上是不同的,但实际应用时,我们都是用其上层函数,即向某地址(或某地址开头的空间内)写入一个或多个数据,或者从某地址读出一个或多个数据,这是与单片机硬件无关的
我们将基本 *** 作过程单独编成子程序,那怕只有很少的一两条指令也要这样做,再由这些子程序组成更高级的子程序,即任意地址读写程序,这样硬件平台发生变化时,上层函数就 不用修改了
以上就是关于编写ARM汇编程序,完成两个64位数相加,结果存放在NUM单元全部的内容,包括:编写ARM汇编程序,完成两个64位数相加,结果存放在NUM单元、运用arm写程序的调用stdio.h C:\Keil\ARM\RV31\INC\stdio.h(659): error: #79: expected a type specifie、如何在ARM7上不用 *** 作系统写个最简单的类似HELLO WORLD 的程序呢等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)