Port Registers


1. Port Open-Drain Registers
 : The port open-drain register(PODR), indicates a normal or wired-OR configuration of the port pins.
 : Determines whethehr the corresponding pin is actively driven as an output or is an open-drain driver.
'0' -> The I/O pin is actively driven as an output.
'1' -> The I/O pin is an open-drain driver. As an output, the pin is driven active-low, otherwise it is three-stated.

2. Port Data Register (PDATx)

3. Port Data Direction Register (PDIRx)
 : Direction. Indicates whether a pin is used as an input or an output.
'0' -> The corresponding pin is an input or is bidirectional
'1' -> The corresponding pin is an output.

4. Port Pin Assignment Register (PPAR)
 : Dedicated enable. Indicates whether a pin is a general-purpose I/O or a dedicated peripheral pin.
'0' -> General-purpose I/O. The peripheral functions of the pin are not used.
'1' -> Dedicated peripheral function.

5. Port Special Options Register (PSORx)
 : Special-option. Determines whether a pin configured for a dedicated function uses option 1 or option 2.
'0' -> Dedicated peripheral function. Option 1
'1' -> Dedicated peripheral function. Option 2




 MPC8280 칩의 Intenal Memory Resources는 연속적인 메모리 블럭에 맵핑되어 진다. 그 크기는 256 Kbytes이다. 이 블럭의 위치는 전역 4-Gbyte 물리 메모리 공간에 256 Kbytes 해상도로 매핑되어 지는데, IMMR(Interal Memory Map Register) 레지스터에 명시된 곳에 위치한다. 즉 Base Address를 IMMR 레지스터를 이용하여 직접 지정할 수 있다.

 - 요약 -
어떤 전압의 직류전원에서 다른 전압의 직류전원으로 변환하는 전자회로 장치를 말하며, 넓은 뜻으로는 직류전동기와 직류발전기를 기계적으로 결합한 것도 포함된다. 텔레비전 수상기에서 주로 사용된다.

 - 본문 -

교류의 전압변환은 변압기로 할 수 있으나 직류에서는 그대로는 변압기를 사용할 수 없으므로, 직류전원에서 발진회로()에 의해 전력용량이 큰 교류를 발생시켜 변압기를 통해서 다른 전압의 교류로 변환하고, 다시 정류해서 직류를 얻는 것이 많다.

텔레비전 수상기에서는 브라운관용 고압 직류전원 등에 사용한다. 넓은 뜻으로는 직류전동기와 직류발전기를 기계적으로 결합한 것도 포함된다.


출처 : 네이버 백과사전
 SPI(Serial Peripheral Interface)는 Motorola사에 의하여 개발되었고 지금은 표준화 되어 전세계적으로 널리 사용하는 근거리용 직렬통신 규격으로서, 마스터(master)와 슬레이브(slave) 사이에서 MOSI, MOSO, SCK, SS 등 4개의 통신선을 사용하는 고속 동기식 직렬통신 방식이다.
 SPI 직렬통신은 반드시 1개의 마스터와 1개의 슬레이브 사이에서만 수행된다. 마스터는 송신 데이터와 함께 클럭 신호를 동시에 슬레이브에게 보낸다. 그러면 슬레이브는 이 클럭을 사용하여 데이터를 수신하면서 동시에 자신의 데이터를 마스터에게 보낸다.
 이와 같이 SPI 직렬통신에서는 마스터가 통신의 제어를 주도하며, 항상 송신 동작과 수신 동작이 동시에 수행되어 전이중 통신이 된다. 따라서, 만약 마스터가 슬레이브에게 데이터를 보내는 것이 목적이라면 마스터가 받은 수신 데이터는 무시하면 되며, 반대로 마스터가 슬레이브로부터 데이터를 가져오는 것이 목적이라면 슬레이브에게 더미 데이터를 송신하면서 수신된 데이터를 읽으면 된다.
 SPI 직렬통신 포트에서는 각각의 통신 채널마다 4개씩의 신호가 사용되는데, MOSI(Master-Out Slave-In) 신호는 마스터에서 서 출력되고 슬레이브로 입력되는 신호이고, MISO(Master-In Slave-Out) 신호는 마스터에서 출력되고 슬레이브로 입력되는 신호이며, SCK(Serial Clock) 신호는 마스터에 의하여 구동되는 직렬전송 클럭 신호이다. 또한 SS(Slave Select) 신호는 마스터가 여러개의 슬레이브 디바이스 중에서 마스터와 서로 데이터를 전송할 1개의 소자를 선택하는 칩선택 신호이다.

