ST 를 기반으로 하는 소스 프로그램(DACS1000, DAC5000)의 전반적인 시스템 전체를 이해하도록 하기 위한 내용으로 구성되어 있다.
문서의 차례는 시스템의 초기화에서 부터 응용 프로그램 단계 순으로 살펴 볼 것이다.
어떤 프로그램이 되었던 간에 가장 기본이 되는 것을 꼽으라면, 단연 초기화 라고 말하고 싶다. 이 문서는 ST 소스를 기반으로 하는 시스템이기 때문에, 앞으로의 모든 예제는 ST 소스가 될 것이다.
ST 의 경우, 툴셋(toolset)을 제공한다. 우리가 흔히 얘기하는 툴 체인이라고 하는 것인데, 여기에는 ST 에서 제공하는 커널과 크로스 컴파일러가 포함되어 있다. 모든 개발은 바로 이 것을 토대로 하게된다. 하지만, 이 것만으로는 실질적인 개발을 하긴 어렵다. 제공하는 커널 소스로는 각각의 디바이스를 제어하기 힘들기 때문이다. 그래서 ST 에서는 각 MCU 의 architecture 에 맞는 디바이스 드라이버를 제공한다. 5517ref 나 7020brick 이 그것이다.
각 디바이스마다 여러가지로 제어할 수 있는 API 를 제공한다.
소스 컴파일을 하게 되면, .map 파일이 만들어진다. 이것은 프로그램이 실행될 때, 어떤 식으로 각 영역이 잡히는 지를 실질적으로 알려주는 것인데, 각 영역을 크기(범위)를 임의로 지정해 줄 수 있다. 그렇다면, 어디서 지정할까? 바로 config 디렉토리에 있는 mb382_um.cfg 파일과 system/section.c 파일에서 지정해주고, 이외의 나머지 영역은 5517 의 데이터시트를 따른다.
먼저, mb382_um.cfg 파일을 살펴보자!
... ... ... ## External Memory address & size // SDRAM 주소 설정 EXTMEM_BASE = 0xC0300000 // 시작 주소 EXTMEM_SIZE = (13 * M) // 전체 용량 ## Address & size of Debug Traphandler area (place at end of External Memory) TH_SIZE = 0x400 TH_BASE = (EXTMEM_BASE + EXTMEM_SIZE - TH_SIZE) TRACE_BUFFER_SIZE = (64 * K) TRACE_BUFFER_BASE = (EXTMEM_BASE + EXTMEM_SIZE - TH_SIZE - TRACE_BUFFER_SIZE) ## Addresses & sizes of cached & non-cached areas of External Memory. ## The area defined by NCACHE_BASE and NCACHE_SIZE will contain the ## 'Non-cached' memory partition. The size of this area may be reduced if ## required (NB subject to hardware limitations!) ## IMPORTANT: These definitions reflect the constants of the same ## name in mb382.h. If one of these files is modified then the ## other must be manually updated accordingly. */ NCACHE_SIZE = (512 * K) NCACHE_BASE = EXTMEM_BASE CACHED_BASE = (EXTMEM_BASE + NCACHE_SIZE) CACHED_SIZE = (EXTMEM_SIZE - NCACHE_SIZE - TH_SIZE - TRACE_BUFFER_SIZE) proc Mem5517Space progSMI BootFromFlash { if ($# != 0) { progSMI = $1 } if ($# >= 2) { BootFromFlash = $2 } ## This procedure calls proc STi5517MB382_noexternal in dcu_mb382.cfg ## which does the "chip STi5517" command (supports DCU3) STi5517MB382_noexternal (1) (progSMI) ## Call clocks configuration procedure (in clks_5516.cfg) setup_clock_gen ## define memory areas memory NONCACHED (NCACHE_BASE) (NCACHE_SIZE) RAM memory EXTERNAL (CACHED_BASE) (CACHED_SIZE) RAM memory mytracebuffer (TRACE_BUFFER_BASE) (TRACE_BUFFER_SIZE) RAM memory TRAPHANDLER (TH_BASE) (TH_SIZE) DEBUG memory SMI_TOP 0xC1000000 (16*M) RAM memory STEM0 0x50000000 (32*M) DEVICE memory STEM1 0x60000000 (64*M) DEVICE ##TK memory STEM1 0x60000000 (32*M) DEVICE memory AT_DVB 0x70000000 (240*M) DEVICE memory FLASH 0x7F800000 (8*M) ROM memory SDRAM 0xC0000000 (16*M) RAM ##set up code placement sections place <startup_section> EXTERNAL place <shutdown_section> EXTERNAL place def_code EXTERNAL place def_data EXTERNAL place def_bss EXTERNAL place def_const EXTERNAL place os20_th_code EXTERNAL place os20_task_queue INTERNAL place os20_th_data INTERNAL place os20_root_tdesc INTERNAL place os20_int_complex_text EXTERNAL place os20_int_moderate_text EXTERNAL place os20_int_simple_text EXTERNAL ## Section for partitions in internal (on-chip) memory. place internal_section INTERNAL place internal_section_noinit INTERNAL -noinit ## Section for partitions in general external (off-chip) memory. place system_section EXTERNAL place system_section_noinit EXTERNAL -noinit ## Section for non-cached partitions. place ncache_section NONCACHED -noinit place ncache2_section SMI_TOP -noinit ## bootdata location changes if FLASH hex image if (BootFromFlash == 1) { bootdata FLASH } else { bootdata EXTERNAL } ## divide the stack and heap stack EXTERNAL heap EXTERNAL ... ... ...
다른 문서에서도 많이 설명을 했기 때문에, 여기서 따로 설명은 하지 않겠다. 유의해서 볼 것은 메모리 맵에서 할당된 사이즈와 여기서 지정한 사이즈가 동일한지 여부를 확인하는 것과, 각 영역의 이름과 여기서 지정한 이름이 같은지 확인하는 것이다.
mb382_um.cfg 에서 지정하지 않았는 데도, 메모리 맵에서는 할당된 영역이 몇 있을 것이다. 그것들은 5517 데이터 시트의 'Memory Map' 부분을 보면 이해가 갈 것이다. 여기에서도 지정되지 않은 영역이 메모리 맵에 있을 것이다. 그것은 system/section.c 파일에 정의되어 있다.
DAC5000 의 초기화 루틴 중에 가장 먼저 수행되는 것이 바로 section_setup() 이다.
다음은 프로그램 소스의 일부분이다.
#define SYSTEM_MEMORY_SIZE 0x300000 /* 3 Mb */ // 메모리 맵에서 system_section 사이즈 설정 #define NCACHE_MEMORY_SIZE 512*1024 /* 512Kb */ // 512 보다 크게 잡으로 컴파일 에러 //#define NCACHE_MEMORY_SIZE 2*1024*1024 /* 512Kb */ static unsigned char InternalMemory[ST20_INTERNAL_MEMORY_SIZE - 1200]; // ST20_INTERNAL_MEMORY_SIZE = 0x1EC0 메모리 맵에서 INTERNAL 영역 사이즈 설정 static unsigned char SystemMemory[SYSTEM_MEMORY_SIZE]; static unsigned char NcacheMemory[NCACHE_MEMORY_SIZE]; //not equel 7020 static ST_Partition_t TheInternalPartition; static ST_Partition_t TheSystemPartition; static ST_Partition_t TheNcachePartition; #pragma ST_section (InternalMemory, "internal_section") #pragma ST_section (SystemMemory, "system_section") #pragma ST_section (NcacheMemory , "ncache_section") ST_Partition_t *InternalPartition = &TheInternalPartition; ST_Partition_t *SystemPartition = &TheSystemPartition; ST_Partition_t *NcachePartition = &TheNcachePartition; /* OS20 */ ST_Partition_t *internal_partition = &TheInternalPartition; ST_Partition_t *system_partition = &TheSystemPartition; ST_Partition_t *ncache_partition = &TheNcachePartition; /* Functions -------------------------------------------------------------- */ /*------------------------------------------------------------------------- * Function : SECTIONS_Setup * setup partition sections; * Input : None * Output : * Return : Error Code * ----------------------------------------------------------------------*/ ST_ErrorCode_t SECTIONS_Setup(void) { (void) partition_init_simple(&TheInternalPartition, (U8 *)InternalMemory, sizeof(InternalMemory)); (void) partition_init_heap( &TheSystemPartition, (U8 *)SystemMemory, sizeof(SystemMemory)); (void) partition_init_heap( &TheNcachePartition, (U8 *)NcacheMemory , sizeof(NcacheMemory)); }
위에서 알아본 것과 같이 메모리맵이 완성되면, 실제적인 부팅 프로세스가 수행된다.
ST_ErrorCode = SECTIONS_Setup(); /* memory partition initialisation */ if (ST_ErrorCode != ST_NO_ERROR) return(ST_ErrorCode); ST_ErrorCode = BOOT_Setup(); /* OS initialisation */ if (ST_ErrorCode != ST_NO_ERROR) return(ST_ErrorCode); /* Get clock info structure - for global use */ (void) ST_GetClockInfo(&ST_ClockInfo); ST_ErrorCode = PIO_Setup(); if (ST_ErrorCode != ST_NO_ERROR) return(ST_ErrorCode); ST_ErrorCode = UART_Setup(); /* UART Needs PIO */ if (ST_ErrorCode != ST_NO_ERROR) return(ST_ErrorCode); /* --- No Calls to STTBX I/O functions before here --- */ ST_ErrorCode = TBX_Setup(); /* Needs UART if DVD_IO set to UART */ if (ST_ErrorCode != ST_NO_ERROR) { printf("TBX_Setup Error!\n"); return(ST_ErrorCode); } ST_ErrorCode = EVT_Setup(); if (ST_ErrorCode != ST_NO_ERROR) { printf("EVT_Setup Error!\n"); return(ST_ErrorCode); } ST_ErrorCode = I2C_Setup(); /* Needs PIO */ if (ST_ErrorCode != ST_NO_ERROR) { printf("I2C_Setup Error!\n"); return(ST_ErrorCode); } ST_ErrorCode = CFG_Setup(); if (ST_ErrorCode != ST_NO_ERROR) { printf("CFG_Setup Error!\n"); return(ST_ErrorCode); }
section.c 파일은 앞에서 설명했기 때문에, 이번에는 system/boot.c 에 대해서 설명하겠다.
... ... memset((void *)&BootParams, 0, sizeof(STBOOT_InitParams_t)); BootParams.CacheBaseAddress = (U32*) ST5517_CACHE_BASE_ADDRESS; // 0x30004000 (5517 데이터 시트 참조) BootParams.SDRAMFrequency = SDRAM_FREQUENCY; // 100 MHz #ifdef ICACHE_ENABLE BootParams.ICacheEnabled = TRUE; #else BootParams.ICacheEnabled = FALSE; // 실행됨 #endif #ifdef DCACHE_ENABLE BootParams.DCacheMap = DCacheMap; // AVMEM 메모리 할당 #else BootParams.DCacheMap = NULL; // 실행됨 #endif /* Autodetect Backend type and revision */ BootParams.BackendType.DeviceType = STBOOT_DEVICE_UNKNOWN; BootParams.BackendType.MajorRevision = STBOOT_REVISION_UNKNOWN; BootParams.BackendType.MinorRevision = STBOOT_REVISION_UNKNOWN; #if defined(mb282b) BootParams.MemorySize = STBOOT_DRAM_MEMORY_SIZE_64_MBIT; #elif defined(mb231) || defined(mb275) || defined(mb295) || defined (mb290) BootParams.MemorySize = STBOOT_DRAM_MEMORY_SIZE_32_MBIT; #else BootParams.MemorySize = STBOOT_DRAM_MEMORY_SIZE_32_MBIT; // 선택됨 #endif BootParams.IntTriggerMask = 0; /* Not used today */ BootParams.IntTriggerTable_p = NULL; /* Not used today */ ErrCode = STBOOT_Init(BOOT_DeviceName, &BootParams); ... ...
여기서는 SDRAM 의 설정과 ICACHE, DCACHE 에 대한 설정을 한다.
여기까지가 내가 생각하는 부팅루틴이다.