Table of Contents

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