도무지 이 내용들이 이해가 잘 안가서 모두 AXD로 돌려보고 올립니다.

이해 안가시면 한번 실제로 해보면 좋을 듯합니다.

그럼 이만^^ 퍼가실때 출처 남겨주시길 바랍니다.

작성자 : realdani

***********************************************************************

Decrement Before : 현제 가리키로 있는 곳에서 상위주소(0번지쪽으로) 가리킨후 실행(STMFD)

LDMDB, LDMEA, STMDB, STMFD 는 모두 r13!,{r2-r3}였을 때

만약 r13에 !가 안붙으면 r13의 값은 변하지 않음

LD일 경우,

처음 r13이 #&14일때 마지막은 #&0C를 가리키고,

r2에 Ox000000C번지의 word, r3에는 Ox0000010번지의 word가 들어감


ST일 경우,

처음 r13이 #&14일때 마지막은 #&0C를 가리키고,

r2의 내용이 Ox0000000C번지에, r3의 내용이 Ox00000010번지에 저장됨

**********************************************************************

Decrease Before

LDMDA,LDMFA,STMDA,STMED 모두 r13!,{r2-r3}였을 때

만약 r13에 !가 안붙으면 r13의 값은 변하지 않음

LD인 경우,

처음 r13이 #&14일때 마지막은 #&0C를 가리키고,

r2에는 0x00000010번지의 내용이 들어가고,

r3에는 0x00000014번지의 내용이 들어감,


ST의 경우,

처음 r13이 #&14일때 마지막은 #&0C를 가리키고

r2의 내용이 0x00000010번지에 저장

r3의 내용이 0x00000014번지에 저장


**********************************************************************

Increment Before

STMIB,STMFA,LDMIB,LDMED 모두 r13!,{r2-r3}였을 때

만약 r13에 !가 안붙으면 r13의 값은 변하지 않음

LD일 경우,

처음 r13이 #&14일때 마지막은 #&1C를 가리키고,

r2에 0x00000018번지의 word내용이저장, r3에 0x0000001c의 (내용)word가 저장


ST일 경우,

처음 r13이 #&14일때 마지막은 #&1C를 가리키고,

r2의 내용이 0x00000018번지에, r3의 내용이 0x0000001c에 저장됨



**********************************************************************

Increment After

STMIA,STMEA,LDMIA,LDMFD 모두 r13!,{r2-r3}였을 때

만약 r13에 !가 안붙으면 r13의 값은 변하지 않음

LD일 경우

r13은 0x00000014 -> 0x0000001C로 변함

r2에 Ox00000014번지 내용이 저장

r3에 Ox00000018번지 내용이 저장


ST일 경우

r13은 0x00000014 -> 0x0000001C로 변함

Ox00000014번지에 r2내용이 저장

Ox00000018번지에 r3내용이 저장


출처 : http://blog.naver.com/realdani?Redirect=Log&logNo=100007759984

 Most chips basded on the ARM architecture are comlex on-chip systems, in which most of the hardware modules, whose working statuses are set by softwares, are configurable. Right after the system starts up, before running applications, a block of codes has to be executed to initialize the system. Generally speaking, the initialization should consist of the following steps:
* Interrupt vector table
* Initializing storage system
* Initializing stack
* Initializing the ports and devices that have special requirements
* Initializing excution environment for  user's applications
* Changing the processor mode
* Running main applications

Interrupt vector table
     The interrupt vector table must be located in the space that starts from address “0” and extends for 8X4 byte.
     Every time when an interrupt occurs, the ARM processor forcibly sets the PC pointer to be the address value of the related interrupt type in the vector table. Since each interrupt only takes up the storage space of one character in the vector table, an ARM instruction must be placed to make the program jump to other spaces in the storage, and then the interrupt can be executed.

     The source program of interrupt vector table is as below

AREA Boot ,CODE, READONLY 
ENTRY 
B  ResetHandler 
B  UndefHandler 
B  SWIHandler 
B  PreAbortHandler 
B  DataAbortHandler 

