2016. 7. 11. 15:25 devel/etc

volatile 극혐

이라고만 배웠는데 실제 volatile 키워드의 필요성을 느껴서 글로 남긴다


linux의 c에서는 못 느껴본 일이다

하지만 펌웨어 세상으로 오면 조금 다른거 같다



전역 변수

int state;


루프문

while(state == 0);


인터럽트 핸들러

extern int state;

state = 1;


이렇게 해놓고 돌렸는데 웬걸

인터럽트 핸들러가 정상적으로 실행되어 state 값이 변했음에도 불구하고

while문을 빠져나갈 생각을 하지 않는 것이었다


고민 좀 많이 하다가 든 생각이 바로 while문 안에서 암껏도 안해서 얘가 while(TRUE)로 최적화를 시켜버렸나보다

하는 생각이 들었다



-> 수정


volatile int state

extern volatile int state

로 바꾸니까 정상적으로 수행된다



volatile 을 쓸 일이 없으니까 이런 일도 겪는구나

좋은 링크가 있어 참고차 남긴다

https://salkuma.wordpress.com/2010/06/13/register-volatile-keyword/





기타

심심해서 더 테스트 좀 해봤다

인터럽트 핸들러 없애버리고 루프문에 의미없는 코드를 넣어보았다


전역변수

int state


루프문

int i;

while(state == 0){

i++;

}


실행하니까 당연한걸까 의미없는 구문으로 판단하고 루프문 자체를 없애버렸다 ㅋㅋ


Posted by 쵸코케키

xxd 유틸리티를 쓰면 된다



예시

위와 같은 내용의 파일 flasher.bin을 header file로 만들어서 include 하고 싶을 경우

xxd -i flasher.bin > flasher.h



확인

사이즈랑 변수랑 정확하게 생성된 것을 볼 수 있다



윈도우에서는 어떻게 하냐고?

cgwin 같은곳에 xxd가 윈도우용으로 포팅된게 있는거 같다

'devel > etc' 카테고리의 다른 글

연산자 우선순위 헷갈리기 쉬운 예제  (0) 2016.08.11
volatile 극혐  (0) 2016.07.11
/proc/config.gz 활성화 안될 때  (0) 2016.04.22
bash 쉘 오른쪽에 시간 표시하기  (0) 2016.04.22
git stash, pull, checkout 삽질  (0) 2016.04.19
Posted by 쵸코케키

64비트 리눅스 커널메모리 맵

Documentation/x86/x86_64/mm.txt


AMD64 canonical address form 이라고도 하는듯


상위 - 커널이 사용(40bit?)

하위 - 유저스페이스(47bit)

나머지 - hypervisor용 등등 그냥 비워둠


하지만 kmalloc 제한은 엄청 작다

신형 대용량 메모리 할당 기법들을 사용해야 한다



기타 64bit low memory 관련 글

http://www.criticalworld.co.kr/?p=56

Posted by 쵸코케키

커널 소스 보다가 발견

typedef struct test{
int                    a;
unsigned long     tvar;
char                  c;
}tt_t;

tt_t test_func(unsigned long val)
{
return (tt_t) {     .a = -9323,
     .tvar = val,
.c = 'a' };
}


int main()
{
unsigned long input = 7;
tt_t result = test_func(input);
printf("%d, %lu, %c\n", result.a, result.tvar, result.c);

return 0;
}

이런식으로 선언 없이 리턴 가능


'devel > code' 카테고리의 다른 글

디버그 on/off에 따라 자료형을 다르게 하는 방법  (0) 2016.12.02
bus_for_each_dev - while 조건문  (0) 2016.10.10
script ㅎㄸㄸ  (0) 2015.08.27
return 깔끔하게 처리  (0) 2015.01.16
ptr loop  (0) 2014.11.19
Posted by 쵸코케키



General setup 

-> Kernel .config support

-> Enable access to.config through /proc/config.gz


이 두가지를 동시에 활성화 해야 한다

만약 Kernel .config support가 *가 아닌 M으로 되어 있다면


modprobe configs 를 해야 접근이 가능하다

ls /proc/config.gz




'devel > etc' 카테고리의 다른 글

volatile 극혐  (0) 2016.07.11
바이너리 파일을 C 헤더 파일로 만들기  (0) 2016.07.11
bash 쉘 오른쪽에 시간 표시하기  (0) 2016.04.22
git stash, pull, checkout 삽질  (0) 2016.04.19
cscope  (0) 2016.04.11
Posted by 쵸코케키


참 신기방기 하다 :)

/usr/bin/ 같은데 넣어버리면 굳




http://mina86.com/p/bash-right-prompt/


Posted by 쵸코케키

헤더파일 전역변수 중복 오류

File:Program memory layout.pdf


재미난 일이 있었다

