導航:首頁 > 編程語言 > s3c2410匯編代碼

s3c2410匯編代碼

發布時間:2023-05-01 20:16:53

① 設計一個硬體電路,使S3C2410的GPF5引腳控制一個LED燈,編寫對應的對應的匯編代碼,使LED燈不停閃爍,同時

同時什麼?

② 請幫我解釋下這段s3c2410 嵌入式開發中的代碼,是將文件從flash中復制到ram中的程序 #include "def.h" #in

#include "def.h"
#include "2410addr.h"
#include "2410lib.h"
#define ARM_ADDR 0x30000000; /*定義一個地址,應該是復位之後要跳轉到的地址*/
void (*run)(void); /* 一個指針函數 */
void ARM9init(void);
void (CopeFromFlashToRM(U32 * FlashAddr.U32 *ArmAddr,U32 ul);
void (void);
void main(void)
{
run=(void(*)(void)) ARM_ADDR;/* 從ARM_ADDR開始執行,遇到return返回繼續下面的函數 */
ARM9init(); /* 調用函數 */
();
run();
}
CopyFromFlashToRAM(U32 * pulFlashAddr,U32 *pulArmAddr,U32 ul)
/* 將長度為ul 的內容從pulFlashAddr 到 pulArmAddr */
{
U32 *pulSource=pulFlashAddr;/* 參數1的數值傳遞給變數 */
U32 *pulDest=pulArmAddr;
U32 i;
ul/=4; /* ul = ul/4,ul應該是要文件的長度 */
for(i=0;i<ul;i++) /* 重復執行指令 */
{
*pulDest++=*pulSource++; /* 源地址的內容到目的地址 */
}
} /* CopyFromFlashToRAM 函數結束 */
(void)
{
U32 *p1;
U32 *p2;
p1=(U32 * )0x00200000; /* flash 地址*/
p2=(U32 * )0x30000000; /* RAM 地址*/
CopyFromFlashRAM(p1,p2,0x20000); /* 將長度為0x20000 的內容從p1 到 p2 */
}

③ 如何利用s3c2410的gpio實現數據輸入和輸出

這些函數的實現在linux內核源代碼的/arch/arm/plat_s3c24xx/gpio.c中實現,這些函數的具體內容就不在這里介紹了,可以通過源代碼進行查看,這里對這些函數的用法進行解讀:
1.void s3c2410_gpio_cfgpin(unsigned int pin,unsigned int function)
第一個參數pin 是對應的io引腳(這里用宏S3C2410_GPB(5),5不是固定的,看你需要引用的引腳而定)
第二個引腳是設置該引腳的功能的
(由S3C2410_GPIO_INPUT,S3C2410_GPIO_OUTPUT,S3C2410_GPIO_SFN2,S3C2410_GPIO_SFN3這4個宏進行定義)
例如:s3c2410_gpio_cfgpin(S3C2410_GPB(5),S3C2410_GPIO_INPUT)
設置GPB5引腳為輸入。
2.unsigned int s3c2410_gpio_gecfg(unsigned int pin)
作用:返回對應的GPIO的配置情況
例如:pin=s3c2410_GPB5返回GPB5的配置情況
3.void s3c2410_gpio_pullup(unsigned int pin,unsigned int to)
作用:設置相應的的GPIO的上拉電阻。
第一個參數:相應的引腳,和1裡面的用法一致。
第二個參數:設置為1或者0,1表示上拉,0表示不上拉。
4.void s3c2410_gpio_setpin(unsigned int pin,unsigned int to)
作用:將相應的引腳輸出為1或者0。
第一個參數:相應的引腳宏
第二個參數:1或者0
例子:s3c2410_gpio_setpin(S3C2410_GPB(5),1)將引腳GPB5輸出為1
5.unsigned int s3c2410_gpin_getpin(unsigned int pin)
功能:獲取輸入值
參數:相應的引腳
6.unsigned int s3c2410_modify_misccr(unsigned int clear ,unsigned int change)
7.int s3c2410_gpio_getirq(unsigned pin)

④ linux中可以直接訪問S3C2410的ADC寄存器嗎

哥們 我遇到了和你一樣的問題 linux下是不可以直接訪問物理寄存器的 需判培要用到虛擬地址 經
過一兩天的摸索,基本上對在linux控制硬體有了個初步的認識,在linux下控制硬體和在無操作系統下控制硬體的不同主要在於硬體的地址不一樣,在
linux下要使用va(虛擬地址),而在無操作系統下可以直接使用硬體的pa(物理地址),當然,在這里還需要進一步的摸索和求證,是不是在編譯內核時
去掉某個模塊後,可以在linux下直接使用pa,顯然,我這兩天的摸索是基於無法直接使用pa的。

在linux-2.6.8.1/include/asm-arm/arch-s3c2410/map.h中定義了大部分硬體的物理地址和他們的虛擬地址。
在光碟的用戶手冊上,um_s3c2410x_rev11_012003.pdf中也就是所謂的datasheet中,同樣對硬體的物理地址進行了說明。
pa與va 不同在於基址,他們的偏移量是一樣的。

現以gpio F為例說明,gpio 的pa 基址(ba)為配山0x56000000,GPFCON pa為0x56000050
即:可見偏移量為0x50,而我們在看看GPFCON va ,vaba :0xf0e0 0000,va:0xf0e0
0050,偏移量為0x50,現在,一切都變的明了起來了。我們只要知道了vaba,和他的偏移量,我們就能計算出va,從而,就可以對其進行操作了。這
樣,也就有了兩個問題,1:如何獲取vaba:在linux-2.6.8.1/include/asm-arm/arch-s3c2410/map.h中
有定義,在這里我們還有必要對map.h的地址的定義進行一下的說明

計算機中,分級分層的思想隨處可見,這也是計算機上的一個基本的思想和思路。在這里,也不例外。用培沖中俺老趙的話說就是分了三級,三級偏移,黨中央的ba為
0xf0000000,偏移一下到省里,0xf0e0 0000 (以GPIO為例),再次偏移到基層,0xf0e0 0050
(以GPFCON為例)。哈哈,現在,就可以在linux 下通過0xf0e0 0050來對GPFCON 寄存器來進行操作了。

現把源碼中的實現過程摘出如下:(當然,我們具體實現時,完全可以事先計算出va,過程如上)

#define S3C2410_ADDR(x) (0xF0000000+(x))//map.h
//linux下所有硬體的黨中央vaba:0xF0000000
#define S3C2410_VA_GPIO S3C2410(0X00E00000)//map.h

//GPIO的偏移量0x00E00000,加上這個偏移量後,到了GPIO器件

#define S3C2410_GPIOREG(x) ((x)+S3C2410_VA_GPIO)
#define S3C2410_GPFCON S3C2410_GPIOREG(0x50)//regs-gpio.h

//GPFCON寄存器的偏移量0x50,加上這個偏移量後,到了具體的寄存器,可以對硬體進行操作了

#define S3C2410_GPFDAT S3C2410_GPIOREG(0x54)//regs-gpio.h
#define S3C2410_GPFUP S3C2410_GPIOREG(0x58)//regs-gpio.h

2:第二個問題就是偏移量的獲取,其實這個問題已經在1中解決了。呵呵,去查具體硬體的頭文件就行了。

⑤ 求助 s3c2410把nandflash中的程序搬到sdram中並運行的程序

你可以自己寫一個匯編的程序,把Nand Flash 中的程序搬到SDRAM中。因為S3C2410有Nor Flash和Nand Flash有兩種啟動方式,所以在搬移過程中略有不同。如果用Nand Flash啟動可以使用下面碰晌的代碼,至於Nor Flash啟動就相對簡單了,你可以自己研究一下。
文件1.head.s
@ 文件 head.s
@ 作用:關閉看門狗、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:flash.s
@ 文件 flash.s
@ 作用:設置 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, #0x0a
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_read.c
ldr r0,=0x30000000
mov r1,#4096
mov r2,#1024
bl nand_read

@ return
mov pc,r10
文件3:interrupt.c
/罩滾*
* 文件 interrupt.c
* 作用:設置並響應按鍵中斷
*/
#include "printf.h"

#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:mem.s
@ 文件 mem.s
@ 作用:SDRAM 的初始化設置
@ 關於初始化的更多細節,請參考我的前一篇隨筆
.global memory_setup @ 導出 memory_setup, 使其對鏈接器可見
memory_setup:
mov r1, #0x48000000
adrl r2, mem_cfg_val
add r3, r1, #13*4
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_read.c
/* 文件 nand_read.c
* 作用:從 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:sdram.c
/* 文件 sdram.c
* 作用:循環點 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+i*2);
GPFDAT = 0x0;

// for delay
for(j=0;j<50000;++j) ;
}
}
}
文件7:nand.lds
SECTIONS {
first 0x00000000 : { head.o mem.o flash.o nand_read.o }
second 0x30000000 : AT(4096) { sdram.o }
}
文件8:Makefile
sdram:head.s flash.s mem.s sdram.c
arm-linux-gcc -c -o head.o head.s
arm-linux-gcc -c -o mem.o mem.s
arm-linux-gcc -c -o flash.o flash.s
arm-linux-gcc -c -o nand_read.o nand_read.c
arm-linux-gcc -c -o sdram.o sdram.c
arm-linux-ld -Tnand.lds head.o mem.o flash.o nand_read.o sdram.o -o sdram_tmp.o
arm-linux-obj -O binary -S sdram_tmp.o sdram
clean:
rm -f *.o
rm -f sdram
好了,你把這些文件拷下去,執行make命令就能生成可執行的二進制代碼sdram,把sdram燒寫到板子上就能運行了。祝你好運

⑥ S3C2410中斷控制器實驗,在參考代碼基礎上做修改,修改中斷控制器各個寄存器的配置,完成初始化函數編寫

STM32的EXTI控制器支持19 個外部中斷/ 事件請求。每個中斷設有狀態位,每個中斷/ 事件都有獨立的觸發和屏蔽設置。
STM32的19個外部中斷對應著19路中斷線,分別是EXTI_Line0-EXTI_Line18:
線0~15:對應外部 IO口的輸入中斷。
線16:連接到 PVD 輸出。
線17:連接到 RTC 鬧鍾事件。
線18:連接到 USB 喚醒事件。
觸發方式:STM32 的外部中斷是通過邊沿來觸發的,不支持電平前塵觸發。
外部中斷分組:STM32 的每一個GPIO都能配置成一個外部中斷觸發源,STM32 通過根據引腳的序號不同將眾多中斷觸發源分成不同的組,比如:PA0,PB0,PC0,PD0,PE0,PF0,PG0為第一組,那麼依此類推,我們能得出一共有16 組,STM32 規定,每一組中同時只能有一個中斷觸發源工作,那麼,最多工作的也就是16個外部中斷。

寄存器組
EXTICR寄存器組,總共有4 個,因為編譯器的寄存器組都是從0 開始編號的,所以EXTICR[0]~ EXTICR[3],對應《STM32參考手冊》里的 EXTICR1~ EXTICR 4(查了好久才搞明白這個數組的含義!!)。每個 EXTICR只用了其低16 位。
EXTICR[0] ~EXTICR[3]的分配如下:

EXTI寄存器的結構體:
typedef struct
{
vu32 IMR;
vu32 EMR;
vu32 RTSR;
vu32 FTSR;
vu32 SWIER;
vu32 PR;
} EXTI_TypeDef;
IMR:中斷屏蔽寄存器
這是一個 32 寄存器。但是只有前 19 位有效。當位 x 設置為1 時,則開啟這個線上的中斷,否則關閉該線上的中斷。
EMR:事件屏蔽寄存器
同IMR ,只是該寄存器是針對事件的屏蔽和開啟。
RTSR:上升沿觸發選擇寄存器
該寄存器同IMR ,也是一個32為的寄存器,只有前 19位有效。位 x 對應線x 上的上升沿觸發,如果設置為 1 ,則是允許上升沿觸發中斷/ 事件。否則,不允許。
FTSR:下降沿觸發選擇寄存器
同 PTSR,不過這個寄存器是設置下降沿的。下降沿和上升沿可以被同時設置,這樣就變成了任意電平觸發了。
SWIER:軟體中斷事件寄存器
通過向該寄存器的位x 寫入 1 ,在未設置 IMR 和EMR的時候,將設置PR中相應位掛起。如果設置了IMR 和EMR時將產生一次中斷。被設置的SWIER位,將會在PR中的對應位清除後清除。
PR:掛起寄存器
0 ,表示對應線上沒有發生觸發請求。
1,表示外部中斷線上發生了選擇的邊沿事件。通過向該寄存器的對應位寫入 1 可喊禪以清除該位。
在中斷服務函數裡面經常會要向該寄存器的對應位寫1 來清除中斷請求。
Ex_NVIC_Config基本是按照這個結構來編寫的
中斷配置步驟
STM32的每個IO口都可以作為中斷輸入,這點很好用。要把IO口作為外部中斷輸入,有以下幾個步驟:
1)初始化IO口為輸入。
這一步設置你要作為外部中斷輸入的IO口的狀態,可以設置為上拉/下拉輸入,也可以設置為浮空輸入,但浮空的時候外部一定要帶上拉,或者下拉電阻。否則可能導致中斷不停的觸發。在干擾較大的地方,就算使用了上拉/下拉,也建議使用外部上拉/下拉電阻,這樣可以一定程度防止外部干擾帶來的影響。
2)開啟IO口復用時鍾慧滲禪,設置IO口與中斷線的映射關系。
STM32的IO口與中斷線的對應關系需要配置外部中斷配置寄存器EXTICR,這樣我們要先開啟復用時鍾,然後配置IO口與中斷線的對應關系。才能把外部中斷與中斷線連接起來。
3)開啟與該IO口相對的線上中斷/事件,設置觸發條件。
這一步,我們要配置中斷產生的條件,STM32可以配置成上升沿觸發,下降沿觸發,或者任意電平變化觸發,但是不能配置成高電平觸發和低電平觸發。這里根據自己的實際情況來配置。同時要開啟中斷線上的中斷,這里需要注意的是:如果使用外部中斷,並設置該中斷的EMR位的話,會引起軟體模擬不能跳到中斷,而硬體上是可以的。而不設置EMR,軟體模擬就可以進入中斷服務函數,並且硬體上也是可以的。建議不要配置EMR位。
4)配置中斷分組(NVIC),並使能中斷。
這一步,我們就是配置中斷的分組,以及使能,對STM32的中斷來說,只有配置了NVIC的設置,並開啟才能被執行,否則是不會執行到中斷服務函數裡面去的。關於NVIC的詳細介紹,請參考前面章節。
5)編寫中斷服務函數。
這是中斷設置的最後一步,中斷服務函數,是必不可少的,如果在代碼裡面開啟了中斷,但是沒編寫中斷服務函數,就可能引起硬體錯誤,從而導致程序崩潰!所以在開啟了某個中斷後,一定要記得為該中斷編寫服務函數。在中斷服務函數裡面編寫你要執行的中斷後的操作。
實驗4--外部中斷實驗exit.c函數如下:
[cpp] view plain
#include "exti.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "usart.h"

//外部中斷0服務程序
void EXTI0_IRQHandler(void)
{
delay_ms(10);//消抖
if(KEY2==1) //按鍵2
{
LED0=!LED0;
LED1=!LED1;
}
EXTI->PR=1<<0; //清除LINE0上的中斷標志位
}

//外部中斷15~10服務程序
void EXTI15_10_IRQHandler(void)
{
delay_ms(10); //消抖
if(KEY0==0) //按鍵0
{
LED0=!LED0;
}else if(KEY1==0)//按鍵1
{
LED1=!LED1;
}
EXTI->PR=1<<13; //清除LINE13上的中斷標志位
EXTI->PR=1<<15; //清除LINE15上的中斷標志位
}
//外部中斷初始化程序
//初始化PA0,PA13,PA15為中斷輸入.
void EXTIX_Init(void)
{
RCC->APB2ENR|=1<<2; //使能PORTA時鍾
JTAG_Set(JTAG_SWD_DISABLE);//關閉JTAG和SWD

GPIOA->CRL&=0XFFFFFFF0;//PA0設置成輸入
GPIOA->CRL|=0X00000008;
GPIOA->CRH&=0X0F0FFFFF;//PA13,15設置成輸入
GPIOA->CRH|=0X80800000;
GPIOA->ODR|=1<<13; //PA13上拉,PA0默認下拉
GPIOA->ODR|=1<<15; //PA15上拉

Ex_NVIC_Config(GPIO_A,0,RTIR); //上升沿觸發
Ex_NVIC_Config(GPIO_A,13,FTIR);//下降沿觸發
Ex_NVIC_Config(GPIO_A,15,FTIR);//下降沿觸發

MY_NVIC_Init(2,2,EXTI0_IRQChannel,2); //搶佔2,子優先順序2,組2
MY_NVIC_Init(2,1,EXTI15_10_IRQChannel,2);//搶佔2,子優先順序1,組2
}
其中的兩個函數:Ex_NVIC_Config(GPIO_A,0,RTIR);和MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);這兩個函數都是在sys.c里定義,分別完成了步驟2、3、4.函數原型如下:
[cpp] view plain
//外部中斷配置函數
//只針對GPIOA~G;不包括PVD,RTC和USB喚醒這三個
//參數:GPIOx:0~6,代表GPIOA~G;BITx:需要使能的位;TRIM:觸發模式,1,下升沿;2,上降沿;3,任意電平觸發
//該函數一次只能配置1個IO口,多個IO口,需多次調用
//該函數會自動開啟對應中斷,以及屏蔽線
//待測試...
void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM)
{
u8 EXTADDR;
u8 EXTOFFSET;
EXTADDR=BITx/4;//得到中斷寄存器組的編號
EXTOFFSET=(BITx%4)*4;

RCC->APB2ENR|=0x01;//使能io復用時鍾

AFIO->EXTICR[EXTADDR]&=~(0x000F<<EXTOFFSET);//清除原來設置!!!
AFIO->EXTICR[EXTADDR]|=GPIOx<<EXTOFFSET;//EXTI.BITx映射到GPIOx.BITx

//自動設置
EXTI->IMR|=1<<BITx;// 開啟line BITx上的中斷
//EXTI->EMR|=1<<BITx;//不屏蔽line BITx上的事件 (如果不屏蔽這句,在硬體上是可以的,但是在軟體模擬的時候無法進入中斷!)
if(TRIM&0x01)EXTI->FTSR|=1<<BITx;//line BITx上事件下降沿觸發
if(TRIM&0x02)EXTI->RTSR|=1<<BITx;//line BITx上事件上升降沿觸發
}
這個函數完成了兩個步驟:
2、開啟IO口復用時鍾,設置IO口與中斷線的映射關系
3、開啟與該IO口相對的線上的中斷/時間,設置觸發條件
[cpp] view plain
//設置NVIC
//NVIC_PreemptionPriority:搶占優先順序
//NVIC_SubPriority :響應優先順序
//NVIC_Channel :中斷編號
//NVIC_Group :中斷分組 0~4
//注意優先順序不能超過設定的組的范圍!否則會有意想不到的錯誤
//組劃分:
//組0:0位搶占優先順序,4位響應優先順序
//組1:1位搶占優先順序,3位響應優先順序
//組2:2位搶占優先順序,2位響應優先順序
//組3:3位搶占優先順序,1位響應優先順序
//組4:4位搶占優先順序,0位響應優先順序
//NVIC_SubPriority和NVIC_PreemptionPriority的原則是,數值越小,越優先
//CHECK OK
//100329
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)
{
u32 temp;
u8 IPRADDR=NVIC_Channel/4; //每組只能存4個,得到組地址
u8 IPROFFSET=NVIC_Channel%4;//在組內的偏移
IPROFFSET=IPROFFSET*8+4; //得到偏移的確切位置
MY_NVIC_PriorityGroupConfig(NVIC_Group);//設置分組
temp=NVIC_PreemptionPriority<<(4-NVIC_Group);
temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
temp&=0xf;//取低四位

if(NVIC_Channel<32)NVIC->ISER[0]|=1<<NVIC_Channel;//使能中斷位(要清除的話,相反操作就OK)
else NVIC->ISER[1]|=1<<(NVIC_Channel-32);
NVIC->IPR[IPRADDR]|=temp<<IPROFFSET;//設置響應優先順序和搶斷優先順序
這個函數完成了:
4、配置中斷分組(NVIC),並使能中斷
補充
在實驗18--觸摸屏實驗中,中斷初始化沒有調用這個函數,它是這樣配置的:
[cpp] view plain
MY_NVIC_Init(2,0,EXTI1_IRQChannel,2);
RCC->APB2ENR|=0x01; //使能io復用時鍾
AFIO->EXTICR[0]|=0X0020; //EXTI1映射到PC1(這句原子的程序里注釋錯了搞成了EXTI13)
EXTI->IMR|=1<<1; //開啟line1上的中斷
EXTI->EMR|=1<<1; //不屏蔽line1上的事件
EXTI->FTSR|=1<<1; //line1上事件下降沿觸發
RCC->APB2ENR|=0x01; 這一句是開啟復用時鍾,什麼時候需要開啟復用時鍾?手冊有這樣一段:

也就是說只要操作EVCR、EXTICRX、MAPR的時候,就必須開啟復用功能時鍾,即當你要配置stm32的事件輸出、外部中斷、重映射的時候.就必須開啟復用時鍾。
AFIO->EXTICR[0]|=0X0020; //EXTI1映射到PC1
這一句設置中斷映射,如上文所說EXTICR[0]~ EXTICR[3] 對應 EXTICR1~ EXTICR4,舉例:
AFIO->EXTICR[3] &= 0xFFFFFF0F;
AFIO->EXTICR[3] |= 0xFFFFFF0F; //EXTI13映射到PA13,0(即0x00)代表A口,1(即0x01)代表B口,依次類推,6(即0x0110)代表G口.
AFIO->EXTICR[3] &= 0xFFFFFF0F;
AFIO->EXTICR[3] |= 0xFFFFFF2F; //EXIT13映射到PC13,2(0x0010)代表C口
外部中斷函數不能進入的原因分析分析,可能為以下幾個方面:
1)GPIO或者AFIO的時鍾沒有開啟;
2)GPIO和配置的中斷線路不匹配;
3)中斷觸發方式和實際不相符合;
4)中斷處理函數用庫函數時,寫錯,經常可能出現數字和字母之間沒有下劃線;
5)外部中斷是沿觸發,有可能檢測不到沿,比如中斷線是低電平(浮空輸入),觸發是下降沿觸發,可能會出現一直是低電平,高電平的時候是一樣的情況,電平持續 為高電平;
6)沒有用軟體中斷來觸發外部中斷,調用函數EXTI_GenerateSWInterrupt;,因為軟體中斷先於邊沿中斷處理。

⑦ 嵌入式是如何做到將某功能植入晶元的

用一片或少數幾片大規模集成電路組成的中央處理器。
這些電路執行控制部件和算術邏輯部件的功能。微處理器與傳統的中央處理器相比,具有體積小,重量輕和容易模塊化等優點。

一) 微處理器的基本組成部分有:寄存器堆、運算器、時序控制電路,以及數據和地址匯流排。微處理器能完成取指令、執行指令,以及與外界存儲器和邏輯部件交換信息等操作,是微型計算機的運算控制部分。它可與存儲器和外圍電路晶元組成微型計算機。但這些專用操作系統都是商業化產品,其高昂的價格使許多低端產品的小公司望而卻步;而且,源代碼封閉性也大大限制了開發者的積極性。

二) 而Linux的開放性,使得許多人都認為Linux非常適合多數Intemet設備。Linux操作系統可以支持不同的設備和不同的配置。

Linux對廠商不偏不倚,而且成本極低,因而很快成為用於各種設備的操作系統。嵌入式linux是大勢所趨,其巨大的市場潛力與醞釀的無限商機必然會吸引眾多的廠商進入這一領域。
三) 嵌入式linux操作系統
Linux是一類Unix計算機操作系統的統稱。Linux操作系統的內核的名字也是"Linux".Linux操作系統也是自由軟體和開放源代碼發展中最著名的例子。嚴格來講,Linux這個詞本身只表示Linux內核,但在實際上人們已經習慣了用Linux來形容整個基於Linux內核,並且使用GNU工程各種工具資料庫的操作系統。

Linux得名於計算機業余愛好者LinuSTorvalds.Linux的程序源碼全部公開,任何人都可以根據自己的需要裁剪內核,以適應自己的系統。

linux移植到ARM920T內核的s3c2410處理器晶元為例,介紹了嵌入式linux內核的裁剪以及移植過程,文中介紹的基本原理與方法技巧也可用於其它晶元。

四) 內核移植過程

1 ,建立交叉編譯環境
在一種計算機環境中運行的編譯程序,能編譯出在另外一種環境下運行的代碼,我們就稱這種編譯器支持交叉編譯。
這個編譯過程就叫交叉編譯。簡單地說,就是在一個平台上生成另一個平台上的可執行代碼。這里需要注意的是所謂平台,實際上包含兩個概念:體系結構(Architecture)、操作系統(Operating System)。

2,同一個體系結構可以運行不同的操作系統;同樣,同一個操作系統也可以在不同的體系結構上運行。舉例來說,我們常說的x86 Linux平台實際上是Intel x86體系結構和Linux for x86操作系統的統稱;而x86 WinNT平台實際上是Intel x86體系結構和Windows NT for x86操作系統的簡稱。

3,交叉編譯交叉編譯呢,簡單地說,就是在一個平台上生成另一個平台上的可執行代碼。這里需要注意的是所謂 平台,實際上包含兩個概念:體系結構(Architecture)、操作系統(Operating System)。同一個體系結構可以運行不同的操作系統;同樣,同一個操作系統也可以在不同的體系結構上運行。

4,交叉編譯器完整的安裝涉及到多個軟體安裝,最重要的有binutils、gcc、glibc三個。其中,binutils主要用於生成一些輔助工具;gcc則用來生成交叉編譯器,主要生成arm-linux-gcc交叉編譯工具;glibc主要是提供用戶程序所使用的一些基本的函數庫。

5,自行搭建交叉編譯環境通常比較復雜,而且很容易出錯。本文使用的是開發板自帶的交叉編譯器,即CROSS一3.3.4.交叉編譯器,該編譯只需將光碟中的arm-linux一3.3.4.bar.bz2用tar ixvf arm-linux一3.3.4.bar.bz2命令解壓到/usr/local/arm下即可。

五) 修改Makefile
Makefile文件Makefile一個工程中的源文件不計數,其按類型、功能、模塊分別放在若干個目錄中,makefile定義了一系列的規則來指定,哪些文件需要先編譯,哪些文件需要後編譯,哪些文件需要重新編譯,甚至於進行更復雜的功能操作,因為makefile就像一個Shell腳本一樣,其中也可以執行操作系統的命令。

修改內核目錄樹根下的Makefile時,可先指明交叉編譯器。設計時,可向Makefile中添加如下內容:
ARCH ?=arm
CROSS_COMPILE?=arm-linux-然後設置PATH環境變數,使其可以找到其交叉編譯工具鏈,然後運行vi~/.bashrc,再添加如下內容:
export PATH=/usr/local/arln-linux一3.4.4/bin:$PATH

六) 設置Flash分區

此處一共要修改3個文件,分別如下:
(1)在arch/arm/machS3C2410/devs.c文件中添加如下內容:
#include
#include
#include
然後再建立Nand flash分區表;同時建立Nand F1ash晶元支持,最後加入Nand FLASH晶元並支持到Nand Flash驅動。

另外,還要修改arch/arm/machs3c2410/devs.C文件中的s3c_device_nand結構體變數,同時添加對dev成員的賦值。

(2)指定啟動時初始化
內核啟動時,可以依據對分區的設置進行初始配置,然後修改arch/am4mach-s3c2410/machsmdk2410.e文件下的smdk2410_devices[],指明初始化時包括在前面所設置的flash分區信息,並添加如下語句:
&s3c_device_nand,

(3)禁止Flash ECC校驗

內核一般都是通過UBOOT寫到Nand Flash的。UBOOT則通過軟體ECC演算法來產生ECC校驗碼,這與內核校驗的ECC碼不一樣,內核中的ECC碼是由S3C2410中Nand Flash控制器產生的。所以,這里選擇禁止內核ECC校驗。

修改drivers/mtd/nand/s3c2410.C 下的s3c2410_nand_init_chip ()函數,可在該函數體最後加上如下一條語句:
chip->eccmode=NAND_ECC_NONE;

⑧ S3C2410A復位後執行的第一條指令存放首地址是什麼

下面是我個人的一點認知,希望對你有幫助。
1、從nor flash啟動則存在地址0x00000000,也就是說要用FLASH做程序啟動,FLASH必須放BANK0,且地址從0x0開始,你可以直接在nor flash 中運行程序,也可把程序用自己寫在啟動代碼拷入SDRAM運行。
2、若從NAND FLASH啟動,則存放在NAND FLASH的開始區域,上電後系統會硬拷貝到內部的4KBRAM運行。
下面是我寫的一個直接從nor啟動的程序代碼:
只有init.s與led.c兩個文件,我調試過,運行正常
ADS環境參數設置中把:RO-BASE設為0x00000000,RW-BASE設為0x30000000(根據具體硬體來定)

image entry point 設為:0x00000000,

設置好的合令為:-info totals -entry 0x00000000 -ro-base 0x00000000 -map -symbols -rw-base 0x31000000 -first init.o(Init) -xref
init.s文件內容:
AREA Init,CODE,READONLY ;該偽指令定義了一個代碼段,段名為Init,屬性只讀
ENTRY ;程序的入口點標識
ResetEntry
ldr sp,=0x31000000 ;定義堆棧指針(根據具體硬體來定)
IMPORT Main ;聲明主函數Main
BL Main ;調用主函數
END ;程序結束符

led.C代碼:
/*led.c*/
/*用GPB5~GPB8控制四個發光二極體閃爍*/
#define GPBCON (*(volatile unsigned *)0x56000010) //Port B control
#define GPBDAT (*(volatile unsigned *)0x56000014) //Port B data
#define GPBUP (*(volatile unsigned *)0x56000018) //Pull-up control B
void Main(void)
{
int i;
GPBCON &= ~((0x3<<10) | (0x3<<12) | (0x3<<14) | (0x3<<16
GPBCON |= (0x1<<10) | (0x1<<12) | (0x1<<14) | (0x1<<16); //GPBCON=0x00015400;
while (1)
{
GPBDAT=0x061F;
for(i=0;i<10000;i++);
GPBDAT=0x07FF;
for(i=0;i<10000;i++);
}
}

閱讀全文

與s3c2410匯編代碼相關的資料

熱點內容
桌面雲配置文件分離 瀏覽:505
iphone5如何升級4g網路 瀏覽:5
團購是在哪個app 瀏覽:897
打開多個word文檔圖片就不能顯示 瀏覽:855
騰訊新聞怎麼切換版本 瀏覽:269
app安裝失敗用不了 瀏覽:326
桌面文件滑鼠點開會變大變小 瀏覽:536
手機誤刪系統文件開不了機 瀏覽:883
微信兔子甩耳朵 瀏覽:998
android藍牙傳文件在哪裡 瀏覽:354
蘋果6s軟解是真的嗎 瀏覽:310
c語言代碼量大 瀏覽:874
最新網路衛星導航如何使用 瀏覽:425
以下哪些文件屬於圖像文件 瀏覽:774
zycommentjs 瀏覽:414
確認全血細胞減少看哪些數據 瀏覽:265
文件有哪些要求 瀏覽:484
cad打開時會出現兩個文件 瀏覽:65
什麼是轉基因網站 瀏覽:48
手柄設備有問題代碼43 瀏覽:921

友情鏈接