2008. 2. 26. 09:47
1. _vimrc

-----------------------------------------------------------------
"My Setting
source $VIMRUNTIME/../ephron_config.vim
source $VIMRUNTIME/../MyMapFunction.vim
source $VIMRUNTIME/../CustomFunction.vim
-----------------------------------------------------------------

2. ephron_config.vim
-----------------------------------------------------------------
set tags=./tags
set nu
set ci
set ai
set si

set sw=4
set ts=4
if has("gui_running")
        set lines=50
        set co=120
endif
"End of My Settings

"Customizing My Color Setting
colorscheme desert

"Customizing Plugin Setting
-----------------------------------------------------------------

3. CustomFunction.vim
-----------------------------------------------------------------
if version >= 500
func! GetTodayDate()
        exe "read !date/t|sed 's/-//g'"
endfunc
endif
-----------------------------------------------------------------

4. myMapFuction.vim
-----------------------------------------------------------------
map <F1> v]#ezf
map <F2> v]}zf
map <F3> zo
map <F9> a// EPHRON_<Esc>:call GetTodayDate()<CR> + kkkJxA
"map <F11> :25vs ./<CR>:set nonumber<CR>^Ww
map <F11> :WMToggle<cr>

"방향키 설정
-----------------------------------------------------------------
2007. 11. 16. 14:23

[ARM] Veneer code

OldPapers/linux 2007. 11. 16. 14:23

                                

Veneer에 대한 정의 입니다.

 

Veneer :  armlinker 생성하는 veneers 대한 세부 정보
            Linker ARM 코드와 Thumb 코드를 link 있고, 필요 자동적으로
            processor state 변경 하기 위한 interworking  veneer 생성하고, 필요한
            에 branch instruction range 확장하기 위해 long branch veneers 생성한다
               Arm linker Arm function Thumb state 호출되거나 Thumb function Arm
            state에서 호출되는 것  detect 있고, 필요 processor state 변경하
            기 위해 call return instruction 변경 하거나 veneers라고 불리는 작은 code
            section 삽입한다.
 
위에 정의된 내용만으로는 뭐하는건지 잘 모르겠죠.. 간단한 예를 들어보겠습니다.
 
다음과 같은 arm모드로 컴파일이된 arm.s 라는 소스가 있고 thumb 모드로 컴파일된 thumb.s 라는 소스가 있다고 하죠
둘다 컴파일 옵션에는 interwork 를 줘야 같이 동작할 수 가 있습니다.
 
 
      ; ******
      ; arm.s
      ; ******
      AREA       Arm,CODE,READONLY
      IMPORT    ThumbProg
      ENTRY
ARMProg
      MOV   r0,#1
      BL      ThumbProg
      MOV   r2,#3
 
      MOV   r0, #0x18
      LDR    r1, =0x20026
      SWI     0x123456
      END
 
 
     ; *******
     ; thumb.s
     ; ********
     AREA  Thumb,CODE,READONLY
 
     CODE16
     EXPORT ThumbProg
ThumbProg
     MOV r1, #2
     BX    lr
     END
 
 
위의 소스를 보면 arm모드로 컴파일되는 arm.s와 thumb모드로 컴파일되는  thumb.s 소스가 있습니다.
일반적으로 arm모드에서 thumb 모드의 코드로 branch하거나 thumb모드에서 arm모드로 branch할때는 BX 명령어가 사용됩니다.
하지만 arm.s 에서 보면 BL  ThumProg 로 Thumb코드인 ThumbProg 함수를 BL 로 호출 했습니다.
이럴 경우 링커는 자동으로 해당 부분에 Veneer 코드를 삽입하여 arm 모드에서 thumb모드로 변환할 수 있는 코드를 넣게 됩니다.
이런 코드를 Veneer 코드라고 하며 위의 소스를 컴파일 한후 disassemble한 코드로 살펴 보면 아래와 같습니다.
 
 
armsd: list 0x8000
ARMProg
            0x00008000: 0xe3a00001  .... : >   mov       r0,#1
            0x00008004: 0xeb000005  .... :      bl          $Ven$AT$$ThumbProg
            0x00008008: 0xe3a02003  . .. :      mov       r2,#3
            0x0000800c: 0xe3a00018  .... :      mov       r0,#0x18
            0x00008010: 0xe59f1000   .... :      ldr         r1,0x00008018 ; =#0x00020026
            0x00008014: 0xef123456   V4.. :    swi        0x123456
            0x00008018: 0x00020026  &... :     dcd        0x00020026   &...
ThumbProg
+0000     0x0000801c: 0x2102       .!    :      mov       r1,#2
+0002     0x0000801e: 0x4770      pG   :      bx         r14
$Ven$AT$$ThumbProg
+0000     0x00008020: 0xe59fc000  .... :      ldr         r12,0x00008028 ; = #0x0000801d
+0004     0x00008024: 0xe12fff1c   ../. :      bx         r12
+0008     0x00008028: 0x0000801d  .... :      dcd       0x0000801d   ....
+000c     0x0000802c: 0xe800e800  .... :     dcd       0xe800e800
+0010     0x00008030: 0xe7ff0010    .... :      dcd       0xe7ff0010   ....
+0014     0x00008034: 0xe800e800  .... :      dcd       0xe800e800  ....
+0018     0x00008038: 0xe7ff0010    .... :      dcd       0xe7ff0010    ....
 
 
disassemble된 코드를 살펴 보면 이전 bl ThumbProg  가 있던 자리에 bl  $Ven$AT$$ThumbProg 로 바뀐것을 볼 수 있습니다.
이 코드가 바로 veneer 코드 이며 arm 모드에서 thumb 모드로 컴파일된 함수를 호출 하기 위해 BX 를 사용하도록 linker가
바꾼 것입니다.
실제 아래쪽에 보면 $Ven$AT$$ThumbProg  로 Lable 이 붙은 코드가 추가가 되었습니다.
BL $Ven$AT$$ThumbProg  에 의해  $Ven$AT$$ThumbProg 로 가보면 이곳에서 하는일은 처음에
r12에다 0x00008028 번지에 있는 값인 0x0000801d 를 넣습니다.
그다음이 bx r12 를 하게 되는데 결국 사용자가 bl ThumbProg로 코드를 작성했지만 thumb모드로 바꾸기위해 링커가
bx 0x0000801d  라는 코드로 바꾼것입니다. (BX를 쓰게되면 해당번지로 branch한 후 state를 바꾸게 됩니다.  번지가 홀 수 번지이면 arm모드에서 thumb 모드로 번지가 짝수 번지이면 thumb모드에서 arm 모드로 state를 바꾸게 됩니다.)
결국 bx 0x0000801d 는 홀수 번지 branch이므로 0x0000801c 번지로 branch하고 arm에서 thumb으로 state를 바꿉니다.
그럼 0x0000801c 번지에는 기존의 ThumbProg 코드가 있습니다. 여기서 해당 코드 수행을 하고 다시 bx r14에 의해 (r14에는 bl 를 한다음 돌아갈 주소가 짝수번지로 들어가 있음  0x00008008) 다시 0x00008008 번지로 branch하고 번지가 짝수 이므로 thumb에서 arm으로 state를 바꾸게 됩니다.
 
이렇게 사용자가 arm/thumb interworking을 고려하지 않고 코드를 짜더라도 링커가 자동으로 해석해서 해당 모드를 바꿀 수 있게 코드를 삽입하게 되는데 이런 코드를 veneer 코드라고 합니다.
 
arm/thumb interworking 뿐아니라 long jump를 할경우도 이런 veneer 코드가 생기는 arm 모드에서 최대 32M 영역까지 branch를 할 수 있고 thumb 모드에서는 최대 4M 영역까지 branch를 할 수 있습니다.  마찬가지로 thumb모드에서 4M를 넘어가는곳의 함수를 호출 하는경우 링커는 알아서 veneer 코드를 만들어 arm 모드로 state를 바꾸고 해당 영역으로 branch한 후 다시 thumb 모드로 바꿔주는 코드를 삽입하게 됩니다.
 
 $Ven$AT$$ThumbProg   여기서 $Ven 은 veneer 코드라는 의미이고  $AT 는 Arm 모드에서 Thumb 모드로 변경한다는 의미입니다.
 
 
 
 
 
 
 
 
 

                                
2007. 8. 28. 16:19
Structure alignment
  - The alignment of a nonpacked structure is the maximum alignment required by any of its fields. - ARM
  - 구조체에서의 alignment 는 가장 큰 alignment에 맞추어진다.
    이는 자동 padding 과 연계되어 실수를 하기 쉬운 부분이 된다.

struct
{
    int a;
    double b;
    int c;
} TT;

TT의 sizeof 결과는 얼마일까? 답은 24이다.
왜냐하면 가장 큰 alignment 인 8 에 맞춰 남는 부분들이 padding 되기 때문이다.


padding
보통 우리가 아는 한에서는 4byte alignment 이다. 그리고 이보다 작을 경우에는 compiler 에서 자동 padding을 넣어준다. 이렇게 하는 이유는 performance 상의 이유이다. 메모리 접근시 유리하다.

packing 하기(packed 의 사용)
그러나 이러한 자동 padding 은 코드 호환성은 상당히 떨어진다.
왜냐하면 compiler 에 따라 자동 padding 하는 방식이 다를 수도 있기 때문이다. 그래서 performance를 떨어트리더라도 코드 호환성을 높이기 위해 자동 padding 을 하지 않게 된다.
즉, alignment 에 맞춰 padding을 넣지 않고 순수한 data가 차지하는 byte만을 메모리에 잡는다.

이렇게 하는 것을 packing 이라고 한다.


packing 하게 되면 기본적으로 alignment 를 1로 잡는다.

arm 계열
__packed 명령을 이용하여 packing 한다.
__align(n) 명령을 통해 특정 n byte 로 align이 가능하다.

gcc
__attribute__((packed))
__attribute__((align(n))) 과 같이 한다.