gcc에서는 문제 없는 코드가

visual studio 에서는 컴파일이 안되는 현상이 있었다


결론 요약

1. gcc랑 visual studio랑 헤더 파일 취급이 다름

2. 변수, 함수의 선언은 중복가능, 정의와 동시에 선언은 불가

3. header 파일은 extern 변수 선언, c 파일에는 변수 선언 및 정의



#1. gcc랑 visual studio랑 헤더 파일 취급이 다름 

type.h, main.c, func.c

*** type.h

#ifndef _type_h_

#define _type_h_

#include <stdio.h>


void show_var(void);

#endif



*** main.c

#include "type.h"

int var = 7;


int main()

{

show_var();

return 0;

}



*** func.c

#include "type.h"

extern int var;


void show_var(void)

{

printf("%d\n", var);

}




별거 아니다 그런데 위의 내용이 gcc에서는 오류 없이 컴파일 되었으나

visual studio에서는 func.c가 int var를 못 찾겠다고 오류를 뱉고 컴파일에 실패했다

중략하고 결론만 이야기 하면 type.h에 extern int var를 써줘야 하는게 원래 맞다고 한다


그런데 참 신기한 일이 main.c의 int var = 7를 type.h로 이동 시켰을 때다

visual studio는 그냥 컴파일이 된다 그러나

gcc는 ld(linker) 단계에서 (.rodata + @) multiple definition 오류가 난다

이건 사실 gcc쪽이 맞는거 같다


왜냐고 생각해보니 헤더를 파일에 복사할 때 일단 main.c, func.c에 _type_h_가 정의 된적 없으니

void show_var(void);랑 int var = 7;를 붙일 것이다

그리고 마지막에 모든 파일을 하나로 합치는 단계에서 main.c에도 int var = 7;이 있고

func.c에도 int var = 7;이 있으니 중복이 되어 오류를 출력하는 것이리라


그런데 왜 .rodata + @ 오류일까? 

initialized data니까 .data + @가 맞지 않으려나 


기타



#2. 변수, 함수의 선언은 중복가능, 정의와 동시에 선언은 불가

테스트 해봤다

*** test.c

void a(int);

void a(int);


int c;

int c;


int main()

{

c = 4;

a(c);

return 0;

}


void a(int b)

{

b+=8;

}


gcc에서 오류 없이 컴파일 된다 -Wall 해도 고요하다

but 

int c = 6;

int c = 3; 

이러면 당연하게 안된다

이 이상해보이는 바보 코드가 위의 의문스러운 문제의 해답이 되리라 :)



Posted by 쵸코케키

git branch 만들고 merge하고 윈도우 + linux에서 이거저거 동시에 하다보니 뭔가 꼬인듯

아마 여러명이서 개발할 때 충분히 가능한 상황

a파일을 1번 컴터에서 수정했는데 이미 2번 컴터에서 수정해서 커밋, 푸쉬까지 완료

1번 컴터의 소스들을 날릴 수도 없고(pull), 그렇다고 푸쉬할 수도 없다


*** 오류 상황

> git pull

There is no tracking information for the current branch.

Please specify which branch you want to merge with.

See git-pull(1) for details

    git pull <remote> <branch>


If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> master


> git revert source.c

fatal: bad revision 'source.c'


*** 해결 단계 #1

> git stash 

Saved working directory and index state WIP on master: 8d8f07c 어쩌고 저쩌고 커밋 주석들

HEAD is now at 8d8f07c 커밋 주석들

잠시 인벤에 넣어둘 수 있는 기능이라칸다


> git stash show

source.c | 2 +-

1 file changed, 1 insertion(+), 1 deletion(-)


> git pull

Updating 8d8f07c..62acd07

+-+_+_+_+_

pull이 된다, 2번 컴터로 작업한 데이터가 고스란히 복구 되었다




*** 오류 상황

> git stash pop

Auto-merging source.c

CONFLICT (content): Merge conflict in source.c

인벤에 넣어뒀던 파일이 튀어나오고 오토머징 된다

복구 해놨더니 stash pop 해서 파일이 1번 작업물과 2번 작업물이 섞였다


> git diff source.c

diff --cc source.c

index 5f69b98,f54d53e..0000000

--- a/source.c

+++ b/source.c

@@@ -1,6 -1,11 +1,17 @@@

++<<<<<<< Updated upstream

 +/**

 + *@file doxygen 주석들

 + */

++=======

+ /*

바뀐 내용들 

+ */

++>>>>>>> Stashed changes

이렇게 stash 이전/이후로 나눠서 파일에 같이 merge 되어 있다

직접 vi로 편집해도 되지만 웬지 싫었다

원복하고 싶었다



> git stash clear

일단은 주머니 초기화


*** 해결 단계 #2

> git reset HEAD source.c

