;

연암과 다산 사이

블로그 이미지
문패 달고 보니까 넘 커다란 이름이네요 ^^; 행여 고래 등 사이에 끼인 새우가 되지 않기를 ㅎㅎ 연암은 고미숙님의 '열하일기, 웃음과 역설의 유쾌한 시공간'에서, 다산은 '다산연구소' (http://www.edasan.org)에서 삘 받았슴다. 잼난 놀이터가 되었으면... ^^
by 명랑만화
  • Total hit
  • Today hit
  • Yesterday hit
02-08 00:04

http://ya-n-ds.tistory.com/3103 : Embedded with ARM (1) ARM Register, Compile, ELF
http://ya-n-ds.tistory.com/3137 : Embedded with ARM (2) Scatter file, Map file, Makefile
http://ya-n-ds.tistory.com/3181 : Embedded with ARM (3) Assembly

 

# Referece : 'Embedded Recipes'(히언, 코너북)
http://recipes.egloos.com/
https://www.cs.utexas.edu/users/fussell/courses/cs429h/lectures/Lecture_20-429h.pdf : Linking

 

 

<< Ch.5 Software Vignetting >>


< Context & AAPCS(ARM Architecture Procefure Call Standard) >
- Context : 현재 CPU에 대한 모든 정보 ( R0~R12, R13-SP, R14-LR, R15-PC, CPSR )
  cf. CPSR (Current Program Satus Registe) : bit[31:28] NZCV, bit[7:6] IF, bit[5:0] mode
  cf. R0~R3 can be used for Return value and Passing parameters of the called function
  cf. Call 'Leaf' function (w/o another fucntion call inside) : 'Move pc, lr' is enough to get back
  cf. RTOS Context Switching : Complete Context Back-up and Restoration

 

- Example
void ContextDaugher();
void ContextMother(void);
{
 code_before_ContextDaughter; // 0x1500
  // Registers(among R0~R12) which will be used(determined in Compile) in 'ContextDauger' are pushed into stack
  // SP is changed based on the stack
  // R14 <= 0x1504 because this code is to be executed after 'ContextDaughter'
  // R14 is pushed into stack ( preparation for the case in which ContextDaughter may call another function )
  // push {Rk~Rn, R14}
  // CPSR is backed-up only for Exception case
 ContextDaugher();  // 0x1502
  // pop {Rk~Rn, PC} // (Pushed) R14 is back to R15(PC)
 code_after_ContextDaughter; // 0x1504
}

 

< Pointer, Array, Double Pointer >
* Pointer : word-size data type
 int* address
 -> address : the address where the integer type data exists
 -> *address : the data which is specified by the address and whose type and size is integer 

 

 char *text="Recipes";  // text is the address where 'R' exists
 // *(text++) -> 'e' - if text is 0x100 then (text++) indicates 0x101
 text[1]; // 'e'
 *(text+1); // 'e' 

 

 char *pointer;
 char array[3] = {0,1,2}; 

 

 pointer=array;
 pointer=&array[0]; // Same meaning 

 

 // Deliver the pointer as arguments
 void swap(int* pa, int* pb)
 {
   // (&pa)[pa] -> (pa)[*pa], (&pb)[pb] -> (pb)[*pb]
   int tmp;  // (&tmp)[tmp]
   tmp = *pa;
   *pa = *pb;
   *pb = temp;
   return;
 } 

 

 int process(void)
 {
   int a,b;
   int a=1;  // (&a)[1]
   int b=2;  // (&b)[2]
   swap(&a, &b);  // &a -> pa, &b -> pb
 } 

 

 // Example : Address, Data of Pointer
 void main()
 {
   int temp;  // (&temp)[temp]
   int* p1;   // (&p1)[p1] -> (p1)[*p1]
   int** pp1;  // (&pp1)[pp1] -> (pp1)[*pp1] -> (*pp1)[**pp1]

   p1=&temp;
   pp1=&p1;  // compile error with 'pp1=&temp' because pp1 shall point the pointer-type variable
   *p1 = 10;  // 'temp' will be set as '10'
 }

 // Double pointer usage
 void gettag(char** ptag)
 {
   *ptag = (char *)malloc(40);
   strncpy(*ptag,"pointer tag",sizeof(char)*40);
 } 

 
 void process()
 {
   char *tag;
   gettag(&tag);
   free(tag);
 }

 

 

< struct, typedef, PACKED >
* struct : generation of structure-type variable
struct customer{
char* name;
int height;
int weight;
}
=> customer Kim;  // Kim is a 'custom'-type variable

 

struct Structure_Type_Name { declare multiple variables } Variable_name(s);

 

* typedef : generation of a new data type
tyepdef 'variable type' Type_Name;

 

typedef struct customer{
char* name;
int height;
int weight;
} Type_Name; 
// Type_Name cannot be a variable (e.g. *kim, kim[100], etc.)
// Instead, 'Type_Name Variable_Name;' is used. ( e.g. Type_Name *kim, Type_Name kim[100], etc. )

 

typedef enum{
 START,
 WALK,
 RUN
} customer_activity_type;
customer_activity_type activity;

 

switch(acitvity)
{
  case START;
    ...
  case RUN;
    ...
}

 

 

< Stack, Heap >
- Stack : LIFO(Last In First Out) structure, push(In), pop(Out), History function
e.g. command history, command abortion(ctrl -z),
cf. implemenation : push(0x1);, push(0x2);, push(0x3); -> pop() //0x3 올라옴, pop() // 0x2 올라옴, pop() // 0x1 올라옴

 

- Heap : Dynamic Allocation ( Linked List, Tree structure ) via alloc, free
e.g. Method to get the size of Arrays whose size is unknown

 

void HEAP (int n)
{
  int *p;
  p=(int *)malloc((sizeof(int))*n);
  ... }
=> *p, *(p+1), *(p+2), ... ~ p[0], p[1], p[2], ...

 

 

< Stack - details >
* Embedded System : Stack and Heap is declared as a 'Global variable'
 e.g. Stack : dword recipe_stack[20000]
      Heap : static uint32 commonMemoryPool[20000]
 cf. Uninitialized Global variable - .bss(ZI)
 cf. Growth direction : Stack(Address Decreases), Heap(Address Increases)

 

- Stack type
 a. Ascending(toward the upper address, Increase), Descending(toward the lower address, Decrease)
 b. Full(current stack point includes the current data), Empty(current stack point does not include the current data)
 c. After(stack pointer changes after data in), Before(stack pointer changes before data in)

 

e.g.

  IB(Increase SP Before Data), IA(Increase SP After Data), DB(Decrease SP Before Data), DA(Decrease SP After Data)
  FA(Full Ascending), FD(Full Descening)  // SP points to the valid data
  EA(Empty Ascending), ED(Empty Descening) // SP points to the invalid data

 

e.g. STM(STore Multiple)=push(), LDM(LoaD Multiple)=pop()
  STMIA r9!, {r0, r1, r5} // STR r0, [R9] & R9++ -> STR r1, [R9] & R9++ -> STR r5, [R9] & R9++ // Same as STMEA
  STMIB r9!, {r0, r1, r5} // R9++ & STR r0, [R9] -> R9++ & STR r1, [R9]  -> R9++ & STR r5, [R9]  // Same as STMFA
  STMDA r9!, {r0, r1, r5} == STMED r9!, {r0, r1, r5}
  STMDB r9!, {r0, r1, r5} == STMFD r9!, {r0, r1, r5}

 

- Normal Stack Type : Full Descending ( Increase Before )
  stmfd sp!, {r4-r12, lr} // sp(Stack Pointer=R13), lr(Linked Register=R14)
  ldmfd sp!, {r4-r12, lr}

 

e.g. Stack initialization : Change CPU mode to Abort mode -> Link Abort stack to R13
  msr CPSR_C, #PSR_Abort  ;; msr : Load an immediate value or a contents of general-purpose regiser to PSR(Program Status Register)
  lrd r13, =abort_stack+Abort_Stack_Size // Descending : from 'abort_stack+Abort_Stack_Size' to 'abort_stack'
      // Ascending : from 'abort_stack' to 'abort_stack+Abort_Stack_Size'

 

- Cautions!
a. Thumb mode : push/pop only  /  ARM mode : Multiple Register transfer
b. CMD r9!, {r0, r1, r5} // Store/Load : from r5 for Descending, from r0 for Ascending -> the 1st element lies in the lower address

 

- Calling Functions
a. Deliver arguments and push the address to return into stack
b. Call functions
c. Prepare the memory space in Stack for local variables
d. Execute the functions
e. Release the local variables from Stack
f. Load the address to return from Stack, and return the caller function
g. Release the arguments

 

-----

AND

ARTICLE CATEGORY

분류 전체보기 (4477)
올드Boy다이어리 (532)
올드Boy@Jeju (83)
올드Boy@Road (131)
올드Boy@Book (58)
숨은길찾기 (14)
스펙트럼 (105)
우물밖엿보기 (32)
교회에말걸기 (226)
이어지는글들 (52)
하하호호히히 (75)
어?...아하! (126)
대한늬우스 (1673)
세계는지금 (268)
차한잔의여유 (64)
La Vita E Bella (230)
좋은나라만들기 (92)
트위터세상 (67)
사람&말 (625)
호모파베르 (20)

RECENT ARTICLE

RECENT COMMENT

RECENT TRACKBACK

CALENDAR

«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28

ARCHIVE