VC (MS 계열)
#pragma pack(push)
#pragma pack(4)
~~~~~~~~~
#pragma pack(pop)

VC 에서는 align 이 없고 pack 명령어를 통해 다 처리한다.
2006. 6. 30. 11:37
http://www.arm.com/support/faqdev/1453.html

ARM/Thumb Interworking and 'Unsupported call'



Description
When building an ARM/Thumb Interworking Image, the linker may give messages like:

For SDT 2.50/2.51:

Error: Unsupported call from Thumb code to ARM symbol arm_sub in thumb.o(C$$code). For SDT 2.11a:

Warning: Unsupported call from Thumb code to ARM symbol arm_sub in thumb.o(C$$code). For SDT 2.11:


1 Thumb to ARM interworking calls generated, use '-info interwork' to listInterworking call from Thumb to ARM code symbol arm_sub in thumb.o(C$$code). Solution
These messages indicate that ARM-to-Thumb or Thumb-to-ARM interworking calls have been detected by the linker, but the called routines have not been compiled for interworking. The example above shows a call from the (Thumb) object module thumb.o to the routine arm_sub() in another module.

Even if the link appears to be successful, you should interpret such messages as being errors, because the image may not execute correctly.

For the case above, you should recompile/reassemble for interworking the (C/asm) module(s) containing arm_sub (let's call it FUNC).

If FUNC is a C file, you should recompile it using the option '-apcs /interwork'.
If FUNC is an assembler file, you should:

use the 'INTERWORK' area assembler attribute for these routines e.g. AREA func, CODE, READONLY, INTERWORK  
check the called routine (arm_sub) use a BX LR instruction to return.
check the calling routine uses a BL instruction to call the routine arm_sub.
If the use of '-apcs /interwork' (for armcc & tcc) and 'INTERWORK' (for armasm & tasm) is applied consistently in your project, then the linker will generate the correct interworking veneers, and you will no longer see the message(s) above.

If the object file causing the error is supplied by a 3rd party vendor (e.g. an RTOS) which you do not have the source code for, then you may have to ask your supplier to provide suitably recompiled/reassembled object files.

For more details, see the SDT 2.11 User Guide, chapter 12, 'Interworking ARM and Thumb' or the SDT 2.50 User Guide, chapter 7, 'Interworking ARM and Thumb'.

2006. 6. 21. 07:35

Nand 자료

OldPapers/linux 2006. 6. 21. 07:35
nand 자료

nand에서 boot시 참고자료
2006. 6. 20. 23:38
U-Boot>nand write.yaffs : NAND Flash Filesystem : YAFFS HOW-TO (2nd)  

글쓴이 : jazz0719  조회 : 3216   날짜 : 2004/06/30 16:40:51

% style % -->
오랫만에 글올리는군요. 다들 잘 지내셨어요?



저번엔 U-Boot에 NAND fusing 관련하여, MTD기반으로 연동하는 방법을 올렸었죠 ?

(공구보드 U-Boot소스. 2410-09-bluesky-u-boot-1.0.0.tar.gz도 살짝 보니까

이런방식이더군요.)



이번에 고도리님 등등과 자체프로젝트(^^?)를 추진하고 있는데, YAFFS작업이 있어서

이 기회에 cmd_nand.c의 JFFS지원 루틴을 분석하여, U-Boot에서 YAFFS 이미지 fusing도

지원하도록 수정해보았습니다.



질문올라온거 보면 yaffs image를 U-Boot의 nand write[.jffs2] 명령을 이용하여

fusing 시도하는 분이 계시던데, 절대 안될겁니다.(^---^).

YAFFS 이미지포맷이 JFFS2등 다른 이미지파일과 다르고, Spare Area(OOB)의 처리가

되어야 하기 때문입니다.



아래 찬찬히 읽어보시면 이해되실거예요.

(보드 specific 코드 - 형욱보드..로 표기)



- 장형욱 씀.


NAND Flash Filesystem : YAFFS
yaffs를 지원하도록 리눅스커널 설정

mtd driver 패치 설치
MTD(Memory Technology Devices)는 임베디드 디바이스에서 고형체 파일시스템(solid state filesystem)을구성하는데 사용하는 플래시 메모리, RAM, 그리고 그 비슷한 다른 칩셋 등 메모리 장치로 yaffs도 mtd를 통해 연결됨
mtd관련모듈을 yaffs를 지원하도록 최신 버전으로 패치(안할경우 fs/yaffs 컴파일시 에러 발생)
http://www.linux-mtd.infradead.org/에서 mtd-snapshot...tar.gz2 최신버전 다운로드
[mtd]/patch> sh patchin.sh -c -j [linux] : kernel mtd모듈 패치
-c : symbolic link를 만들지 않고 직접 커널소스로 mtd copy
-j : jffs2 지원

변경내용 : [linux]/drivers/mtd/, [linux]/include/linux/mtd/

NAND 관련 driver 코드 작성(형욱보드_nand.c)
falinux사이트에서 관련소스를 다운로드(http://www.falinux.com/download/data/kernel.zip)
[linux]/drivers/mtd/nand/ez_x5.c를 pwpro_nand.c로 바꾸고 아래와 같이 수정
: 하드웨어 관련 컨트롤 함수, IO 주소공간 지정, NAND 파티션 테이블 작성 등.
NAND 플래시 상 MTD 파티션 구분
Creating 3 MTD partitions on "NAND 16MiB 3,3V":
mtd0,mtdblock0 : 0x00004000-0x00190000 (1584K) : "Linux Kernel Partition"
mtd1,mtdblock1 : 0x00190000-0x00640000 (4800K) : "Root Filesystem(YAFFS) Partition"
mtd2,mtdblock2 : 0x00640000-0x00fa0000 (9600K) : "Configuration Partition"


소스

/*
*  drivers/mtd/nand/형욱보드_nand.c
*
*  Copyright (C) 2003 JANG, Hyung-Wook (jazz0719@dreamwiz.com)
*
*  Support board : 형욱보드
*/

#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
/* modified by hwjang. */
#include <asm-ppc/delay.h>
#include <asm-ppc/processor.h>

#define PWPRO_NAND_BASE                0xf0000000
#define PWPRO_NAND_BASE_D0            PWPRO_NAND_BASE
#define PWPRO_NAND_ACCESS_START            (0x000)    // not use
#define PWPRO_NAND_DATA                    (0x00000)
#define PWPRO_NAND_CMD                     (0x00001)
#define PWPRO_NAND_ADDR                    (0x00002)
#define PWPRO_NAND_ACCESS_END              (0x300) // not use
#define NAND_MAXCHIP                (1)
static struct mtd_info *pwpro_nand_mtd = NULL;    

#define SZ_1K                           (1024)
#define SZ_1M                 (1024*1024)
#define __PWPRO_GPIO

/* modified by hwjang. add NAND Flash IO address mapping. */

#define FLASH_BASE_ADDR     0xF0000000
/*
#define FLASH_DATA_REG      *(volatile unsigned char*)(FLASH_BASE_ADDR + 0x00000)
#define FLASH_CMD_REG       *(volatile unsigned char*)(FLASH_BASE_ADDR + 0x00001)
#define FLASH_ADDR_REG      *(volatile unsigned char*)(FLASH_BASE_ADDR + 0x00002)
#define FLASH_CS0_SET       *(volatile unsigned char*)(FLASH_BASE_ADDR + 0x80000)
#define FLASH_CS0_CLR       *(volatile unsigned char*)(FLASH_BASE_ADDR + 0xA0000)
*/
#define FLASH_DATA_REG      (FLASH_BASE_ADDR + 0x00000)
#define FLASH_CMD_REG       (FLASH_BASE_ADDR + 0x00001)
#define FLASH_ADDR_REG      (FLASH_BASE_ADDR + 0x00002)
#define FLASH_CS0_SET       (FLASH_BASE_ADDR + 0x80000)
#define FLASH_CS0_CLR       (FLASH_BASE_ADDR + 0xA0000)

#if defined(__PWPRO_GPIO)               /* Clocking and Chip Control */
#define DCRN_CPC0_CGCR0     0x0b1       /* Clock Generation Control Register 0 */

#define GPIO0_OR        0xEF600700
#define GPIO0_TCR       0xEF600704
#define GPIO0_ODR       0xEF600714
#define GPIO0_IR        0xEF60071C

#define GPIO_MASK_NAND_FLASH_MEM (1<<(31-15))

#define gpio_init()     (*(volatile unsigned int*)GPIO0_TCR = 0x10000000)
#define gpio_read()     (*(volatile unsigned int*)GPIO0_IR)
#define gpio_write(n)   (*(volatile unsigned int*)GPIO0_OR = (n))

static void _flash_gpio_init(void)
{
        unsigned long temp;
        unsigned int  val;
                                                                                                
        temp = mfdcr(DCRN_CPC0_CGCR0);
        temp |= 0x00200000;
        mtdcr(DCRN_CPC0_CGCR0, temp);
                                                                                                
        val = (*(volatile unsigned int*) GPIO0_TCR);
        val &= ~(GPIO_MASK_NAND_FLASH_MEM);
        (*(volatile unsigned int*) GPIO0_TCR) = val;
                                                                                                
        val = (*(volatile unsigned int*) GPIO0_ODR);
        val &= ~(GPIO_MASK_NAND_FLASH_MEM);
        (*(volatile unsigned int*) GPIO0_ODR) = val;
                                                                                                
        val  = gpio_read();
        val &= ~GPIO_MASK_NAND_FLASH_MEM;
        gpio_write(val);
}
#endif /* __PWPRO_GPIO */

/*
* Define partitions for flash device
*/
const static struct mtd_partition partition_info[] =
{
    {
        name  : "형욱보드 Linux Kernel Partition",
        offset: 0x00004000,
        size  : 1584*SZ_1K
    },
    {
        name  : "형욱보드 Root Filesystem(YAFFS) Partition",
        offset: 0x00190000,
        size  : 4800*SZ_1K
    },
    {
        name  : "형욱보드 Configuration Partition",
        offset: 0x00640000,
        size  : 9600*SZ_1K
    }
};
#define PWPRO_NAND_NUM_PARTITIONS     3


/*
*    hardware specific access to control-lines
*/
/* void pwpro_nand0_hwcontrol(int cmd) */
void pwpro_nand0_hwcontrol(struct mtd_info *mtd, int cmd)
{
/*    int dummy; */

    switch(cmd)
    {
/*
    case NAND_CTL_SETNCE: dummy = readb(EZ_NAND_BASE_D0 + EZ_NAND_DATA)      ; break;
    case NAND_CTL_CLRNCE: dummy = readb(EZ_NAND_BASE_D0 + EZ_NAND_ACCESS_END); break;
*/  
    case NAND_CTL_SETNCE:
        writeb(0, FLASH_CS0_SET);         /* chip enable */
        writeb(NAND_CMD_RESET, FLASH_CMD_REG);     /* reset */
        udelay(20);                 /* delay */
        break;
    case NAND_CTL_CLRNCE:
        break;
    default:
        break;
    }
}

/*
* Send command to NAND device
*/
void pwpro_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
{
    register struct nand_chip *this = mtd->priv;
    register unsigned long NAND_IO_ADDR = this->IO_ADDR_W;

    // Write out the command to the device.
    if (command != NAND_CMD_SEQIN)
    {
        writeb (command, NAND_IO_ADDR + PWPRO_NAND_CMD );
    }  
    else
    {
        if (mtd->oobblock == 256 && column >= 256)
        {
            column -= 256;
            writeb (NAND_CMD_READOOB, NAND_IO_ADDR + PWPRO_NAND_CMD );
            writeb (NAND_CMD_SEQIN  , NAND_IO_ADDR + PWPRO_NAND_CMD );
        }
        else if (mtd->oobblock == 512 && column >= 256)
        {
            if (column < 512)
            {
                column -= 256;
                writeb (NAND_CMD_READ1, NAND_IO_ADDR + PWPRO_NAND_CMD);
                writeb (NAND_CMD_SEQIN, NAND_IO_ADDR + PWPRO_NAND_CMD);
            }
            else
            {
                column -= 512;
                writeb (NAND_CMD_READOOB, NAND_IO_ADDR + PWPRO_NAND_CMD);
                writeb (NAND_CMD_SEQIN  , NAND_IO_ADDR + PWPRO_NAND_CMD);
            }
        }
        else
        {
            writeb (NAND_CMD_READ0      , NAND_IO_ADDR + PWPRO_NAND_CMD);
            writeb (NAND_CMD_SEQIN      , NAND_IO_ADDR + PWPRO_NAND_CMD);
        }
    }

    // Serially input address
    if (column != -1 || page_addr != -1)
    {
        if (column != -1) writeb (column, NAND_IO_ADDR + PWPRO_NAND_ADDR);
        if (page_addr != -1)
        {
            writeb ((unsigned char) (page_addr & 0xff), NAND_IO_ADDR + PWPRO_NAND_ADDR);
            writeb ((unsigned char) ((page_addr >> 8) & 0xff), NAND_IO_ADDR + PWPRO_NAND_ADDR);
            // One more address cycle for higher density devices
            if (mtd->size & 0x0c000000)
            {
               writeb ((unsigned char) ((page_addr >> 16) & 0x0f), NAND_IO_ADDR + PWPRO_NAND_ADDR);
            }
        }  
    }
  
    switch (command)
    {
          
    case NAND_CMD_PAGEPROG:
    case NAND_CMD_ERASE1:
    case NAND_CMD_ERASE2:
    case NAND_CMD_SEQIN:
    case NAND_CMD_STATUS:
        return;

    case NAND_CMD_RESET:
        if( this->dev_ready )    break;
        writeb (NAND_CMD_STATUS, NAND_IO_ADDR + PWPRO_NAND_CMD);
        while ( !(readb (this->IO_ADDR_R) & 0x40));
        return;

    default:
        if (!this->dev_ready)
        {
            udelay (this->chip_delay);
            return;
        }  
    }
  
/*    while (!this->dev_ready()); */
    while (!this->dev_ready);
  
}

/*
* Main initialization routine
*/
int __init pwpro_nand_init (void)
{
    struct nand_chip *this;
  
    //  Allocate memory for MTD device structure and private data
    pwpro_nand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL);
    if (!pwpro_nand_mtd)
    {
        printk ("Unable to allocate 형욱보드 MTD device structure.\n");
        return -ENOMEM;
    }
    // Get pointer to private data
    this = (struct nand_chip *) (&pwpro_nand_mtd[1]);

    // Initialize structures
    memset((char *) pwpro_nand_mtd, 0, sizeof(struct mtd_info));
    memset((char *) this, 0, sizeof(struct nand_chip));

    // Link the private data with the MTD structure
    pwpro_nand_mtd->priv = this;

    // Set address of NAND IO lines
    this->IO_ADDR_R = PWPRO_NAND_BASE_D0 + PWPRO_NAND_DATA;
    this->IO_ADDR_W = PWPRO_NAND_BASE_D0 + PWPRO_NAND_DATA;
    // Set address of hardware control function
    this->hwcontrol = pwpro_nand0_hwcontrol;
    // Set commamd function
    this->cmdfunc = pwpro_nand_command ;
    // 15 us command delay time */
    this->chip_delay = 15;      

//    this->eccmode = NAND_ECC_SOFT;
//    pwpro_nand_mtd->oobinfo.useecc = -1;

#if defined(__PWPRO_GPIO)
    _flash_gpio_init();
#endif /* __POWATCH_GPIO */
  
    // Scan to find existence of the device
/*    if (nand_scan (pwpro_nand_mtd)) */
    if (nand_scan (pwpro_nand_mtd, NAND_MAXCHIP))
    {
        kfree (pwpro_nand_mtd);
        return -ENXIO;
    }
    // Allocate memory for internal data buffer
    this->data_buf = kmalloc (sizeof(u_char) * (pwpro_nand_mtd->oobblock + pwpro_nand_mtd->oobsize), GFP_KERNEL);
    if (!this->data_buf)
    {
        printk ("Unable to allocate NAND data buffer for 형욱보드-NAND.\n");
        kfree (pwpro_nand_mtd);
        return -ENOMEM;
    }
    // Register the partitions
    add_mtd_partitions(pwpro_nand_mtd, partition_info, PWPRO_NAND_NUM_PARTITIONS);
    // Return happy
    return 0;
}
module_init(pwpro_nand_init);

/*
* Clean up routine
*/
#ifdef MODULE
static void __exit pwpro_nand_cleanup (void)
{
    struct nand_chip *this = (struct nand_chip *) &pwpro_nand_mtd[0];

    // Unregister the device
    del_mtd_device (pwpro_nand_mtd);

    // Free internal data buffer
    kfree (this->data_buf);

    // Free the MTD device structure
    kfree (pwpro_nand_mtd);
}
module_exit(pwpro_nand_cleanup);
#endif

MODULE_LICENSE("GPL");
MODULE_AUTHOR("JANG, Hyung-Wook <jazz0719@dreamwiz.com");
MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on 형욱보드");



pwpro_nand.c를 커널컴파일 때 추가할 수 있도록 설정
[linux]/drivers/mtd/nand/Config.in 에 추가
dep_tristate '  NAND Device Support' CONFIG_MTD_NAND $CONFIG_MTD
if [ "$CONFIG_MTD_NAND" = "y" -o "$CONFIG_MTD_NAND" = "m" ]; then
   bool '    NAND Flash Device on 형욱보드' CONFIG_MTD_NAND_PWPRO
fi
[linux]/drivers/mtd/nand/Makefile 에 추가
obj-$(CONFIG_MTD_NAND_PWPRO)    += pwpro_nand.o


NAND Flash에 접근할 수 있도록 IO 주소공간을 커널에 등록
[linux]/arch/ppc/platforms/walnut.c 에 다음내용을 추가 (위에서 이미 등록됨. 확인)
void __init
board_io_mapping(void)
{
/* modified by hwjang */
        ...
        /* CS1 - NAND FLASH */
        io_block_mapping( 0xF0000000, 0xF0000000, 0x00100000, _PAGE_IO );
        ...
}
NAND ECC 경고메세지 관련
YAFFS는 MTD/NAND driver의 ECC기능을 쓰지않고, YAFFS에서 제공하는 것을 쓰므로 이로인한 아래의 경고메세지를 주석처리한다

[linux]/drivers/mtd/nand/nand.c 수정
case NAND_ECC_NONE:
  // printk(KERNEL_WARNING ...)


yaffs를 kernel fs에 포함

http://www.aleph1.co.uk/armlinux/projects/yaffs/index.html(yaffs소스),
http://www.toby-churchill.org/(ballon_yaffs소스) 다운로드


[linux]/fs/yaffs 생성.

yaffs소스에서 [linux]/fs/yaffs아래에 devextras.h yaffs_fs.c yaffs_guts.c yaffs_guts.h
yaffs_mtdif.cyaffs_mtdif.h yaffsinterface.h, yportenv.h, yaffs_ecc.h, yaffs_ecc.c 를 copy


[linux]/fs/yaffs에 [ballon_yaffs]/Makefile을 copy하고 아래와 같이 수정
obj-y := yaffs_fs.o yaffs_guts.o yaffs_mtdif.o yaffs_ecc.o
[linux]/fs/Config.in의 앞부분에 아래 추가하여 커널 컴파일 configuration시 yaffs 선택할 수 있도록 함
tristate "Yaffs filesystem on NAND" CONFIG_YAFFS_FS
(document에서는 CONFIG_MTD_NAND가 정의되어있을때면 설정가능하도록 되어있으나,
실제 nand flash에 접근할때는 mtd가아닌 yaffs의 ecc, verify write기능을 쓰기 때문에 이렇게 설정해야함


[linxux]fs/Makefile에 추가
subdir-$(CONFIG_YAFFS_FS)       += yaffs


컴파일 에러 발생시 추가 수정내용 (옵션)
[linux]/include/linux/serialP.h 수정 : async_icount 구조체 정의 관련
/* modified by hwjang. for yaffs filesystem support */
/* #if (LINUX_VERSION_CODE < 0x020300) */
#if (LINUX_VERSION_CODE >= 0x020300)
/* Unfortunate, but Linux 2.2 needs async_icount defined here and
* it got moved in 2.3 */
#include <linux/serial.h>
#endif


[linux]/include/linux/mtd/mtd.h 추가 : 2.5버전이하에서 사용하는 BUG_ON함수가 previewkit 소스에는 제공하지 않으므로 2.5이상 버전의 커널 소스트리의 bug.h파일을 [linux]/include/asm-ppc/bug.h 로 copy
#include <asm-ppc/bug.h>




kernel에 mtd, yaffs가 적용되도록 환경설정

Load configuration : arc/ppc/deconfig 한후 아래 내용 추가

Loadable module support
  [*] Kernel module loader : /sbin/insmod yaff.o하지 않아도 커널이 자동적으로 yaff module을 등록시키도록 하기 위함.

General setup
  [*] Default bootloader kernel arguments
    Initial kernel command string: "console=ttyS0,9600 console=tty0 root=/dev/mtdblock0"
    : 루트파일시스템을 플래시에 구성된 yaffs파일시스템으로 mtd를 통해 연결. 아래 참고.

Memory Technolygy Devices(MTD)
  <*> Memory Technology Device (MTD) support
  [*] Debugging(verbocity=0)
  <*> MTD partitioning support
  <*> Direct char Device access to MTD device
  <*> Caching block device access to MTD devices
  NAND Flash Device Drivers
    <*> NAND Device Support
    [*] NAND Flash Device on 형욱보드
    [*] Verify NAND page writes

Fliesystem
  <*> Yaffs filesystem on NAND

Save as poswatch_pro.menuconfig


[linux]>make clea
[linux]>make dep
[linux]>make uImage
-> yaffs 플래시파일시스템 지원 u-boot용 커널 생성
   : [linux]/arch/ppc/boot/images/vmlinux.UBoot
[linux]>make zImage
-> Poswatch openbios용 압축커널이미지(arch/ppc/boot/images/zImage.treeboot) 생성(http://www.geocrawler.com/archives/3/8358/2002/1/50/7622546/)


U-Boot를 yaffs를 지원하여 Stand-alone으로 동작하도록 수정
include/configs/형욱보드.h
mtd partition 0으로부터 리눅스 커널 이미지를 램으로 로드하여, 부팅.
/* autoboot command */
#define CONFIG_BOOTCOMMAND      "nand read 200000 4000 (vmlinux.UBoot사이즈);bootm 200000"

mtd partition 1의 yaffs.image를 root filesystem으로 인식.
#define CONFIG_BOOTARGS           "root=/dev/mtdblock1 rw"


yaffs rootfs 구성


directory 구성
yaffs : working dir
- rootfs_yaffs : 위에서 구성한 rootfs를 copy ( cp -dprR 이용)


$ cd rootfs_yaffs


mknod dev/mtd0 c 90 0
mknod dev/mtd1 c 90 1
mknod dev/mtdblock0 b 31 0
mknod dev/mtdblock1 b 31 1


$ vi etc/fstab
/dev/mtdblock1    / yaffs default 0 0


아래의 설정은 http://doc.kldp.org/KoreanDoc/html/Boot_Process-KLDP/inittabfile.html 참조.


vi etc/inittab
::sysinit:/etc/init.d/rcS 추가 (이상하게 앞의 si 키워드 없애야 동작함. 향후 검토)


vi etc/init.d/rcS 수정(맨앞)
/sbin/insmod yaffs.o : menuconfig에서 Loadable support>kernel module loader선택했다면 제외할것.
mount -t yaffs /dev/mtdblock1 / -> flash의 yaffs파일시스템이 /로 마운트


yaffs 이미지 작성.


yaffs/utils에서 yaffs 이미지 작성용 툴을 제공
mkyaffsimage : root filesystem 디렉토리로부터 NAND flash용 yaffs 이미지 작성
mkyaffs : flash erase


yaffs compile
yaffs/Makefile, yaffs/utils/Makefile을 아래와 같이 수정
KERNELDIR = [linux]
MAKETOOLS =
...
# USE_RAM_FOR_TEST = -DCONFIG_YAFFS_RAM_ENABLED


yaffs$ make
yaffs/utils$ make
http://62.49.201.250/balloon/releases/utils/mkyaffsimage 다운로드  
$ mv mkyaffsimage mkyaffsimage.ballon
Ihttp://www.intrinsyc.com/support/I-Linux/405-cube/cerfcube405ep.htm#misc/cd.htm으로부터 mkyaffsimage 다운로드
$ mv mkyaffsimage mkyaffsimage.cerf


$ mkyaffsimage.cerf rootfs_yaffs yaffs.image convert: NAND flash용 yaffs 이미지(yaffs.image)생성


U-Boot에 YAFFS 이미지 지원 NAND flash 처리루틴 추가 (cmd_nand.c 기반)
NAND flash 관련 명령어는 common/cmd_nand.c에서 정의됨
common/cmd_nand.c
U_BOOT_CMD(
        nand,   5,      1,      do_nand,
        "nand    - NAND sub-system\n",
        "info  - show available NAND devices\n"
        "nand device [dev] - show or set current device\n"
        "nand read[.jffs2[s]]  addr off size\n"
        "nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
        "    at offset `off' to/from memory address `addr'\n"
        "nand erase [clean] [off size] - erase `size' bytes from\n"
        "    offset `off' (entire device if not specified)\n"
        "nand bad - show bad blocks\n"
        "nand read.oob addr off size - read out-of-band data\n"
        "nand write.oob addr off size - write out-of-band data\n"
);
nand 관련 명령어 셋 컴파일되도록 설정

$ vi common/Makefile
COBJS = cmd_nand.o 추가
$ vi include/configs/WALNUT405.h : CFG_CMD_NAND 추가

#define CONFIG_COMMANDS        (CONFIG_CMD_DFL  | \
                                CFG_CMD_PCI     | \
                                CFG_CMD_IRQ     | \
                                CFG_CMD_NAND )
board/.../형욱보드.c
/* modified by hwjang : NAND initialization */
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
extern ulong
nand_probe(ulong physadr);

void
nand_init(void)
{
#define FLASH_BASE_ADDR     0xF0000000
        ulong totlen = 0;

        printf ("Probing at 0x%.8x\n", FLASH_BASE_ADDR);
        totlen = nand_probe (FLASH_BASE_ADDR);

        printf ("%4lu MB\n", totlen >>20);
}
#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */




$ vi include/configs/형욱보드.h : 각시스템의 설정에 맞게 각 매크로를 define해주세요.
/* modified by hwjang */
/*-----------------------------------------------------------------------
* NAND-FLASH stuff
*-----------------------------------------------------------------------
*/
#define CONFIG_NAND
#define CONFIG_YAFFS                    /* use yaffs filesystem on nand flash */

#define CFG_NAND_BASE                   0xF0000000
#define DCRN_CPC0_CGCR0                 0x0b1
#define GPIO0_TCR_ADDR                  0xEF600704
#define GPIO0_ODR_ADDR                  0xEF600718
#define GPIO0_IR_ADDR                   0xEF60071C

#define GPIO_MASK_NAND_FLASH_MEM        (1<<(31-15))

#define gpio_read()                     (*(volatile unsigned int*)GPIO0_IR)
#define gpio_write(n)                   (*(volatile unsigned int*)GPIO0_ODR_ADDR = (n))

#define CFG_MAX_NAND_DEVICE     1       /* Max number of NAND devices           */
#define SECTORSIZE 512

#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3

#define NAND_ChipID_UNKNOWN     0x00
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1

#define CFG_NAND_CE_SET         (CFG_NAND_BASE + 0x00080000)
#define CFG_NAND_CE_CLR         (CFG_NAND_BASE + 0x000A0000)
#define CFG_NAND_CMD_REG        (CFG_NAND_BASE + 0x00000001)
#define CFG_NAND_ADDR_REG       (CFG_NAND_BASE + 0x00000002)

#define NAND_DISABLE_CE(nand)    do { *(volatile __u8 *)(CFG_NAND_CE_CLR) = 0;} while(0)
#define NAND_ENABLE_CE(nand)     do { *(volatile __u8 *)(CFG_NAND_CE_SET) = 0;} while(0)
#define NAND_CTL_CLRALE(nandptr) do { ; } while(0)
#define NAND_CTL_SETALE(nandptr) do { ; } while(0)
#define NAND_CTL_CLRCLE(nandptr) do { ; } while(0)
#define NAND_CTL_SETCLE(nandptr) do { ; } while(0)
#define NAND_WAIT_READY(nand)    while ((gpio_read() & GPIO_MASK_NAND_FLASH_MEM) ? 0:1)

#define WRITE_NAND_COMMAND(d, adr) do{ *(volatile __u8 *)(CFG_NAND_CMD_REG) = (__u8)(d); } while(0)
#define WRITE_NAND_ADDRESS(d, adr) do{ *(volatile __u8 *)(CFG_NAND_ADDR_REG) = (__u8)(d); } while(0)
#define WRITE_NAND(d, adr) ( writeb(d, adr) )
#define READ_NAND(adr) ( readb(adr) )


$ vi lib_ppc/board.c : flash 초기화 안해줌(수정 가능)
/* modified by hwjang : no flash initialization */
#if 0
/* #if !defined(CFG_NO_FLASH) */
        puts ("FLASH: ");

        if ((flash_size = flash_init ()) > 0) {


YAFFS 이미지  Fusing 루틴 추가 (cmd_nand.c)
#  nand write.yaffs (yaffs.image가 로딩된 ram addr) (NAND flash offset) (yaffs.image 사이즈)
가 동작하도록 명령어 셋과 처리루틴 추가
YAFFS의 경우 U-Boot에서 지원하는 JFFS2와 동작하는 상황이 다르며, 아래사항을 처리해야 함
Page Write 시 OOB영역 처리 : yaffs.image는 data(1st/2nd half array, 512bytes) + oob(spare array, 16bytes)의 연속으로 구성되며, JFFS2와 다르게  spare area(OOB영역)에 yaffs.image의 값을 쓸 수 있도록 수정

ECC disable : YAFFS는 NAND_ECC_NONE모드
size 문제 : (yaffs.image 사이즈)는 oob영역까지 포함된 사이즈, U-Boot에서는 data영역만의 사이즈 기반(즉 FLASH address기반)으로 처리하므로, yaffs의 경우 이를 적당히 조절해야 함. 처리하지 않을 경우 의도보다 FLASH 영역을 넘어서 잘못된 값을 Fusing. bad block 발생.
nand write.yaffs 명령어셋 추가
#define NANDRW_YAFFS    0x08
nand write.yaffs 명령을 인식하고, nand_write_yaffs()를 호출하도록 설정.
int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
...
                else if (cmdtail && !strncmp(cmdtail, ".yaffs", 2))
                        cmd |= NANDRW_YAFFS;
...
}
/* cmd: 0: NANDRW_WRITE                 write, fail on bad block
*      1: NANDRW_READ                  read, fail on bad block
*      2: NANDRW_WRITE | NANDRW_JFFS2  write, skip bad blocks
*      3: NANDRW_READ | NANDRW_JFFS2   read, data all 0xff for bad blocks
*      7: NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP read, skip bad blocks
*      8: NANDRW_WRITE | NANDRW_YAFFS  write, yaffs // hwjang
*/
static int nand_rw (struct nand_chip* nand, int cmd,
            size_t start, size_t len,
            size_t * retlen, u_char * buf)
{
/* size관련처리 */
int pages_per_block = (nand->erasesize) / (nand->oobblock);
if (cmd & NANDRW_YAFFS) {
// len passed is yaffs image size (including oob_data).
// modified to size except oob_data to work properly in u-boot
        int num_pages_yaffs = len / (nand->oobblock + nand->oobsize);
        len = num_pages_yaffs << nand->page_shift;
}
..
             else if ((cmd == (NANDRW_WRITE | NANDRW_JFFS2)) || (cmd == (NANDRW_WRITE | NANDRW_YAFFS))) {
             //else if (cmd == (NANDRW_WRITE | NANDRW_JFFS2)) {
                                        /* skip bad block */
                                        start += erasesize;
                                        continue;
                                }
...
    else if (cmd & NANDRW_YAFFS) {
        ret = nand_write_yaffs (nand, start,
                   min(len, eblk + erasesize - start),
                   &n, (u_char*)buf, NULL);

        // hwjang :     yaffs image contains oob_data ( size : 16 Bytes in each page )
        //              so buf pointer should be increased to point at data_buf of the next block.
        buf += (pages_per_block << 4);

    }

}
nand->data_buf[]에 OOB영역까지 포함한 yaffs.image의 값을 할당하고, OOB영역까지 page programming되도록 설정
static int nand_write_yaffs (struct nand_chip* nand, size_t to, size_t len,
                           size_t * retlen, const u_char * buf, u_char * ecc_code)
{
        int i, page, col, cnt, ret = 0;
//hwjang
int pages_per_block = (nand->erasesize) / (nand->oobblock);

        /* Do not allow write past end of device */
        if ((to + len) > nand->totlen) {
                printf ("%s: Attempt to write past end of page\n", __FUNCTION__);
                return -1;
        }

        /* Shift to get page */
        page = ((int) to) >> nand->page_shift;

        /* Get the starting column */
        col = to & (nand->oobblock - 1);

        /* Initialize return length value */
        *retlen = 0;

        /* Select the NAND device */
#ifdef CONFIG_OMAP1510
        archflashwp(0,0);
#endif
        NAND_ENABLE_CE(nand);  /* set pin low */

        /* Check the WP bit */
        NanD_Command(nand, NAND_CMD_STATUS);
        if (!(READ_NAND(nand->IO_ADDR) & 0x80)) {
                printf ("%s: Device is write protected!!!\n", __FUNCTION__);
                ret = -1;
                goto out;
        }

        /* Loop until all data is written */
// hwjang :     yaffs image contains oob_data ( size : 16 Bytes in each page )
//              so additional length should be checked.
        while (*retlen < len + (pages_per_block << 4)) {

                /* Invalidate cache, if we write to this page */
                if (nand->cache_page == page)
                        nand->cache_page = -1;

                /* Write data into buffer */
                if ((col + len) >= nand->oobblock)
// hwjang :     write including oob_data in yaffs image
                        for (i = col, cnt = 0; i < nand->oobblock + nand->oobsize; i++, cnt++)
                                nand->data_buf[i] = buf[(*retlen + cnt)];
                else
                        for (i = col, cnt = 0; cnt < (len - *retlen); i++, cnt++)
                                nand->data_buf[i] = buf[(*retlen + cnt)];

                /* We use the same function for write and writev !) */
                ret = nand_write_page_yaffs (nand, page, col, i, NULL);

                if (ret)
                        goto out;

                /* Next data start at page boundary */
                col = 0;

                /* Update written bytes count */
                *retlen += cnt;

                /* Increment page address */
                page++;
        }

        /* Return happy */
        *retlen = len;

out:
        /* De-select the NAND device */
        NAND_DISABLE_CE(nand);  /* set pin high */
#ifdef CONFIG_OMAP1510
        archflashwp(0,1);
#endif
        return ret;
}


OOB영역에 접근하는 ECC관련코드를 제거(nand_write_page()와 비교해볼것).
timing 설정(아래참조)
static int nand_write_page_yaffs (struct nand_chip *nand,
                            int page, int col, int last, u_char * ecc_code)
{
        int i;
        unsigned long nandptr = nand->IO_ADDR;

        /* Prepad for partial page programming !!! */
        for (i = 0; i < col; i++)
                nand->data_buf[i] = 0xff;

        /* Postpad for partial page programming !!! oob is already padded */
        for (i = last; i < nand->oobblock; i++)
                nand->data_buf[i] = 0xff;

        /* Send command to begin auto page programming */
        NanD_Command(nand, NAND_CMD_READ0);
        NanD_Command(nand, NAND_CMD_SEQIN);
        NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);

        /* Write out complete page of data */
        for (i = 0; i < (nand->oobblock + nand->oobsize); i++)
                WRITE_NAND(nand->data_buf[i], nand->IO_ADDR);

        /* Send command to actually program the data */
        NanD_Command(nand, NAND_CMD_PAGEPROG);

udelay(300); // hwjang

        NanD_Command(nand, NAND_CMD_STATUS);
#ifdef NAND_NO_RB
        { u_char ret_val;

          do{
                ret_val = READ_NAND(nandptr);   /* wait till ready */
          } while((ret_val & 0x40) != 0x40);
        }
#endif
        /* See if device thinks it succeeded */
        if (READ_NAND(nand->IO_ADDR) & 0x01) {
                printf ("%s: Failed write, page 0x%08x, ", __FUNCTION__, page);
                return -1;
        }

#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
        /*
         * The NAND device assumes that it is always writing to
         * a cleanly erased page. Hence, it performs its internal
         * write verification only on bits that transitioned from
         * 1 to 0. The device does NOT verify the whole page on a
         * byte by byte basis. It is possible that the page was
         * not completely erased or the page is becoming unusable
         * due to wear. The read with ECC would catch the error
         * later when the ECC page check fails, but we would rather
         * catch it early in the page write stage. Better to write
         * no data than invalid data.
         */

        /* Send command to read back the page */
        if (col < nand->eccsize)
                NanD_Command(nand, NAND_CMD_READ0);
        else
                NanD_Command(nand, NAND_CMD_READ1);
        NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);

udelay(9); // hwjang

        /* Loop through and verify the data */
        for (i = col; i < last; i++) {
               if (nand->data_buf[i] != readb (nand->IO_ADDR)) {
                        printf ("%s: Failed write verify, page 0x%08x ", __FUNCTION__, page);
                        return -1;
                }
        }
#endif
        return 0;
}