Unstaged changes after reset:

M source.c


> git diff source.c

fatal: ambiguous argument 'source.c': unknown revision or path not in the working tree.

Use '--' to separate paths from revisions, like this:

'git <command> [<revision>...] -- [<file>...]'

맛감


> git checkout source.c

성공


2번 컴터로 올린 자료로 복구 되었다

Posted by 쵸코케키

arm 어셈블리 코드 선행 지식

대충 아는 분들은 아래로 죽 넘겨버리면 ok


c code

val = *addr;


gcc inline assembly

asm (

"ldr %0, [%1]"

: "=r"(val)

: "r" (addr)

);


':'이게 뭘까? 

: output operand list(register to memory)

: input operand list(memory to register)

: clobber list(temporary variables, 컴파일러가 맘대로 못 쓰게 할 수 있음, 생략가능)


%0, %1, %2 .... output 부터 시작해 input에 나열된 변수 순서 대로 번호가 할당된다

예를 들어

: "=d (res)", "=&c" (d0), "=&D" (d1), "=&a" (d2) 이런게 가능


Constraints(info gcc 해서 ::Constraints 로 확인 가능)

: "0"(val) - src랑 dst를 같은 register쓰도록 강제(input, output)

0~9 등등 가능 아마도 %0을 같이 쓴다 이런 의미일듯

= output only variables(write only)

r  register

등등 많다


Operand 2(Flexible second operand)

예제

mov r0, r1, lsl #3

r0 = r1<<3;



바이트 스왑 어셈블리 코드 

0x12345678 -> 0x78563412

unsigned long ByteSwap(unsigned long val)

{

asm volatile (

"eor     r3, %1, %1, ror #16        \n\t"

"bic     r3, r3, #0x00FF0000        \n\t"

"mov     %0, %1, ror #8            \n\t"

"eor     %0, %0, r3, lsr #8          \n\t"

: "=r" (val)

: "0"(val)

: "r3"

);


return val;

}

 

%0 -> 함수 인자 val변수 (ldr r0, &val 대충 이런 느낌)

%1 -> %0과 동일


eor r3, %1, %1, ror #16

r3 = 12345678 ^ 56781234

= 444C444C


bic r3, r3, #0x00FF0000

r3 = r3 & 0xFF00FFFF

r3 = 444C444C & 0xFF00FFFF

= 4400444C


mov %0, %1, ror #8

%0 = 78123456 

  

eor %0, %0, r3, lsr #8

%0 = %0 ^ (r3 >> 8)

= 78123456 ^ 00440044

= 78563412



이게 가능한 이유?

XOR의 특징 : a ^ b = c -> c ^ b = a


일단 byte swap의 규칙을 찾아보자

0x1234ABCD -> 0xCDAB3412

34랑 CD는 ror 8회 하면 된다

AB랑 12는 rol 8회 하면 된다

걍 ror 8회 하고 0xFF00FF00 이랑

rol 8회 하고 0x00FF00FF랑 or 하면 안되나요?

-> operand 2 에 constant 제약 때문에 안될듯? 아닌데 제약 범위 이내던데???



처음 eor 코드에서 일종의 백업을 한다 이제 r3는 원본인 %1과 ^를 하면 언제든지 ror 16회 된 데이터를 뽑아올 수 있다


bic(not and)를 사용해 체를 걸러낸다 왜 굳이 not을 하고 and를 해야했을까?

이제 FF00FFFF 에서 00 부분을 제외했기 때문에 ror 16회 한 56781234에서 56xx1234만 복원이 가능하다


FF00FF00 혹은 00FF00FF 형태로 만든 것과 ror 8 혹은 rol 8 한 값과 

으메 모르겠다........



기타 추천 링크

http://xenostudy.tistory.com/206



'devel > man & example' 카테고리의 다른 글

gcc inline assembly  (0) 2016.08.11
arm stm32f4xx software interrupt handler 만들기  (0) 2016.08.09
dev file  (0) 2015.08.04
ioctl  (0) 2012.07.26
const  (0) 2012.07.21
Posted by 쵸코케키

2016. 4. 11. 15:32 devel/etc

cscope

#!/bin/bash

if [[ "$1" = "-R" ]]; then

rm -f cscope.out cscope.files

fi

find `pwd` -name '*.c' -o -name '*.cpp' -o -name '*.cc' -o -name '*.h' \

-o -name '*.s' -o -name '*.S' -o -name '*.dts' -o -name '*.dtsi' \

> cscope.files

cscope -i cscope.files



편하더라


Posted by 쵸코케키

블로그 이미지
chocokeki
쵸코케키

공지사항

Yesterday
Today
Total

달력

 « |  » 2024.5
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 29 30 31

최근에 올라온 글

최근에 달린 댓글

글 보관함