ST STB 시스템의 이해
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 에 대한 설정을 한다.
여기까지가 내가 생각하는 부팅루틴이다.