형욱보드 설정에 맞춘 wait timing 세팅  
하드웨어 측정 결과
구분
하드웨어 R/B pin Busy timing
소스 설정값(udelay 적용값)

write
t_PROG = 180 us
300 us

erase
t_BER = 2000 us
2500 us

read
t_R = 7.20 us
9 us


$ vi common/cmd_nand.c
static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len,
                 size_t * retlen, u_char *buf, u_char *ecc_code)
{
...
                /* Send the read command */
                NanD_Command(nand, NAND_CMD_READ0);
                NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col);

udelay(9); // hwjang

                /* Read in a page + oob data */
                NanD_ReadBuf(nand, nand->data_buf, nand->oobblock + nand->oobsize);
...
}

static int nand_write_page (struct nand_chip *nand,
                            int page, int col, int last, u_char * ecc_code)
{
...
        /* Write out complete page of data */
        for (i = 0; i < (nand->oobblock + nand->oobsize); i++)
                WRITE_NAND(nand->data_buf[i], nand->IO_ADDR);

        /* Send command to actually program the data */
        NanD_Command(nand, NAND_CMD_PAGEPROG);

udelay(300); // hwjang

        NanD_Command(nand, NAND_CMD_STATUS);
...
}

static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len,
                         size_t * retlen, u_char * buf)
{
...
        if (nand->page256 && ofs + len > (ofs | 0x7) + 1) {
                len256 = (ofs | 0x7) + 1 - ofs;
                NanD_ReadBuf(nand, buf, len256);

                NanD_Command(nand, NAND_CMD_READOOB);
                NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff));
        }