B  IRQHandler 
B  FIQHandler 

     In these codes, the keyword “ENTRY” is used so that these codes might not be regarded as redunancy and therefore optimized by the compiler.

     Make sure to link this code to the address “0” and make it to be the entry point of the whole program.


Initializing storage system
    Storage types and timing configuration:

    Generally, Flash and SRAM are both static storage devices, they can share the same storage interface. While DRAM, due to its specific characters such as dynamic refreshing and address line multiplexing, must be equipped with dedicated storage interface.

 ARM의 의사(Pseudo) 명령은 실제로 ARM의 명령어 디코더에 정의되어 있는 명령이 아니고, 어셈블러에서 지원하는 명령이다.

 

종류

ADR, ADRL, NOP, ALIGN, DCx

 

ADR : 어드레스를 읽어오는 명령

ADR{cond} Rd, <expression>

{cond}는 조건부 실행을 위한 조건을 나타낸다.

Rd는 ARM의 범용 레지스터로 어드레스를 읽어서 저장될 레지스터이다.

<expression>은 읽어올 어드레스의 위치를 나타내며, 라벨 형태로 표현된다.

<expression>에 표현될 수 있는 라벨의 어드레스 범위는, word-aligned로 되어 있는 경우 PC 값을 기준으로 ±1020바이트이다.

 

ADR 명령은 <expression>의 주소 값을 Rd에 저장한다. 실제 동작될 때는 주소 값을 읽어오기 위해 하나의 ADD나 SUB 같은 명령을 사용하여 주소를 계산한다.

예)

start     MOV   r0,   #10

ADR     r4, start            ; start 라벨의 주소를 r4에 저장한다. 실제 동작은 SUB r4, PC, #0xC가 된다.

 

 

 

ADRL : 어드레스를 읽어오는 명령으로 ADR과 유사하지만 보다 광범위한 어드레스 범위를 읽어올 수 있다.

ADR{cond}L Rd, <expression>

{cond}는 조건부 실행을 위한 조건을 나타낸다.

Rd는 ARM의 범용 레지스터로 어드레스를 읽어서 저장될 레지스터이다.

<expression>은 읽어올 어드레스의 위치를 나타내며, 라벨 형태로 표현된다.

<expression>에 표현될 수 있는 라벨의 어드레스 범위는, word-aligned로 되어 있는 경우 PC 값을 기준으로 ±256K바이트이다.

ADR 명령은 <expression>의 주소 값을 Rd에 저장한다. 실제 동작될 때는 주소 값을 읽어오기 위해 하나의 ADD나 SUB 같은 명령을 사용하여 주소를 계산한다.

예)

start     MOV   r0,   #10

ADRL   r4,   start   ; start 라벨의 주소를 r4에 저장한다. 실제 동작은 ADD r4, PC, #0xE800

                            ADD  r4, r4, #0x254 와 같이 사용되어 계산된 주소가 r4에 저장한다.

 

 

 

NOP : NOP 명령이 사용되면 프로세서에 아무런 영향 없이 한 프로세서 사이클을 소비한다.

NOP

NOP는 'MOV r0, r0'로 코드가 생성되어 사용된다.

 

 

ALIGN : 메모리 내의 코드 또는 데이터의 배치를 워드 단위 경계로 정렬한다.

 

DCx : 데이터를 선언한다.

 

DCB : 바이트 데이터(byte data)
DCW : 하프워드데이터(half word data)
DCD : 워드데이터(word data)
DCS : 255바이트까지의 문자열 데이터
DCF : Floating Point Data

예)

DCB    0x12

DCD   0x12345678

DCS   "hello"


출처 : http://blog.naver.com/luis8282?Redirect=Log&logNo=20077512659

[출처] ARM의 의사 명령어|작성자 piao

1. cstartup.s
- Exception Vector Table
- reset_handler / irq_handler 구현
- lowlevel_init으로 분기 : 클럭 설정, 각 인터럽트 소스에 디폴트 핸들러 등록, Watchdog Disable (분석이 더 필요)
- Remap SRAM
- Stack 설정 : Abort, IRQ, SVC 모드일 때 각각 스택 영역 설정
- Data 영역을 RAM에 적재
- Bss 영역을 0으로 초기화

