앞에서의 플래시 문서를 포함한 전체적인 플래시의 내용을 정리한 문서이다.
알아야 할 것들
- flash datasheet
- flash 관련 API
데이터 시트가 왜 필요한지 의문을 가질지도 모르겠다. 하지만, 정말 중요하다. 데이터 시트에는 플래시의 동작과 커맨드, Manufactuer Code 등 많은 정보를 가지고 있다.
또한 이 것을 보고, 현재 쓰고 있는 플래시의 방식이 top 또는 bottom 인지 알아야 한다. 아래 표의 정보를 데이터 시트를 통해 알 수 있다.
모델명 | M29W160ET(T는 top 방식을 뜻함) |
배속 | X16(16bit access) |
Manufacturer Code | 0020h |
Device Code | 22C4h |
위의 모델명을 참고하여, top 방식의 블럭을 설정하면 된다. 또한 우리는 16bit access 를 한다. 기본적으로 8bit 도 지원하지만, CPU 칩 회로도 상 불가능하다. Manufacturer, Device Code 는 플래시 테스트 프로그램을 통해서 확인할 수 있다. 데이터 시트에 나온 커맨드(명령을) 특정 번지에 넣어주면, 읽을 수 있다. 이를 통해 초기 플래시 디버깅도 가능하다.
이제 플래시를 read/write 하는 프로그램을 통해 확인해보자!!
플래시 프로그램 분석
일단 가장 기본이 되는 main.c 부터 살펴보자!!
U8 temp[20]; // 플래시에 넣을 Data 를 배열로 정의 temp[0] = 't'; // test 를 data 에 입력 temp[1] = 'e'; temp[2] = 's'; temp[3] = 't'; FLASH_Initx(); // 플래시 디바이스 초기화 FLASH_Open(); // 디바이스 열기 WriteBlock(1, temp, 4); // 1번 블럭에 'test' 를 4 만큼 쓴다.
위의 설명을 봐도 그렇지만, 어떤 디바이스를 사용하려면, 우선 초기화(init) 하고 열기(open)를 해주어야 한다. 이 동작이 끝나면, 이제 사용할 준비가 끝난 것이다. 그리고 나서, 플래시를 읽고 쓸수 있다. 위에서 선언해준 배열은 플래시에 쓸 데이터이다. 여기서는 'test' 라는 문자를 넣었다.
이제 위에서 호출한 함수들을 하나하나 살펴보자!!
ST_ErrorCode_t FLASH_Initx()
ST_ErrorCode_t FLASH_Initx() { ST_ErrorCode_t ErrCode; STFLASH_InitParams_t InitParams; // partition_init_heap( &TheSystemPartition, (U8 *)SystemMemory, sizeof(SystemMemory)); printf("Start flash init!\n"); InitParams.DeviceType = DEVICE_TYPE; // STFLASH_M29W160BT // if ( BankNum == BANK0 ) // { InitParams.BaseAddress = (U32*)0x7f800000;//STFLASH_BANK_0_BASE; 시작 주소 InitParams.VppAddress = (U32*)NULL; // } InitParams.MinAccessWidth = MIN_ACCESS_WIDTH; // 16bit InitParams.MaxAccessWidth = MAX_ACCESS_WIDTH; // 16bit InitParams.NumberOfBlocks = NUM_BLOCKS; InitParams.Blocks = BlockData_s; // 35 InitParams.DriverPartition = SystemPartition; ErrCode = STFLASH_Init(FLASHDeviceName[0], &InitParams ); // ST 에서 제공하는 함수 호출 if(ErrCode!=ST_NO_ERROR) { printf("Init Error!\n"); return (ErrCode); } else printf("Flash init sucess!\n"); STTBX_Print(("STFLASH_Init(%s)=%s\n", FLASHDeviceName[0], GetErrorText(ErrCode) )); return ( ErrCode ); } /* end FLASH_Init */
ST_ErrorCode_t FLASH_Open()
ST_ErrorCode_t FLASH_Open() { ST_ErrorCode_t ErrCode; STFLASH_OpenParams_t OpenParams; ErrCode = STFLASH_Open(FLASHDeviceName[0], &OpenParams, &FLASHHnd); // ST 에서 제공하는 함수 호출 STTBX_Print(("STFLASH_Open(%s)=%s\n", FLASHDeviceName[0], GetErrorText(ErrCode) )); if(ErrCode!=ST_NO_ERROR) { GeneralError(ErrCode); printf("Open Error!\n"); return (ErrCode); } return ( ErrCode ); } /* end FLASH_Open */
BOOL WriteBlock()
BOOL WriteBlock(U8 blockId, U8* data, U32 len) // 몇 번째 블럭인지, 배열단위의 데이터, 길이 { ST_ErrorCode_t errCode; U32 uWriteLen,re; errCode = STFLASH_Erase( FLASHHnd, // ST 에서 제공한 지우는 함수 0+(0x00010000*blockId), // 위의 블럭 단위로 되어 있다. 0x00010000); if(errCode!=ST_NO_ERROR) { GeneralError(errCode); printf("\nRease Error!\n"); return false; } else printf("Rease Sucess Block %d\n",blockId); errCode = STFLASH_Write( FLASHHnd, // ST 에서 제공하는 쓰는 함수 0+(0x00010000*blockId), // 블럭 단위 data, len, &uWriteLen ); if(errCode!=ST_NO_ERROR) { GeneralError(errCode); printf("Write Error!\n"); return false; } else printf("Write Sucess Block %d adress %x offset %x size %d\n",blockId,0x7fe00000+(0x00010000*blockId),0x00010000*blockId,uWriteLen); for(re=0;re<len;re++) printf("%x ",data[re]); printf("\n\n"); return true; }
위의 프로그램에서 볼 수 있듯이, 플래시는 블럭(block)단위로 access 한다. 그리고 반드시 write 하기 전에는 해당 블럭을 erase 한다. 내가 예전에 쓰던 프로그램은 직접 주소를 넣어서 write 하는 프로그램이다. 그 직접 주소를 넣을 때는 블럭의 맨 처음 주소를 넣어야 한다.
STFLASH_Block_t BlockData_s[NUM_BLOCKS] = { { 0x00010000, STFLASH_MAIN_BLOCK },/* 0 */ { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK }, { 0x00010000, STFLASH_MAIN_BLOCK },/*64k*/ { 0x00008000, STFLASH_MAIN_BLOCK },/* 32k*/ { 0x00002000, STFLASH_PARAMETER_BLOCK }, { 0x00002000, STFLASH_PARAMETER_BLOCK },/*8k*/ { 0x00004000, STFLASH_BOOT_BLOCK } }; /* 16k */ /*34*/