udelay(9); // hwjang

        NanD_ReadBuf(nand, &buf[len256], len - len256);
...
}

static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len,
                  size_t * retlen, const u_char * buf)
{
...
        /* treat crossing 8-byte OOB data for 2M x 8bit devices */
        /* Note: datasheet says it should automaticaly wrap to the */
        /*       next OOB block, but it didn't work here. mf.      */
        if (nand->page256 && ofs + len > (ofs | 0x7) + 1) {
                len256 = (ofs | 0x7) + 1 - ofs;
                for (i = 0; i < len256; i++)
                        WRITE_NAND(buf[i], nandptr);

                NanD_Command(nand, NAND_CMD_PAGEPROG);

udelay(300);

                NanD_Command(nand, NAND_CMD_STATUS);
...
        for (i = len256; i < len; i++)
                WRITE_NAND(buf[i], nandptr);

        NanD_Command(nand, NAND_CMD_PAGEPROG);

udelay(300); // hwjang

        NanD_Command(nand, NAND_CMD_STATUS);
...
}

static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean)
{
...
        while(len) {
                /*mychip = &nand->chips[shr(ofs, nand->chipshift)];*/
                mychip = &nand->chips[ofs >> nand->chipshift];

                /* always check for bad block first, genuine bad blocks
                 * should _never_  be erased.
                 */
                if (ALLOW_ERASE_BAD_DEBUG || !check_block(nand, ofs)) {
                        /* Select the NAND device */
                        NAND_ENABLE_CE(nand);  /* set pin low */

                        NanD_Command(nand, NAND_CMD_ERASE1);
                        NanD_Address(nand, ADDR_PAGE, ofs);
                        NanD_Command(nand, NAND_CMD_ERASE2);
udelay(2500); // hwjang
                        NanD_Command(nand, NAND_CMD_STATUS);
...
}
NAND FLASH로부터 STAND-ALONE으로 동작
# tftpboot 200000 /tftpboot/vmlinux.UBoot
# tftpboot 400000 /tftpboot/yaffs.image
# nand erase (nand시작번지) (nand 사이즈)
# nand write 200000 4000 (vmlinux.UBoot 사이즈)
# nand write.yaffs 400000 190000 (yaffs.image 사이즈)
# reset
(재부팅)
# nand read 200000 4000 (vmlinux.UBoot사이즈);bootm 200000 실행되고

(콘솔메시지)
U-Boot 1.1.1 (Jun 30 2004 - 15:21:21)

CPU:   IBM PowerPC 405GPr Rev. B at 266.500 MHz (PLB=133, OPB=66, EBC=66 MHz)
       PCI sync clock at 33 MHz, internal PCI arbiter enabled
       16 kB I-Cache 16 kB D-Cache
Board: ### No HW ID - assuming WALNUT405
I2C:   ready
DRAM:  32 MB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
NAND:Probing at 0xf0000000
  16 MB
Hit any key to stop autoboot:  0
=> tftpboot 200000 /tftpboot/uImage
ENET Speed is 10 Mbps - HALF duplex connection
TFTP from server 192.168.1.210; our IP address is 192.168.1.200
Filename '/tftpboot/uImage'.
Load address: 0x200000
Loading: #################################################################
         #################################################################
         ############
done
Bytes transferred = 722310 (b0586 hex)
=> tftpboot 400000 /tftpboot/yaffs.image
ENET Speed is 10 Mbps - HALF duplex connection
TFTP from server 192.168.1.210; our IP address is 192.168.1.200
Filename '/tftpboot/yaffs.image'.
Load address: 0x400000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ############################################################
done
Bytes transferred = 3631056 (3767d0 hex)
=> nand write 200000 4000 b0586

NAND write: device 0 offset 16384, size 722310 ...  722310 bytes written: OK
=> nand write.yaffs 400000 190000 3767d0

NAND write: device 0 offset 1638400, size 3631056 ...  3521024 bytes written: OK
=> nand bad

Device 0 bad blocks:
0x00000000

=> reset

U-Boot 1.1.1 (Jun 30 2004 - 15:21:21)

CPU:   IBM PowerPC 405GPr Rev. B at 266.500 MHz (PLB=133, OPB=66, EBC=66 MHz)
       PCI sync clock at 33 MHz, internal PCI arbiter enabled
       16 kB I-Cache 16 kB D-Cache
Board: ### No HW ID - assuming WALNUT405
I2C:   ready
DRAM:  32 MB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
NAND:Probing at 0xf0000000
  16 MB
Hit any key to stop autoboot:  0

NAND read: device 0 offset 16384, size 2097152 ...  2097152 bytes read: OK
## Booting image at 00200000 ...
   Image Name:   Linux-2.4.24-pre2
   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
   Data Size:    722246 Bytes = 705.3 kB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK

...(중간생략)

NAND device: Manufacturer ID: 0xec, Chip ID: 0x73 (Samsung NAND 16MiB 3,3V)
Creating 3 MTD partitions on "NAND 16MiB 3,3V":
0x00004000-0x00190000 : "형욱보드 Linux Kernel Partition"
mtd: Giving out device 0 to 형욱보드 Linux Kernel Partition
0x00190000-0x00640000 : "형욱보드 Root Filesystem(YAFFS) Partition"
mtd: Giving out device 1 to 형욱보드 Root Filesystem(YAFFS) Partition
0x00640000-0x00fa0000 : "형욱보드 Configuration Partition"
mtd: Giving out device 2 to 형욱보드 Configuration Partition

...(중간생략)

yaffs: dev is 7937 name is "1f:01"
VFS: Mounted root (yaffs filesystem).
Freeing unused kernel memory: 100k init
serial console detected.  Disabling virtual terminals.
init started:  BusyBox v0.60.2 (2002.12.19-10:50+0000) multi-call binary

(none) login: root

$ ls
$ cd /tmp
$ ls
$ cat abcd > test.txt
cat: abcd: No such file or directory
$ echo abcd > test.txt
$ ls
test.tx
2006. 2. 6. 14:38
http://dirac.uos.ac.kr/linux/Old/HOWTO/Vim-HOWTO-3.html



source [color schema path]
2005. 11. 9. 02:48

ASCII Code

OldPapers/linux 2005. 11. 9. 02:48
Ascii Code
2005. 11. 9. 02:40

C Standard Lib.

OldPapers/linux 2005. 11. 9. 02:40
머 리눅스에서 man 치면 더 잘 나오지만..그래도..

1. 데이터 변환 함수
2. 디렉토리 조작 함수
3. 버퍼 조작 함수
4. 파일 조작 함수
5. stream 입출력 함수
6. Low level 입출력 함수
7. Mathematics
8. 메모리 조작 함수
9. 탐색과 정렬 함수
10. 문자열 조작 함수
11. 시간 함수
12. 문자 분류 및 변환 함수
13. 기타 함수


1. 데이터 변환 함수

문자나 문자열을 수치 값으로 변환시키거나 대문자를 소문자로 소문자를 대문자로 변환하는 함수로 stdlib.h에 정의되어 있다.

헤더 파일 : #include

atof
형식 : double atof(char *string)
설명 : 문자열을 부동소수점 값으로 변환하는 함수 부동소수점으로 변환할 수 없는 문자열인 경우 0을 반환한다.

atoi
형식 : int atoi(char *string)
설명 : 문자열을 정수 값으로 변환하는 함수, 변환할 수 없는 경우에는 0을 반환한다.

atol
형식 : int atol(char *string)
설명 : 문자열을 long integer값으로 변환하는 함수, 변환할 수 없는 경우에는 0을 반환한다.

itoa
형식 : char *itoa(int value, char *string, int radix)
설명 : 정수형 숫자를 문자열로 변환하는 함수

ltoa
형식 : char *ltoa(long value, char *string, int radix)
설명 ; long integer형 숫자를 문자열로 변환하는 함수

strtod
형식 : double strtod(char *string, char *endptr)
설명 : 문자열을 부동소수점 값으로 변환하는 함수, 실패한 경우 0을 반환한다. 변환할 수 없는 문자를 만난 경우, 읽기를 중단한다.

strtol
형식 : long strtol(char *string, char *endptr, int radix)
설명 : 문자열을 long integer형 숫자로 변환하는 함수, 변환할 수 없는 문자열인 경우 0을 반환한다.

strtoul
형식 : unsigned long strtoul(char *string, char *endptr, int radix)
설명 : 문자열을 unsigned long형의 숫자로 변환하는 함수, 변환할 수 없는 문자열인 경우 0을 반환한다.


2. 디렉토리 조작 함수

헤더 파일 : #include

chdir
형식 : int chdir(char *path)
설명 : 현재 디렉토리를 주어진 경로로 바꾸는 함수

getcwd
형식 : char *getcwd(char *path, int numchars)
설명 : 현재의 작업 디렉토리의 이름을 반환하는 함수

mkdir
형식 : int mkdir(char *path)
설명 ; 주어진 경로를 사용하여 디렉토리를 만드는 함수

rmdir
형식 : int rmdir(char *path)
설명 : 주어진 경로의 디렉토리를 삭제하는 함수


3. 버퍼 조작 함수

헤더 파일 : #include

memchr
형식 : void *memchr(void *s, int c, size_t n)
설명 : 버퍼에 문자를 찾는 함수

memcmp
형식 : int memcmp(void *s1, void s2, size_t n)
설명 : 두 버퍼를 비교하는 함수

memcpy
형식 : void *memcpy(void *dest, void *src, size_t n)
설명 : 버퍼의 내용을 복사하는 함수

memmove
형식 : void *memmove(void *dest, void *src, size_t n)
설명 : 바이트 수만큼 src버퍼에서 dest버퍼로 이동시키는 함수

memset
형식 : void *memset(void *s, int c, size_t n)
설명 : 주어진 문자로 버퍼로 채우는 함수


4. 파일 조작 함수

헤더 파일 : #include

chmod
형식 : int chmod(char *path, int pmode)
설명 : 파일의 permission을 바꾸는 함수

fstat
형식 : int fstat(int handle, struct stat *buffer)
설명 : 파일의 상태 정보를 가져오는 함수

remove
형식 : int remove(char *path)
설명 : 파일을 삭제하는 함수

rename
형식 : int rename(char *oldname, char *newname)
설명 : 파일의 이름을 바꾸는 함수

stat
형식 : int stat(char *path, struct stat *buffer)
설명 : 파일의 상태 정보를 가져오는 함수

umask
형식 : unsigned umask(unsigned pmode)
설명 : 파일의ㅣ permission을 mask시키는 함수

5. Stream 입출력 함수

헤더 파일 : #include

clearerr
형식 : void clearerr(FILE *file_pointer)
설명 : stream의 에러 지시자를 지우는 함수

fclose
형식 : int fclose(FILE *file_pointer)
설명 : 파일을 닫는 함수, 정상적으로 수행되면 0을 에러가 발생되면 EOF을 반환한다.

feof
형식 : int feof(FILE *file_pointer)
설명 : 파일의 끝을 검사하는 함수, 지정된 파일이 EOF이면 0이외의 값을 반환한다.

ferror
형식 : int ferror(FILE *file_pointer)
설명 : 파일의 입출력 동안 에러가 발생되었는지를 검사하는 함수, 에러가 있으면 0이외의 값을 반환한다.

fflush
형식 : int fflush(FILE *file_pointer)
설명 : 버퍼의 내용을 파일에 쓰는 함수, 정상적으로 수행이 끝나면 0을 반환하고 그 이외에는 EOF를 반환한다.

fgetc
형식 : int fgetc(FILE *file_pointer)
설명 : stream으로부터 한 문자를 가져오는 함수, 에러 발생이나 파일의 끝인 경우에는 EOF를 반환한다.

fgetpos
형식 : int fgetpos(FILE *file_pointer, fpos_t current_pos)
설명 : stream에서 현재 위치를 가져오는 함수

fgets
형식 : char *fgets(char *string, int maxchar, FILE *file_pointer)
설명 : 파일에서 문자열을 읽는 함수, 읽어들이는 단위는 EOF나 \n을 만나거나 n-1개의 문자 길이 만큼이다. 실패한 경우 NULL을 반환한다.

fopen
형식 : FILE *fopen(char *filename, char *access_mode)
설명 : 파일을 열기 위한 함수, 에러가 발생되면 NULL을 반환한다.

fprintf
형식 : int fprintf(FILE *file_pointer, char *format_string, args)
설명 : 파일에 주어진 형식으로 데이터를 쓰기 위한 함수, 정상적으로 수행이 되면 출력한 문자의 수를 반환한다. 만약 에러가 발생되면 EOF를 반환한다.

fputc
형식 : int fputc(int c, FILE *file_pointer)
설명 : 문자를 stream에 쓰기 위한 함수, 정상적으로 수행이 되면 출력한 문자의 수를 반환한다. 에러가 발생되면 EOF를 반환한다.

fputchar
형식 : int fputchar(int c)
설명 : 문자를 stdout에 쓰기 위한 함수

fputs
형식 : int fputs(char *string, FILE *file_pointer)
설명 : 문자열을 stream에 쓰기 위한 함수, 에러가 발생되면 EOF를 반환한다.

fread
형식 : size_t fread(char *buffer, size_t size, size_t count, FILE *file_pointer)
설명 : stream으로부터 unformatted data를 buffer에 쓰기 위한 함수, 읽어들인 블록의 수를 반환한다.

freopen
형식 : FILE *freopen(char *filename, char *access mode, FILE *file_pointer)
설명 : 파일 포인터를 다른 파일에 재 할당하기 위한 함수

fscanf
형식 : int fscaf(FILE *file_pointer, char *format string, args)
설명 : stream으로부터 formatted input을 읽기 위한 함수, stream파일에서 형식대로 읽혀진 데이터 수를 반환한다. format의 형식은 scanf()와 같다.

fseek
형식 : int fseek(FILE *file_pointer, long offset, int origin)
설명 : 파일의 현재 위치에서 새로운 위치로 변경하는 함수, 정상적으로 수행했을 경우 0을 반환한다.

fsetpos
형식 : int fsetpos(FILE *file_pointer, fpos_t *current pos)
설명 : 파일의 현재 위치에서 새로운 위치로 변경하는 함수

ftell
형식 : long ftell(FILE *file_pointer)
설명 : 파일에서의 현재 위치를 가져오는 함수 에러가 발생되면 -1을 반환한다.

fwrite
형식 : size_t fwrite(char *buffer, size_t size, size_t count, FILE *file_pointer)
설명 : 버퍼에 있는 unformatted data를 stream에 쓰기 위한 함수

getc
형식 : int getc(FILE *file_pointer)
설명 : 문자를 stream으로부터 읽기 위한 함수

getchar
형식 : int getchar(void)
설명 : srdin으로부터 문자를 읽기 위한 함수

gets
형식 : char *gets(char *buffer)
설명 : srdin으로부터 라인을 버퍼로 읽는 함수

printf
형식 : int printf(int c, FILE *file_pointer)
설명 : formatted output을 stdout에 쓰는 함수

putc
형식 : int putc(int c, FILE *file_pointer)
설명 : 문자를 steam에 쓰기 위한 함수

putchar
형식 : int putchar(int c)
설명 : 문자를 stdout에 쓰기 위한 함수

puts
형식 : int puts(char *string)
설명 : 문자열을 stdout에 쓰기 위한 함수

rewind
형식 : void rewind(FILE *file_pointer)
설명 : 파일을 rewind하기 위한 함수

scanf
형식 : int scanf(char *format_string, args)
설명 : stdin으로부터 formatted input을 읽는 함수

setbuf
형식 : void setbuf(FILE *file_pointer, char *buffer)
설명 : stream을 위해 새로운 버퍼를 지정하는 함수

setvbuf
형식 : int setvbuf(FILE *file_pointer, char *buffer, int buf_type, size_t buf_size)
설명 : 새로운 버퍼를 지정하고 제어하는 함수

sprintf
형식 : int sprintf(char *string, char *format_string, args)
설명 : formatted output을 문자열로 쓰는 함수

sscanf
형식 : int sscanf(char *buffer, char *format_string, args)
설명 : 문자열로부터 formatted input을 읽는 함수

tmpfile
형식 : FILE *tmpfile(void)
설명 : temporary 파일의 이름을 가져오기 위한 함수

tmpnam
형식 : char *tmpnam(char *file_name)
설명 : temporary 파일의 이름을 가져오기 위한 함수

ungetc
형식 : int ungetc(int c, FILE *file_pointer)
설명 : 문자를 stream의 버퍼에 되돌려 주는 함수


6. Low level 입출력 함수

헤더 파일 : #include 외에 #include , #include , #include , #include

close
형식 : int close(int handle)
설명 : unbuffered I/O를 위해 열어 놓은 파일을 닫기 위한 파일, 정상적으로 수행되었을 경우 0을 반환한다. 에러가 발생되었을 경우에는 -1을 반환한다.

creat
형식 : int creat(char *filename, int pmode)
설명 : 주어진 permission을 갖는 새로운 파일을 생성하기 위한 파일, 에러가 발생되었을 경우에는 -1을 반환한다.

eof
형식 : int eof(int handle)
설명 : 파일의 끝을 검사하는 파일, 지정된 파일의 현재 위치가 파일의 끝이면 1을 반환하고 그렇지 않을 경우에는 0을 반환한다.

lseek
형식 : long lseek(int handle, long offset, int orgin)
설명 : 파일의 주어진 위치로 이동하는 함수

open
형식 : int open(char *filename, int oflag, unsigned pmode)
설명 : low-level I/O를 위해 파일을 여는 함수

read
형식 : int read(int handle, char *buffer, unsigned length)
설명 : 파일로부터 바이너리 데이터를 버퍼로 읽는 함수, 읽은 문자의 바이트 수를 반환한다. 파일의 끝일 경우에는 EOF를 반환한다. 에러가 발생되면 -1을 반환한다.

write
형식 : int write(int handle, char *buffer, unsigned count)
설명 : 버퍼에 있는 바이너리 데이터를 파일에 쓰는 함수, 정상적으로 수행되었을 경우에는 쓴 문자의 바이트 수를 반환한다. 에러가 발생되었을 경우에는 -1을 반환한다.


7. Mathematics

헤더 파일 : #intclude

abs
형식 : int abs(int n)
설명 : 정수의 절대값을 구하는 함수

acos
형식 : double acos(double x)
설명 : x의 arc cosine을 계산하는 함수

asin
형식 : double asin(double x)
설명 : x의 arc sine을 계산하는 함수

atan
형식 : double atan(double x)
설명 : x의 arc tangent를 계산하는 함수

atan2
형식 : double atan2(double y, double x)
설명 : y/x의 arc tangent를 계산하는 함수

ceil
형식 : double ceil(double x)
설명 : x를 초과하는 가장 작은 integral 값을 구하는 함수

cos
형식 : double cos(double x)
설명 : cosine을 계산하는 함수

cosh
형식 : double cosh(double x)
설명 : x의 hyperbolic cosine을 계산하는 함수

div
형식 : div_t div(int number, int denom)
설명 : nunber/denom을 계산하여 몫과 나머지로 이루어진 구조체 div_t를 반환한다.
div_t의 형식은 다음과 같다.
type struct{
      int quot;
      int rem;
} div_t;

exp
형식 : x의 exponential을 계산하는 함수

fabs
형식 : double fabs(double x)
설명 : x의 절대값을 구하는 함수

floor
형식 : double floor(double x)
설명 : x보다 작은 가장 큰 integral값을 구하는 함수

fmod
형식 : double fmod(double x, double y)
설명 : x/y의 나머지를 반환하는 함수

frexp
형식 : double frexp(double x, int *expptr)
설명 : x를 mantissa와 exponent로 분리하는 함수

labs
형식 : labs(long n)
설명 : long integer의 절대값을 찾는 함수

ldexp
형식 : double ldexp(double x, int exp)
설명 : mantissa와 exponent로 값을 계산하여 반환하는 함수

ldiv
형식 : ldiv_t ldiv(long number, long denom)
설명 : long integer를 나눗셈하는 함수

log
형식 : double log(double x)
설명 : log(x)를 계산하는 함수

log10
형식 : double log10(double x)
설명 : base 10인 x의 log을 구하는 함수

modf
형식 : double modf(double x, double *inptr)
설명 : x를 fraction부분과 integer부분으로 분리하는 함수

pow
형식 : double pow(double x, double y)
설명 : x의 y승을 구하는 함수

rand
형식 : int rand(void)
설명 : 0에서 32사이의 random 정수를 구하는 함수

random
형식 : int random(int max_num)
설명 : 0에서 max_num)사이의 random 정수를 구하는 함수

randomize
형식 : void randomize(void)
설명 : random 수를 발생시키기 위해 seed를 지정하는 함수

sin
형식 : double sin(double x)
설명 : sine을 계산하는 함수

sinh
형식 : double sinh(double x)
설명 : x의 hyperbolic sine을 계산하는 함수

sqrt
형식 : double sqrt(double x)
설명 : x의 양의 제곱근을 계산하는 함수

srand
형식 : void srand(unsigned seed)
설명 : random 수 발생을 위해 새로운 seed를 지정하는 함수

tan
형식 : double tan(double x)
설명 : x의 tangent를 계산하는 함수

tanh
형식 : double tanh(double x)
설명 : x의 hyperbloic tangent를 계산하는 함수


8. 메모리 조작 함수

헤더 파일 : #include

calloc
형식 : void *calloc(size_t num_elem, size_t elem_size)
설명 : 배열을 할당하고 모든 원소를 0으로 초기화하는 함수

free
형식 : void free(void *mem_address)
설명 : 할당된 메모리 블록을 되돌려 주는 함수

malloc
형식 : void *malloc(size_t num_bytes)
설명 : 메모리 블록을 할당하는 함수

realloc
형식 : 메모리 블록을 재 할당하는 함수


9. 탐색과 정렬 함수

헤더 파일 : #include

bsearch
형식 : void *bsearch(void *key, void *base, size_t num, size_t width, int (*com pare)(void *elem1, void *elem2)
설명 : 이진 탐색을 수행하는 함수

qsort
형식 : void qsort(void *base, size_t num, size_t width, int (*compare)(void *elem1, void *elem2)
설명 : quick sort 알고리즘을 이용하여 정렬을 수행하는 함수


10. 문자열 조작 함수

헤더 파일 : #include

strcat
형식 : int strcat(char *string1, char *string2)
설명 : 두 문자열을 결합하여 하나의 문자열로 만드는 함수

strcmp
형식 : int strcmp(char *string1, char *string2)
설명 : 문자열을 알파벳 순서로 비교하는 함수, 두 문자열이 같으면 0을 반환한다. 만약 같지 않으면 다음과 같은 값을 반환한다.

string1 < string2 이면 음수 값을 반환
string1 > string2 이면 양수 값을 반환

strcpy
형식 : char *strcpy(char *string1, char *string2)
설명 : 문자열 string2를 string1으로 복사하는 함수

strerror
형식 : char *strerror(int errnum)
설명 : 주어진 에러 번호에 해당되는 에러 메시지를 가져오는 함수

strlen
형식 : int strlen(char *string)
설명 : 문자열의 길이를 구하는 함수 이때 NULL문자는 제외하고 길이를 구한다.

strncat
형식 : char *strncat(char *string1, char *string2, size_t n)
설명 : string2의 문자를 string1 끝에 붙이는 함수

strncmp
형식 : int strncmp(char *string1, char *string2, size_t n)
설명 : 두 문자열의 처음 n개의 문자를 비교하는 함수

strncpy
형식 : char *strncpy(char *string1, char *string2, size_t n)
설명 : string2의 처음 n개의 문자를 string1에 복사하는 함수

strnset
형식 : char *strnset(char *string, int c, size_t n)
설명 : 문자열의 처음 n개 문자를 c로 만드는 함수

strrchr
형식 : char *strrchr(char *string, int c)
설명 : 문자열에서 마지막에 나오는 문자 c를 찾는 함수 만약, 해당되는 문자가 발견되지 않은 경우에는 NULL을 반환한다.


11. 시간 함수

헤더 파일 : #include

asctime
형식 : char *asctime(struct tm *time)
설명 : struct tm 형식의 시간을 문자열로 바꾸는 함수

clock
형식 : clock_t clock(void)
설명 : clock tick으로 경과된 시간을 가져오는 함수

ctime
형식 : char *ctime(time_t *time)
설명 : 이진 시간을 문자열로 바꾸는 함수

difftime
형식 : double difftime(time_t time1, time_t time2)
설명 : 두 시간 사이의 차를 초단위로 계산하는 함수

gmtime
형식 : struct_tm *gmtime(time_t *time)
설명 : Greenwich Meam Time(GMT)을 tm structuregudtlr으로 가져오는 함수

localtime
형식 : struct tm *localtime(time_t *time)
설명 : local time을 tm structure형식으로 가져오는 함수

time
형식 : time_t time(time_t *timeptr)
설명 : GMT 1970년부터 경과된 현재 시간을 가져오는 함수


12. 문자 분류 및 변환 함수

헤더 파일 : #include

isalnum
형식 : int isalnum(int c)
설명 : c가 alphanumeric이면 참값을 반환

isalpha
형식 : int isalpha(int c)
설명 : c가 letter이면 참값을 반환

isascii
형식 : int isascii(int c)
설명 : c가 ASCII이면 참값을 반환

iscntrl
형식 : int iscntrl(int c)
설명 : c가 control 문자이면 참값을 반환

isdigit
형식 : int isdigit(int c)
설명 : c가 decimal digit이면 참값을 반환

isgraph
형식 : int isgraph(int c)
설명 : c가 graphic c문자이면 참값을 반환

islower
형식 : int islower(int c)
설명 : c가 소문자이면 참값을 반환

isprint
형식 : int isprint(int c)
설명 : c가 인쇄 가능한 문자이면 참값을 반환

ispunct
형식 : int ispunct(int c)
설명 : c가 punctuation 문자이면 참값을 반환

isspace
형식 : int isspace(int c)
설명 : c가 공백 문자이면 참값을 반환

isupper
형식 : int tsupper(int c)
설명 : c가 대문자이면 참값을 반환

isxdigit
형식 : int isxdigit(int c)
설명 : c가 hexadecimal digit이면 참값을 반환

toascii
형식 : int toascii(int c)
설명 : c를 ASCII로 변환하는 함수

tolower
형식 : tolower(int c)
설명 : c를 소문자로 변환하는 함수

toupper
형식 : int toupper(int c)
설명 : c를 대문자로 변환하는 함수


13. 기타 함수

다음은 화면 제어에 관한 라이브러리 함수들이다.

헤더 파일 : #include

clreol
형식 : void clreol(void)
설명 : 커서의 현 위치 행을 지우는 함수

clrscr
형식 : void clrscr(void)
설명 : 현재 사용 중인 윈도우를 지우고 커서를 왼쪽 상단으로 이동시키는 함수

deline
형식 : void deline(void)
설명 : 커서가 있는 행을 삭제하는 함수

gettext
형식 : int gettext(int left, int top, int right, int bottom, void *dest)
설명 : 지정된 텍스트 화면의 내용을 dest로 읽어 들이는 함수

gettextinfo
형식 : void gettextinfo(struct text_info r)
설명 : 현재의 텍스트 모드의 정보를 구조체 r로 읽어 들이는 함수, 구조체의 r의 형식은 다음과 같다.

struct text_info {
      unsigned char currmode;
      unsigned char screenheigh;
      unsigned char screenwidth;
      unsigned char normattr;
      unsigned char winleft;
      unsigned char wintop;
      unsigned char winright;
      unsigned char winbottom;
      unsigned char curx;
      unsigned char cury;
} *r;
2005. 11. 9. 02:15

ELF format

OldPapers/linux 2005. 11. 9. 02:15



The Executable and Linking Format (ELF)


 


The executable and linking format (ELF) was originally developed by Unix System Laboratories and is rapidly becoming the standard in file formats[8]. The ELF standard is growing in popularity because it has greater power and flexibility than the a.out and COFF binary formats[3]. ELF now appears as the default binary format on operating systems such as Linux, Solaris 2.x, and SVR4.  Some of the capabilities of ELF are dynamic linking, dynamic loading, imposing runtime control on a program, and an improved method for creating shared libraries[3]. The ELF representation of control data in an object file is platform independent, an additional improvement over previous binary formats. The ELF representation permits object files to be identified, parsed, and interpreted similarly, making the ELF object files compatible across multiple platforms and architectures of different size.

The three main types of ELF files are executable, relocatable, and shared object files. These file types hold the code, data, and information about the program that the operating system and/or link editor need to perform the appropriate actions on these files. The three types of files are summarized as follows:




  • An executable file supplies information necessary for the operating system to create a process image suitable for executing the code and accessing the data contained within the file.


  • A relocatable file describes how it should be linked with other object files to create an executable file or shared library.


  • A shared object file contains information needed in both static and dynamic linking.


In the next section we overview the ELF file format including a detailed description of each of the five section types that an ELF file might include. These five types are (1) the ELF header, (2) the program header table, (3) the section header table, (4) the ELF sections, and (5) the ELF segments. In Section 2.4.2, we describe the representation of data in an ELF file. The interested reader may consult reference [8] for additional information about the ELF format.