2. gnu 어셈블리 지시어
- .global <symbol> : 심볼을 외부 링크로 제공
- .align {<expression>, {<offset>}} : 다음 명령어의 주소를 <expression> + <offset> 형태로 정렬

ARM은 기본적으로 거의 모든 명령이 4 byte로 구성되어 진다. 4의 배수로 실행 코드를 쪼개서 기계어 하나하나를 해석해 낸다고 보면 된다. 그런데 asm 코드들 중간에 address나 변수 등을 정의할 때 1 byte 2 byte로 정의를 해버리면 4의 배수가 않되는 경우가 발생한다. 이때 오류가 발생할 수 있다. 4의 배수를 맞추기 위하여 0으로 초기화되는 byte들을 추가로 패딩해주는 것이 필요한데 이것을 해주는 directive이다.

- .section <section_name> {, "<flags>"} : 새로운 코드 색션 또는 데이터 색션을 시작한다. 보통 코드 색션 .text, 초기화 된 데이터 색션 .data, 초기화 되지 않은 데이터 색션 .bss를 호출해야 한다. 이것들은 디폴트 플래그를 가지고 있으며 링커는 이 디폴트 이름들을 이해하고 있다.
- .word <word1> {,<word2>}... : ARM asm에서의 DCD와 같이 데이터로 32비트 워드값 목록들을 어셈블리에 삽입한다.

3. cstartup.S 코드
#include "project.h"

#define TOP_OF_MEMORY    (AT91C_ISRAM + AT91C_ISRAM_SIZE)
#define ABT_STACK_SIZE   8*3*4
#define IRQ_STACK_SIZE   8*3*4

#define ARM_MODE_ABT     0x17
#define ARM_MODE_FIQ     0x11
#define ARM_MODE_IRQ     0x12
#define ARM_MODE_SVC     0x13

#define I_BIT            0x80
#define F_BIT            0x40


/* Application startup entry point */
        .globl reset_handler    // reset_handler 심볼을 외부에 보이도록 한다.
        .align 4          // 4 바이트 단위로 정렬하겠다는 의미

.section .vectors    /* .vectors 색션 시작 */
.arm
        
/// 1. start ////////////////////////////////////////////////////////////////////////
/* Exception vectors (should be a branch to be detected as a valid code by the rom */
/* exception vector table */
_exception_vectors:
reset_vector:
        ldr    pc, =reset_handler  /* Reset vector : pc := reselt_handler  0x00000000 */
                  /* reset_handler로 분기됨 */
undef_vector:
        b    undef_vector    /* Undefined Instruction : 미구현  0x00000004 */
swi_vector:
        b    swi_vector      /* Software Interrupt : 미구현     0x00000008 */
pabt_vector:
        b    pabt_vector     /* Prefetch Abort : 미구현       0x0000000C */
dabt_vector:
        b    dabt_vector     /* Data Abort : 미구현         0x00000010 */
rsvd_vector:
        b    rsvd_vector     /* reserved : 예약되어 있는 공간   0x00000014 */
irq_vector:
        b    irq_handler     /* IRQ : read the AIC         0x00000018 */
fiq_vector:
/*------------------------------------------------------------------------------
 *- Function             : fiq_handler
 *- Treatments           : FIQ Interrupt Handler.
 *- Called Functions     : 
 *------------------------------------------------------------------------------*/

fiq_handler:
    b    fiq_handler    /* FIQ : 미구현           0x0000001C */
/* exception vector table end */
/* x86의 경우엔 해당 벡터에 address를 넣어 두면, 인터럽트 발생시에 해당 주소를 가져다가
   PC(Program Counter)에 넣어 주는 일이 발생하지만, ARM7의 경우엔 그냥 해당 벡터로 점프한다.
   예를 들어 IRQ가 발생했다면 다음 순간의 PC값은 0x00000018이 된다. 따라서 해당 벡터 번지에는
   단순히 번지가 들어가는 것이 아니라 점프 명령 같은 것이 들어간다.  */

/// 1. end //////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
    
/*------------------------------------------------------------------------------
 *- Function             : irq_handler
 *- Treatments           : IRQ Controller Interrupt Handler.
 *- Called Functions     : AIC_IVR[interrupt]
 *------------------------------------------------------------------------------*/

irq_handler:
/*- Manage Exception Entry */
/*- Adjust and save LR_irq in IRQ stack */
        sub      lr, lr, #4      /* lr := lr - 4 / 돌아갈 주소 교정 */
        stmfd    sp!, {lr}      /* *sp := lr / 스택에 lr 저장 */
/*- Save r0 and SPSR in IRQ stack */
        mrs      r14, SPSR      /* r14 := SPSR */
        stmfd    sp!, {r0,r14}    /* *sp <- r0, r14 */

/*- Write in the IVR to support Protect Mode */
/*- No effect in Normal Mode */
/*- De-assert the NIRQ and clear the source in Protect Mode */
        ldr      r14, =AT91C_BASE_AIC  /* r14 := AT91C_BASE_AIC */
        ldr      r0 , [r14, #AIC_IVR]  /* r0 := *(r14 + AIC_IVR) */
        str      r14, [r14, #AIC_IVR]  /* *(r14 + AIC_IVR) := r14 */

/*- Enable Interrupt and Switch in Supervisor Mode */
        msr      CPSR_c, #ARM_MODE_SVC

/*- Save scratch/used registers and LR in User Stack */
        stmfd    sp!, {r1-r3, r12, r14}

/*- Branch to the routine pointed by the AIC_IVR */
        mov      r14, pc
        bx       r0

/*- Restore scratch/used registers and LR from User Stack */
        ldmia    sp!, {r1-r3, r12, r14}

/*- Disable Interrupt and switch back in IRQ mode */
        msr      CPSR_c, #ARM_MODE_IRQ | I_BIT

/*- Mark the End of Interrupt on the AIC */
        ldr      r14, =AT91C_BASE_AIC
        str      r14, [r14, #AIC_EOICR]

/*- Restore SPSR_irq and r0 from IRQ stack */
        ldmia    sp!, {r0,r14}
        msr      SPSR_cxsf, r14

/*- Restore adjusted  LR_irq from IRQ stack directly in the PC */
        ldmia    sp!, {pc}^


/// 2. start ////////////////////////////////////////////////////////////////////////
/*------------------------------------------------------------------------------
 *- Function             : reset_handler
 *- Treatments           : Reset Interrupt Handler.
 *- Called Functions     : lowlevel_init
 *                         main
 *------------------------------------------------------------------------------*/

.section .text    /* text 색션 시작 */
reset_handler:
  ldr     pc, =_low_level_init  /* pc := _low_level_init */
                  /* _low_level_init 으로 분기됨 */

/*------------------------------------------------------------------------------
 *- Low level Init is performed in a C function: lowlevel_init
 *- Init Stack Pointer to a valid memory area before calling lowlevel_init
 *------------------------------------------------------------------------------*/

/*- Temporary stack in internal RAM for Low Level Init execution */
_low_level_init:
  ldr      r2, =_lp_ll_init    /* r2 := _lp_ll_init */
        ldmia    r2, {r0, r1}    /* r0 := lowlevel_init, r1 := TOP_OF_MEMORY */
        mov      sp, r1        /* sp := r1    sp := TOP_OF_MEMORY / 스택 위치 설정 */
        mov      lr, pc        /* lr := pc    return address를 저장 */
        bx       r0                 /* Branch on C function (interworking) */
                  /* lowlevel_init으로 분기됨, ARM상태 */
/* #define TOP_OF_MEMORY    ((char *)   0x00200000 + (0x00010000)) */
/// 2. end //////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////

/// 3. start ////////////////////////////////////////////////////////////////////////
/*------------------------------------------------------------------------------
 *- Remap SRAM at 0x0
 *------------------------------------------------------------------------------*/

/* AT91C_MC_RCR : (MC) MC Remap Control Register */
_remap:
        ldr r2, _lp_remap    /* r2 := _lp_remap / r2 := AT91C_MC_RCR */
        mov r0, #AT91C_MC_RCB  /* r0 := AT91C_MC_RCB / AT91C_MC_RCB:1 */
        str r0, [r2]      /* *r2 := r0 / MC_RCR 레지스터에 1을 세팅 */
/* SRAM 영역이 0x00000000으로 리맵핑 된다 */

/*------------------------------------------------------------------------------
 *- Setup the stack for each mode
 *------------------------------------------------------------------------------*/

_stack_init:
  ldr      r2, =_lp_stack_init  /* r2 := _lp_stack_init */
        ldmia    r2, {r0, r1, r2}  /* r0 := TOP_OF_MEMORY / r1 := ABT_STACK_SIZE / r2 := IRQ_STACK_SIZE */
/* #define ABT_STACK_SIZE   8*3*4
   #define IRQ_STACK_SIZE   8*3*4 */


/*- Set up Abort Mode and set ABT Mode Stack */
        msr      CPSR_c, #ARM_MODE_ABT | I_BIT | F_BIT    /* Abort mode로 변경, IRQ/FIQ disable */
        mov      sp, r0      /* sp := r0 / sp := TOP_OF_MEMORY : Abort mode 스택 포인터 설정 */
        sub      r0, r0, r1    /* r0 := r0 - r1 */
/*- Set up Interrupt Mode and set IRQ Mode Stack */
        msr      CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT    /* IRQ mode로 변경, IRQ/FIQ disable */
        mov      sp, r0      /* sp := r0 / sp = TOP_OF_MEMORY - 8*3*4 : IRQ mode 스택 포인터 설정 */
        sub      r0, r0, r2    /* r0 := r0 - r2 */

/*- Enable interrupt & Set up Supervisor Mode and set Supervisor Mode Stack */
        msr      CPSR_c, #ARM_MODE_SVC | F_BIT    /* SVC mode로 변경, FIQ disable */
        mov      sp, r0      /* sp := r0 / sp = TOP_OF_MEMORY - 8*3*4 - 8*3*4 : SVC mode 스택 포인터 설정 */
/* Abort, IRQ, SVC mode들의 스택 포인터들을 설정 */
/* 각 모드 마다 스택 포인터가 각각 독립적으로 존재함으로 각 모드의 스택 영역을 설정한 것이다 */

/*------------------------------------------------------------------------------
 *- Segments initialization
 *------------------------------------------------------------------------------*/

/* Copy the data section in RAM at 0x0000 */
_init_data:
  ldr      r2, =_lp_data      /* r2 := _lp_data */
        ldmia    r2, {r1, r3, r4}  /* r1 := _etext / r3 := _sdata / r4 := _edata */ 
1:
        cmp      r3, r4        /* CPSR flag := r3 - r4 */
        ldrcc    r2, [r1], #4    /* C flag clear 이면 r2 := *r1 / r1 := r1 + 4 */
        strcc    r2, [r3], #4    /* C flag clear 이면 *r3 := r2 / r3 := r3 + 4 */
        bcc      1b          /* C flag clear 이면 1로 분기 */
/* _etext : 코드 영역의 끝을 가리킨다 */
/* _sdata : 데이터 영역의 시작을 가리킨다 */
/* _edata : 데이터 영역의 끝을 가리킨다 */

/* Clear the bss segment */
_init_bss:
  ldr      r2, =_lp_bss      /* r2 := _lp_bss */
        ldmia    r2, {r3, r4}    /* r3 := _sbss / r3 := _ebss */
        mov      r2, #0        /* r2 := 0 */
1:
        cmp      r3, r4        /* CPSR flag := r3 - r4 */
        strcc    r2, [r3], #4    /* *r3 := r2 / r3 := r3 + 4 */
        bcc      1b          /* C flag clear 이면 1로 분기 */
/* bss 영역을 0으로 초기화 */
/* _sbss : bss 영역의 시작을 가리킨다 */
/* _ebss : bss 영역의 끝을 가리킨다 */

/*------------------------------------------------------------------------------
 *- Branch to the main
 *------------------------------------------------------------------------------*/

_branch_main:
        ldr      r0, =main    /* r0 := main */
        mov      lr, pc      /* lr := pc / return address 저장 */
        bx       r0        /* main으로 분기 / ARM 상태 */
/// 3. end //////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////

/*------------------------------------------------------------------------------
 *- Litteral pools
 *------------------------------------------------------------------------------*/

_lp_ll_init:
        .word    lowlevel_init
        .word    TOP_OF_MEMORY              /* Default SVC stack after power up */ 

_lp_remap:
        .word    AT91C_MC_RCR

_lp_stack_init:
        .word    TOP_OF_MEMORY             /* Top of the stack */
        .word    ABT_STACK_SIZE            /* ABT stack size */
        .word    IRQ_STACK_SIZE            /* IRQ stack size */

_lp_bss:
        .word    _sbss
        .word    _ebss

_lp_data:
        .word    _etext
        .word    _sdata
        .word    _edata
















RM7TDMI 레퍼런스 매뉴얼을 살펴보면 다음과 같이 칩코어의 블럭다이어그램을 찾을 수 있다.

 

 

위 그림에서 좌측부분을 보면 디바이스가 프로그램메모리에 접근하기 위해 PC(프로그램 카운터) 정보를 레지스터로부터 가져옴을 볼 수 있는데, 이로부터 resolve하는 어드레스의 크기는 A31:0의 총 32비트임을 보여준다. 즉, SAM7S가 인식하는 메모리의 어드레스 공간은 총 32비트(약 4.3GB)로 구성됨을 알 수 있다. 또한, PC는 32비트의 주소값을 저장해야 하므로, 아래의 그림에서 ARM7TDMI 코어의 동작모드(총 7가지)에 관계없이 레지스터15(R15)를 PC를 위해 사용한다.

 

 

SAM7S는 폰노이만 구조로서, 코어에 내장된 물리적 메모리(플래시 및 SRAM)와 각종 I/O 주변장치등을 매모리맵 I/O 방식(Memory Mapped I/O)으로 맵핑시켜 두었다. (아래 그림 참고)

 

 

 

우선 위의 그림의 좌측에서와 같이, 32비트의 어드레스 공간은 크게 3개의 영역으로 나뉘어져 있다. 하위 256MB는 물리적 메모리를 위한 영역으로 할당되어 있고, 상위 256MB는 주변장치를 위한 I/O 공간으로 할당되어 있다. 이들 사이의 3.5GB 정도의 공간은 미정의상태로서 사용되지 않는다.

 

여기서 하위 256MB의 물리적메모리를 위한 공간을 다시 자세히 살펴보면, 3개의 1MB 영역과 253MB의 미사용영역으로 이루어져 있음을 알 수 있다.(위 그림에서 우측 참고) 여기서, SAM7S의 프로그램메모리(플래시)는 0x10_0000 번지부터 맵핑되어 있으며, 데이터메모리(SRAM)는 0x20_0000 번지부터 맵핑되어 있다. 플래시와 SRAM의 공간은 각각 1MB의 영역만큼 할당되어 있으나, 플래시메모리와 SRAM의 용량은 디바이스마다 그 크기가 정해져 있기 때문에 실제 사용되는 공간은 디바이스의 메모리 용량에 의해 결정된다. (예컨데, SAM7S256의 경우 플래시메모리의 크기가 256KB이므로 256KB의 공간만큼만 사용가능)

 

디바이스가 리셋이 되면 PC는 0x0000_0000 번지로 점프하므로 이 곳은 아무런 메모리도 할당되어 있지 않아 왠지 모순이 되는 것 같다. 그러나, SAM7S에는 메모리 리맵핑(Memory Re-mapping) 기능이 제공되고 있어, 디폴트로 0x10_0000 번지의 플래시영역이 0x00_0000 번지에 리맵핑되어 있다. 따라서, 리셋이 되면 SAM7S는 플래시메모리의 내용을 읽으면서 부팅이 된다. 반면에,MC_RCR이란 레지스터의 RCB비트를 1로 세팅하면 재배치 명령(Remmap Command)이 실행되어 0x20_0000 번지의 SRAM영역이 0x00_0000 번지로 리맵핑되어 SRAM의 내용을 읽으면서 부팅이된다.

 

SAM7S의 플래시메모리는 Single Plane으로 구성되어 있기 때문에, 플래시메모리의 내용을 실행하면서 플래시-라이트를 할 수는 없다. 때문에, SAMBA와 같은 경우 이 리맵핑 기능을 이용하여 SRAM영역으로 SAMBA 코드를 복사한 뒤 SRAM영역에서 부팅하여 플래시메모리에 펌웨어를 라이팅하게 된다.

+ Recent posts