[TC3xx] 3. Tricore Start-up Sequence

비트 앤 와트·2024년 12월 18일
0

Tricore

목록 보기
3/3

소프트웨어 스타트업 시퀀스를 이해하기 위해서는 마이크로컨트롤러에 전원이 어떻게 공급되고, 전원이 공급되는 순간 어떤 일이 일어나는지 파악해야 한다. 이러한 내용은 Application User Manual3. AURIX TC3XX FirmwarePMS (Power Management System) 섹션에 상세히 기술되어 있으며, 인피니언의 AP32381에서도 다루어지고 있다. 본 글에서는 AP32381의 내용을 중심으로 User Manual을 정리한다.

전체적인 개념을 명확히 이해하기 위해서는 먼저 용어들을 정리할 필요가 있다. 리셋초기화와 같은 단어들은 종종 혼용되기 때문에, 이를 명확히 정의하여 스타트업 시퀀스를 이해하는 데 어려움이 없도록 한다.

Reset (재설정)

시스템을 정의된 초기 상태로 복귀시키는 과정이다. 이 과정에서 모든 레지스터와 주요 하드웨어 모듈들이 초기화되며, 시스템 클럭과 메모리 상태도 초기화된다. 리셋은 시스템이 실행 준비를 하기 전의 상태를 의미한다.

Initialize (초기화)

시스템이 동작할 준비를 위해 필요한 설정 값을 적용하는 과정이다. 리셋 후, 시스템은 구체적으로 사용할 하드웨어와 소프트웨어 설정을 구성한다. 여기에는 메모리, 클럭, 인터럽트 설정 등이 포함된다.


1. Aurix TC3xx Start-up Sequence 개요

Aurix TC3xx의 스타트업 과정은 크게 다섯 단계로 나눌 수 있다.

1.1 RESET 단계

시스템을 초기 상태로 되돌려 놓는 단계이다. 이 과정에서는 Power On Reset, System Reset, Application Reset 등이 트리거로 작용한다. 리셋을 통해 시스템은 정상 동작을 준비하게 된다.

1.2 Analog Power

외부 전원이 내부 전압 레일(5V, 3.3V, 1.3V)에 공급되며, 마이크로컨트롤러는 리셋 상태에서 벗어난다. Analog Power Up이 완료되는 순간, 리셋이 종료되고 Initialize 단계로 넘어간다.

1.3 Boot

리셋 후 가장 먼저 실행되는 Infineon 제공 코드로, Flash 메모리 및 RAM 설정 등 하드웨어 초기화를 수행한다.

1.4 Application Start-up Software

Application 소프트웨어 시작을 위한 초기화가 진행된다. 이 과정까지를 스타트업 시퀀스라고 할 수 있으며, 이후 단계부터는 사용자 코드가 실행된다.

1.5 Application Software

최종적으로 실제 Application 코드가 실행되며, 제어가 사용자 코드로 넘어가 시스템이 정상적으로 동작한다.

앞으로 각 단계에서 수행되는 구체적인 과정을 자세히 살펴본다.

2. Tricore의 RESET

Reset (리셋 / 재설정)

Start-up Sequence의 트리거, 즉 첫 시작이 바로 Reset (재설정) 이다. 리셋의 종류는 크게 1. Power On Reset과 2. System Reset, 3. Application Reset 세가지로 분류하기도 하는데, System Reset에서 Warm Reset을 따로 빼서 네가지로 분류하기도 한다. 각각의 리셋을 간단히 다음과 같이 설명 할 수 있다.

  1. Cold Power On Reset : 마이크로컨트롤러에 처음 전원이 공급 될 때 트리거됨.

  2. System Reset : 전원이 공급된 상태에서 내부/ 외부의 신호 (e.g. 와치독, 소프트웨어 명령 , 외부핀) 등으로 트리거 됨.

  3. Application Reset : Application S/W나 특정 하드웨어 이벤트로 트리거 됨.

2.1. Cold Power On Reset

Cold Power On Reset은 마이크로컨트롤러 또는 외부 PMIC(Power Management IC)를 통해 전원이 공급되지 않다가, 마이크로컨트롤러의 전원 핀(VEXT)에 전원이 들어오는 순간 발생하는 리셋이다. 즉, VEXT의 전원 공급이 완전히 차단된 후 다시 전원이 공급될 때만 발생하는 리셋이다.

이 리셋은 RAM부터 모든 주변 장치(Peripheral)까지를 초기화하는 가장 큰 범위의 리셋 이벤트임.

Cold Power On Reset이 발생하는 조건:

  • Start-Up: 마이크로컨트롤러에 전원이 처음 공급될 때.
  • VEXT 전원: 공급 전원이 3.0V 미만일 때.
  • VDDP3 전원: 공급 전원이 3.0V 미만일 때.
  • VDD 전원: 공급 전원이 1.125V 미만일 때.

Cold Power On Reset이 미치는 영향:

  • 모든 레지스터 초기화: 모든 레지스터 값이 초기 상태로 돌아감.
  • Flash 메모리 리셋: Flash 메모리가 초기화됨.
  • RAM 영역 비활성화: RAM이 비활성화 상태로 전환됨.
  • 클럭 시스템 초기화: 클럭 시스템이 기본 상태로 초기화됨.

Cold Power On Reset은 시스템이 전원 공급이 처음 시작될 때나, 전원 공급에 이상이 발생해 전압이 특정 수준 이하로 떨어질 때 자동으로 발생하는 중요한 초기화 단계임.

2.2 Warm Power-on Reset

Warm Power on Reset은 이미 전원이 공급되고 있는 상태에서 발생하는 리셋을 의미한다. Active Low인 PORST (Power on Reset Request Trigger) 핀에 0[V]가 인가되면 리셋이 발생한다.

  • PORST pad asserted

Cold Reset v.s. Warm Reset.

2.3 System Reset (Warm Power on Reset)

시스템 리셋은 일반적으로 마이크로컨트롤러에 전원이 공급되고 있는 상태에서 발생하는 초기화를 의미한다. 시스템 리셋을 트리거 할 수 있는 소스는 다음과 같다. Boot Firmware가 시스템 리셋을 Warm-Power on Reset으로 부른다. System Reset은 전원시스템 / 디버그 시스템 / 리셋 설정 레지스터의 초기화에 관여하지 않는다.

시스템 리셋 트리거 소스

  • Internal Signal (Hardware / Software)
  • External Hardware Signals
    - ESR0/ ESR1
    - SMU
    - WatchDog via SMU
    - Software Reset

2.4 Application Reset

마이크로컨트롤러가 동작중인 상태에서 발생하는 리셋이벤트를 의미함. 내부 하드웨어 / 소프트웨어 혹은 외부 하드웨어 시그널을 통해 트리거 할 수 있으며, 내부 페리퍼럴 및 CPU들을 초기화 함.

  • ESR0/ ESR1
  • SMU
  • WatchDog via SMU
  • Software Reset
  • Tuning Protection

이렇게 Reset State에서 Release되기 위해서는 PowerRail에 전압이 인가되고, 셀프 전원 모니터링 테스트를 통과해야한다. 이 다음 단계는 Analogue Power Up 단계가 되겠으며 다음 글에서 알아보도록 한다.

3. 아날로그 Power-Up 시퀀스

3.1개요

System의 Reset이후 (초기화) 이후에 Analogue Power Up 시퀀스가 이어지게 된다. 전체적인 플로우로 보자면 Reset 이후 Analogue Power Up으로 이어지는게 스타트업 시퀀스의 일부라고 볼 수 있다.아날로그 Power-Up 시퀀스는 외부에서 공급되는 전원이 System Reset상태에서 실제로 Code 영역의 Start-up 으로 진입하기 전, 외부 전원공급이 정상적으로 수행되어서 초기화가 되기 위한 전원 Power up 과정으로 이해 할 수 있다. 본 글에서는 Tricore의 Reset 상태가 desserted 되고 Analogue 전원 Power up이 되는 전반적인 과정을 살펴보도록 한다.

3.2Tricore 전원공급 체계

이러한 내용을 이해하기 전, Tricore의 전원 공급체계에 대해서 간단히 살펴볼 필요가 있다. Tricore에서는 다음과 같이 총 세개의 대표적 전압이 있다.
1) 5V
2) 3.3V
3) 1.25V

이때 필요에 따라서 위 세가지중 5V 또는 3.3V 중 한개만을 공급하는방식, 또는 위 세가지 전원중 일부 두개 , 혹은 세개를 모두다 외부 PMIC에서 Regulate하여 공급하는 방식 등 총 다섯가지의 Varilation이 존재하게 된다.

한편 외부 전원 5V나 3.3V를 이용해서 1.25V를 StepDown하는 컨버터의 명칭을 EVRC (Embedded Voltage Regulator Converrter)라고 부르며, EVRC컨버터는 다음과 같은 Half-Brige로 구성된 컨버터 토폴로지를 사용하며 외부의 인덕터, 스위치, 커패시터를 필요로 한다.

단독으로 입력되는 5V로 부터 3.3V를 생성할 수 있는 컨버터도 존재한다. 이 컨버터의 이름은 EVR33으로, Embedded Voltage Regulator 3.3의 약자이다. 선형컨버터로, 외부 스위치나 소자를 별도로 불필요로 한다.

대표적인 내장 컨버터 EVR33과 EVRC를 사용하여 외부 단일 전원을 공급받아서 내장 컨버터를 활용한 전원구동이 가능한 옵션이 앞서 설명한바와 같이 존재하며, 다음과 같이 총 다섯가지의 조합 설계가 가능하다. 이 중 일부를 살펴보면 다음과 같다.

Case1. Single 5V External Supply
첫번째 케이스는 VEXT핀에 단일 5V 전원을 공급하는 방식이다. VEXT핀에 5V가 공급이 되는 경우 3.3V 전원생성을 위해서는 EVR33을 사용하고, 1.25V VDD 생성을 위해서는 EVRC를 사용한다.

Case2. Single 3.3V External Suppply
두번째 케이서는 VEXT핀에 단일 3.3V를 공급하는 방식이다. VEXT핀에 3.3V가 공급되면 별도로 3.3V 전원을 생성할 필요가 없으니 EVR33을 사용하지 않는다. 그럼에도 1.25V의 VDD 전원 생성이 필요하므로 EVRC는 사용이 되어야하며 구성은 다음과 같다.

Case3. 5V(VEXT) + 1.25V(VDD) External Supply
세번째 케이스는 외부에서 5V와 1.25V가 공급되는 경우이다. VEXT는 5V이며, 공급된 5V를 기반으로 EVR33을 사용하여 3.3V가 내부에서 생성된다. 한편 1.25V의 VDD 전원은 외부에서 공급이 되므로, EVRC는 사용되지 않는 Inactive상태가 된다.

Case4. 5V(VEXT) + 1.25V (VDD) + 3.3V(VDDP3) External Supply
마지막 네번쩨 케이스는 외부에서 모든 전원이 공급되는 경우이다. 외부에서 모든 전원이 공급되는 경우에는 내부 Converter를 사용할 필요가 없으므로 EVR33과 EVRC가 모두 사용되지 않는 Inactive 상태가 된다.

3.3.Power-Up Sequence

앞서 Tricore의 외부 전원 공급 방식에 대해 간략히 살펴보았다. 그러면 본 절에서는 전원이 공급되는 방식에 따라서 상세하게 Power-Up Sequence가 이뤄지는 내용을 다뤄보도록 한다. 전원이 공급되는 방식에 따라 일부 상이한점이 있긴 하나, 전체적으로 Power-Up Sequence는 유사하게 구성되어있으며 대동소이한 수준이다. 따라서 위 사례 중 5V가 단일 전원 공급되는 사례와, 모든 전원이 외부에서 공급되는 두가지 사례만을 User Manual에서 발췌하여 설명해보도록 한다.

Single 5V Supply

VEXT에 5V가 단독으로 공급되는 경우 3.3V와 1.25V 생성을 위해 각각 EVR33과 EVRC가 사용됨을 설명했다. 결과적으로 모든 세가지 전압이 DC상태를 유지하는 경우 안정적으로 전원초기화가 이루어진 것인데, VEXT에서 0V가 인가되어 세 전압이 정상상태를 유지하는 Start-Up 과정을 본 글에서 다루는 Analogue Start-up의 핵심이라고 볼 수 있다.

과정은 다음과 같다.

T1- T2 : 기본 전원 공급(VEXT) 및 클록 인프라 준비 단계

  • 외부 전원 상승에 따라 클록 등 준비단계
  • LVD 리셋 상태 해제 : VEXT의 전압레벨이 VLVDRST5 값을 초과하는 경우 LVD 리셋상태가 해제된다. (T1시점)
  • LVD Reset 해제시점에는 PORST핀의 동작이 LOW에서 HIG로 변화한다.

    PORST 활성 상태는 입력 또는 출력에서 리셋 신호가 발생한 경우를 의미하는데, PORST INPUT에서 활성화 (LOW Active)가 되는 경우 외부 장치가 PORST 핀 전압을 0V로 유지하여 리셋을 활성화 시키는 경우이며, 일반적으로 외부 전압 VEXT가 임계 전압인 T1 시점까지는 PORST LOW를 유지하는것이 바람직하다. 또한 PORST 출력핀이 있는데, PORST 출력은 마이크로컨트롤러가 내부적으로 리셋을 활성화 해서 PORST 핀을 Low Active로 설정하는것을 외부로 알려주는 경우임. 만약 VEXT 감소에 따라서 내부 주요 전압 Rail (VEXT, VDDP3, VDD)에서 낮은 전압이 감지되면 PORST Low Active Output이 출력된다.

T2 : EVRC / EVR33 레귤레이터 스타트

  • LVD Reset Release가 되는 경우 EVRC와 EVR33 레귤레이터가 전압을 상승하여 전압을 생성한다.

T3 : 펌웨어 시작

  • 모든 공급전압이 리셋 Release 기준값을 초과하므로 정상적인 S/W동작이 가능하다. 이 시점부터 PORST 출력값이 HIGH로 변한다. (즉 리셋 Desserted상태)

T4 : Boot Firmware 실행이 완료되면 이후 User Code 실행

  • CPU0가 기본 주파수인 100MHz로 사용자 코드를 실행한다.

All External Supply

모든 전원이 외부에서 공급되는 경우 EVRC와 EVR33이 필요가 없으니 세 전압이 모두 임계점이 도달하는 순간 바로 PORST Release가 이뤄지고, 이떄부터 S/W의 Firmware Execution이 이뤄진다. 상세한 내용은 앞서 설명한 3.1과 동일하다고 보면 된다.

3.4 정리

앞서 설명한 내용중 EVR레귤레이터 시작 전 PBIST1을 수행하여 EVR 레귤레이터 동작을 시작하고 이후 ,PBIST 2를 통해서 전압을 모니터링하는 내용이 있는데 Start-up Sequence에 다소 벗어나는 내용으로 본 글에서는 다루지 않도록 한다. 이처럼 외부 전원이 공급되어 모든 전압 레일이 안정적인 전압을 유지하는 경우 Boot Firmware가 시작됨을 알 수 있다.

다음 장에서는 Boot Frimware의 시작을 통해 초기화 되는 내용을 살펴보도록 하겠다.

4. Boot Firwmare 개요

TC3xx 플랫폼에서는 CPU Start-up 이후 최초로 실행되는 펌웨어다. Aurix TC3xx에서는 CPU0에 의해 Boot Firmware가 수행되며, 다른 CPU코어들은 halt state에 대기하고 있다.(Core 0 이외 Core들)

일반적으로 Automotive S/W에서 Boot Software라고 한다면, 필수 User Code (CAN 통신 / Task Manger / 리프로그래밍 관장) 등이 포함된 내용들이지만, 여기서 말하는 Boot Firmware는 User Code를 실행하기 전, 리프로그래밍이 불가능한 제조사 영역에 설치된 S/W를 말한다. 당연히 소프트웨어 코드는 볼 수 없다.

앞서 살펴본 Analouge Power Up Sequence가 종료되면 Boot Firmware가 수행되는데, Boot Firmware는 BROM이라는 영역에 존재한다. 제조사 이외에는 접근이 불가능한 영역이며 user가 수정할 수 있는 코드는 아니다.

BROM에 존재하는 Boot Code는 아날로그 전원의 Ramp-up이후 PORST 핀의 Reset Assertion, System reset, Application Reset, CPU0 커널 Reset등, 여러 리셋 타입 및 유저의 설정에 따라 다른 스타트업 시퀀스를 갖게 된다.

즉, Boot Code가 수행되기 전 발생한 리셋 이벤트 타입을 토대로 Boot Firmware의 스타트업 시퀀스가 결정되는것이다. 이 외에도 UCB 영역, HWCFG핀 설정이 주요한 영향을 미치게 된다. 정리하면 다음과 같다.

Boot Firwmare의 Start-up 시퀀스 결정 요소

  • UCB 영역 설정
  • HWCFG 핀 설정
  • 스타트업을 유발한 리셋 이벤트 타입

한편 Boot 펌웨어는 CPU0가 수행하며, 이 동안 나머지 Core들은 Halt State에 머무르고 있다.

2. Boot Firmware 동작

2.1 Falsh Ramp-Up 시작

  • 플래시 메모리 초기화 : 플래시 메모리가 모든 작업(Read/ Write / Erase) 을 정상적으로 수행 할 수 있도록 설정이 된다.

    선택된 RAM영역을 0으로 초기화 하고,ECC (Error Correcting Code) 값을 자동으로 설정한다. RAM을 초기화 하는 방법에도 여러 자유도가 있는데, RAM 초기화 옵션 설정의 경우 UCB 영역에서 설정하는 값에 따라 다음 세가지 설정에 대한 옵션이 제공된다.

  • RAM 초기화 여부 : Power On Reset이나 Warm 리셋시 RAM을 초기화 할 지 말 지 결정 할 수 있다. 기본적으로 Power On Reset시에는 RAM이 초기화 되도록 설정값을 갖고있다.

  • CPU별 RAM 초기화 : CPU에 할당된 RAM을 개별적으로 초기화 여부를 선택 할 수 있다.

  • LMU 및 AMU RAM 초기화 : LMU (Local Memory Unit) , AMU (Access Managenemt Unit)의 RAM 초기화 여부 선택이 가능.

2.2 BMI 평가 (스타트업 모드 결정)

이후 부트 모드 헤더의 유효성을 검사하고 부팅 모드 선택을 준비하게 된다. 부트 소프트웨어에서는 다양한 Start Up Software 구성이 가능한데, BMHD (Boot Mode Headers) 설정에 따라서 스타트업 모드의 설정이 가능하다. 한편 스타트업 모드의 결정은 BMHD 뿐 만 아니라, HWCFG핀에 따라 스타트업 부트 모드를 결정하는것 또한 가능하다. 즉 BMHD영역 S/W 설정 혹은 H/W 핀 설정에 따라 스타트업 모드 결정이 가능한것으로 보면 되겠다.

우선 BMHD영역 설정값에 따라 스타트업 모드를 결정하게 되는 경우에는 BMHD0 - BMHD3의 값을 참고하여 부트모드가 결정되고,

HWCFG핀 입력설정값에 따라 결정되는 경우에는 HWCFG3,4,5 세 핀의 입력 값에 따라 부트모드가 결정된다. 만약 이와 같이 BMHD와 HWCFG값을 참고하여 부트모드를 결정할수 없는 경우에는 다음과 같이 처리가 된다.

  1. 유효한 BMHD가 없고, HSM Boot, Boot Mode Lock이 걸리지 않은 경우에는 사용자 코드가 없는것으로 간주한다. 이러한 경우에는 혹시라도 Reset 이후 Halt 요청이 있었는지를 확인하고 만약 Halt 요청이 있었다면 시스템 내부 플래시메모리에서 부팅을 시작하도록 한다. 만약 그게 아니라면 Generic BSL 모드로 동작하여, CPU0의 PSPR을 사용자 시작코드 주소로 설정하게 된다.

  2. 유효한 BMHD가 없고, HSM 혹은 Boot Mode Lock이 설정된 경우에는, 적절한 부팅모드를 선택 할 수 없다. 따라서 디버그 액세스 인터페이스가 가능한 경우에는, 디버그 인터페이스를 활성화 시키고 무한대기상태에 진입한다. 만약 디버그 인터페이스가 비활성화(Lock)된 상태라면 부팅도 진행이 안되고 아무런 작업이 진행되지 않는다.

Halt After Reset이란 ? 일반적으로 시스템이 리셋 후 S/W를 바로 수행하는것이 아니라 동작을 멈추는것을 의미한다. 주로 디버깅 목적에 의해 사용이 되는데, 사용자 코드나 시스템코드가 바로 수행되는 경우 리셋에 대한 상태 분석이 어렵기 떄문이다.

2.3 HSM 부트

한편 Tricore는 몇 안되는 Full EVITA HSM이 있는 마이크로컨트롤러다. HSM은 ARM 기반 32비트 하드웨어 보안 모듈이다. HSM의 수행역할은 초기화시 특정 보안 및 초기화 작업을 담당하는것이다.

HSM이 동작하려면 DMU_SP_PROCONHSMCFG, HSMBOOTEN값이 활성화 되어있어야한다. 만약 이 두 값이 활성화 되었다면 HSM 펌웨어가 실행되고 부팅과정이 시작된다.

2.4 LockStep 구성

부트펌웨어는 Lockstep을 구성한다.Lockstep은 두개의 동일한 프로세서를 동기화 시켜서 동일한 작업을 시키도록 하는 기술이다. 즉 동일한 일을 서로 독립된 두개의 프로세서에서 수행한 뒤, 프로세서 수행 결과값의 출력이 동일함을 기대하는것인데, 만약이라도 출력이 지속적으로 비교되어 불일치 하지 않는 경우 오류가 표시된다.

LockStep의 경우 부트펌웨어가 그 초기화 설정을 진행한다. 시작모드 평가중에 유효한 BMI가 발견되는 경우 Lockstep 설정이 진행된다. 만약에 유효한 BMI가 발견되지 않으면 CPU0에 대한 Lockstep이 비활성화 된다. 이말인 즉, 부트모드 헤더에 Lockstep관련 정보가 없으면 CPU0는 Lockstep 모드로 동작하지 않음을 의미한다.

2.5 디버그 포트 활성설정

만약 debug interface access가 활성화 되어있으면,Boot firmware가 디버그 인터페이스를 사용가능하도록 설정한다. 또한 디버그 액세스가 활성화 된다면 외부 디버거에서 요청에 따라 첫번째 사용자 코드 명령 전 실행을 중단하는 HAR (Halt After Reset) 설정이 진행된다.

이상 부트 펌웨어에서 수행하는 동작을 다섯 단계에 나누어서 알아보았다. 한편 부트 펌웨어 같은 경우는 다음의 세가지 상황에서 즉시 종료가 된다.

  1. Flash 램프업중에 오류가 발생하는 경우
  2. Flash를 구성하는 영역이 훼손되는 경우 (복구 불가능한 데이터 오류)
  3. 부트 펌웨어에 의해서 평가한 UCB가 하나라도 오류거나 복구 불가능한 상태인 경우

3. BOOT Mode Option

3.1 Boot Option 개요

TC3x는 다양한 Start-up Configuration 을 지원한다. Start-up Sofware가 Boot Mode Option 평가를 수행하고 해당 모드에 따라서 필요한 초기화를 수행한다고 보면 된다. 이때 부팅 모드의 평가는 다음 두가지 요소를 기반으로 수행한다.

  • Boot Mode Header (BMHD) : 플래시메모리에 존재하는 UCB 영역에 저장된 데이터구조로, 시작주소 , 락스텝 활성화 여부, 외부 부팅모드 활성화 여부등을 선택 할 수 있다.

  • 하드웨어 구성핀 (HWCFG PIN) : TC3x 마이크로컨트롤러의 특정 핀을 통해서 부트모드를 설정 할 수 있다. HWCFG핀의 경으 다음 설정을 통해 부트모드를 결정한다.

이떄 BMHD의 설정값을 사용할지, HWCFG 하드웨어 입력값을 사용할지는 HWCFG PIN Mode Selection값에 따라 달려있다.

위 그림처럼 BOOT CFG에 설정값이 일단 복사 된 뒤에 부트모드 평가가 이루어진다. 이때 설정 할 수 있는 부트모드는 각각 다음과 같다.

3.2 Alternate Boot Mode

Alternate Boot Mode 란 사용자가 정의한 주소 (STADD) 에서 프로그램 코드를 시작하고, 실행전에 프로그램 코드와 데이터 무결성을 확인 할 수 있는 기능이다. ABM을 사용하면 플래시 메모리 영역 특정 영역에 저장된 코드 / 데이터 유효성을 확인 할 수 있기 떄문에 안전한 부팅이 가능하다.

작동방식은 다음과 같다.

1) 부팅모드 선택 : 앞서 3.1에서 알아본 내용에 따라서 Start up Boot Firmware가 부트모드를 선택한다.

2) ABMHD 헤더 확인 : SSW는 BMHD의 STAD필드의 지정된 주소에서 ABMHD를 찾는다. ABMHD는 ABM에 필요한 정보를 담고 있는 데이터 구조이다.

3) ABMHD 유효성검사 : ABMHD의 무결성등을 검사 한 뒤, ABMHD에 있는 ABMHDID, CRCABMHD, CRCRANGE등을 무결성 검증에 사용한다.

4) 코드및 데이터검증 : ABMHD의 CHKSTART 및 CHKEND 필드는 검증할 메모리영역의 시작 및 끝을 나타낸다. SSW는 이 영역에 저장된 코드 무결성을 검증하게 된다.

5) 사용자 코드 실행 : 모든 검증이 성공적으로 수행 완료되면 SSW는 ABMHD의 STADABM필드에 지정된 주소에서 사용자의 코드를 시작한다.

이처럼 Alternative Boot Mode를 사용하게 되면 실행전 코드 및 데이터 무결성을 검증하여 악의적인 코드 실행을 방지 할 수 있다. 또한 신뢰성 향상측면에서 데이터 오류로 인한 발생가능성을 줄여준다.

3.3 BSL (Boot Starp Loader)

부트스트랩로더란, CPU0의 PSPR에 코드를 이동하여 BOOT ROM이 종료된 이후에 이 코드가 시행된다. TC3x에서는 ASC, CAN 두가지 인터페이스를 지원하며 선택된 통신프로토콜에 따라서 코드가 특정 메모리 섹션으로 전송된다.

일단 BSL 모드가 시작되면 통신프로토콜 페리퍼럴에서 사용자 코드가 다운로드 될 때 까지 정의된 절차에 따라 시행되어야한다. BSL의 실행과정에 있어서는 RxD 핀을 결정한다. 그 다음 시작펄스 (Low Level Pulse)를 기다리고 펄스 지속시간을 측정한다. 두번째 펄스가 확인되면 Generic BSL은 CAN 프로토콜을 사용하고, 그렇지 않으면 ASC 프로토콜을 사용한다.

이후 코드를 다운로드하여 CPU0_PSPR에 저장한다. 다운로드가 완료되면 SSW는 CPU0의 PSPR에서 코드를 실행한다. 잘 사용되지는 않는 방식이니 크게 알아 둘 필요는 없다.

이상으로 Boot Mode 결정과 사용가능한 Boot Mode에 대해 간략히 알아보았다. 이제 Boot Mode가 결정한 대로 User Code가 실행되는 부분부터를 Application Startup software라고 하는데, 이 부분 부터는 디버거를 통해서 유저가 실행 코드를 직접 살펴볼수 있다. 다음 글에서는 application start up 코드의 실행에 대해 자세히 살펴보도록 한다.

4. Application Start up Software 개요

Application Software의 Start-up software는 Boot Firmware 직후 실행되는 코드로써, User Code 실행 전 초기화를 담당하는 S/W이다. 줄여서 ASSW (Application Start Up Software)라고 부르도록 한다.

Application Startup Software는 Boot Firmware 실행 후에 CPU0에서 초기화를 수행한다. 이때, Start-up을 유발한 Reset Event에 따라서 Start-up Software는 각기 다른 실행경로를 갖게된다. Application Startup Sotware는 마이크로컨트롤러 사용자가 임의로 수정 할 수 있다. 이러한 ASSW는 일반적으로 다음의 수행절차를 갖는게 일반적이다. 전체적인 수행절차에 있어서는 리셋 유형을 평가하여 POR인 경우 LBIST, MONBIST를 수행하고, CPU0의 초기화를 수행한다. 이어서 CPU0의 와치독, RAM등을 초기화하며 MBIST를 통해 RAM 영역 검사를 수행한다. 이후 SMU 알람 설정을 수행하고 순차적으로 각 Core들을 Wakeup하면서 CPU0 Init절차를 수행한다. 이를 그림으로 나타낸것이 다음이다.

4.1 ASSW 수행절차

리셋유형 평가

1단계로 수행하는 절차는 리셋 유형 평가이다. ASSW가 실행된 리셋 사유가 Application Reset인지, System Reset인지, CPU0 리셋인지 등, 리셋 사유를 확인하여 ASSW를 실행하게 된다. 리셋 유형 평가에 있어서는 RSTSTAT / RSTCON 레지스터 값을 읽음을 통해 평가가 가능하다. 실제 리젯을 발생 시킬 수 있는 , S/W, STM, SMU, ESR 등은 어플리케이션 리셋만을 발생 시킬 수 있다. 다른 리셋 소스들은 시스템 리셋을 발생시킨다. 이떄 어플리케이션 리셋이 발생한 이후에는 Ifx_Ssw_isApplicationReset() 값이 1을 리턴하는 경우 리셋이 완료된다.

PMS , LBIST, MONBIST 수행

2단계절차에서는 PMS, LBIST, MONBIST 처리 (Cold Power On Reset에만 실행) 를 수행한다. 만약 1단계에서 평가한 Reset 사유가 Cold Power on Reset이면 EVR을 초기화 하고, 시스템 점검을 위한 LBIST 테스트를 수행하게 된다.

LBIST란?
LBIST란 Logic Built in Selft Test의 약자로, Aurix TC3x에 내장된 시스템 내 상태 점검을 위한 테스트 방법이다. LBIST는 외부 하드웨어의 도움 없이 온 칩 내장 회로를 사용하여 테스트 입력을 인가하고, 이에 따른 출력 응답을 분석하여 테스트를 수행하게 된다. 즉 쉽게말하자면 LBIST는 마이크로컨트롤러 내부에 자체 테스트를 위해 내장된 기능이고, 칩이 정상적으로 동작하는지 확인하는 역할정도로 우선 정리할수 있겠다.
LBIST의 경우 LBISTCTRL00,1,2 레지스터를 통해 구성되며, 이 레지스터들을 통해서 테스트 할 회로 및 테스트 패던, 테스트 범위를 지정 할 수 있다. 그리고 LBISTCTRL0의 Req 비트를 SET하면 LBIST가 시작된다. 실행에 따라서 LBIST 결과값에 대한 고유한 서명이 생성되어서, ASSW에서는 이 서명값을 토대로 LBIST에 문제가 없는지 확인 할 수 있게 된다. 이보다 자세한 LBIST 수행에 관한 내용은 별도 글을 통해 다시 설명할수 있도록 하겠다.

LBIST에 대한 상세한 Flow는 다음과 그림과 같다. 우선 LBISTDONE비트 값을 읽음을 통해서 이전에 트리거한 LBIST가 완료 되었는지 확인한다. 만약 LBIST가 완료된 경우 예상되는 값을 Siganture Value와 비교하여 정답을 확인한다.

이후 LBIST가 완료되면, MONBIST를 점검하고, secondary 전압 모니터를 확인한다.

MONBIST란?
MONBIST는 Secondary Monitor and Standby SMU Built in Selt Test의 약자로써, 2차 전압 모니터와 Standby SMU에 연결된 Alarm 및 Error 검출 로직에 대한 잠재적 결함 검출 범위를 보장하는 테스트로, 쉽게 말하자면 MONBIST는 시스템 전압을 모니터링하는 회로가 제대로 동작하는지 확인하는 테스트이다. Secondary Monitor 는 시스템으 ㅣ전압이 지정된 범위를 벗어나게 되는 경우에 Standby SMU에 알람을 전송하는 역할을 수행한다. Standy SMU는 시스템 Saftey Module로써, 알람을 수신하게 되는 경우 시스템을 Safety State로 전환하거나 리셋을 발생시키는 조취를 취하게 된다.
MONBIST의 수행절차는 첫번째로 MONBIST를 활성화 하는것으로 시작한다. Standby SMU모듈의 MONBISTCTRL 레지스터에서 TSTEN비트를 설정하여 MONBIST를 활성화 한다. 이후 MONBISTSTAT레지스터에서 TSTRUN비트가 설정될때까지 기다린다. 이후 MONBIST결과확인을 하게된다. 만약 TSTOK비트가 설정되면 MONBIST가 정상적으로 수행되었음을 나타낸다.

CPU0 Function Call 시스템 설정

CPU0에서 함수호출이 지원 될 수 있도록 컨텍스트 저장 영역 및 스택포인터 (A10)을 설정하게 된다.

PLL 및 기타 드라이버 초기화 및 RAM 테스트 (POR)

PLL및 드라이버 초기화등은 POR에만 수행된다. CPU0 및 Sfaety Watchdog을 동작시키고, 클럭과 플러시의 대기상태를 초기화한다. Safety Application의 경우에는 MBIST 검사를 RAM에 수행한다.

클럭같은 경우는 다음과 같이 PLL을 통해 안정화 된 이후 Clock Distribution 시스템을 통해 각 모듈별로 클럭이 공급된다.

MBIST란? (Memory Built In Test)
MBIST는 Tricore 시리즈 마이크로컨트롤러 내부의 SRAM 무결성을 확인하기 위한 메모리 내장 자체 테스트 기능이다. MBIST는 CPU를 사용하지 않고 메모리에 직접 접근하여 테스트를 수행하므로 CPU를 통해 직접 접근 할 수 없는 메모리도 테스트 할 수 있는 장점이 있다. MBIST는 ASSW과정에서 수행되며, Power On Reset시에만 수행된다. MBIST의 세부 절차는 다음과 같다.

  1. MBIST는 SSH(Safety and Security Hardware) 를 통해 우선 설정된다. SSH의 CONFIG0및 CONFIG1 레지스터, 그리고 MCONTROL 레지서터를 통해 MBIST 설정이 가능하다.
  2. Gang별 순차적 실행 : RAM은 Gang이라는 그룹으로 나뉜다. 이후 MBIST는 각 Gang을 순차적으로 검사한다. 이는 전원 공급 전류의 큰 변동을 방지하기 위해서이며, 한 Gang 내의 모든 RAM은 병렬로 처리된다. 이를테면 TC39x시리즈에서 RAM 초기화를 위해서 18개의 Gang으로 그룹회 됨을 의미한다.

SMU 알람 처리 (선택사항)

이후 ASW 요구사항에 따라서 SMU 알람을 처리한다.

C 초기화 및 멀티코어 시작

본 단계에서는 ASW구성에 따라 캐시 메커니즘을 활성화 한다. 이후 인터럽트 및 트랩 메커니즘을 지원하도록 시스템을 설정하고, CPU0 및 CPU 공유 변수에 대한 전역변수 초기화를 수행한다. 그리고 추가로 설정된 타 코어 (멀티코어 CPU1, CPU2..)에 대한 설정을 시작한다.

이때 멀티코어의 싲가은 데이지 체인 시퀀스로 발생하며 CPU0 --> CPU1 --> CPU2와 같은 방식으로 하나의 CPU가 다른 CPU를 순차적으로 활성화 한다.

캐시 매커니즘에서 캐시메모리란, CPU가 자주 사용하는 데이터를 빠르기 위해 사용하는 메모리이다. CPU는 일반적으로 주 메모리 (RAM)에서 데이터를 읽어오지만, RAM은 CPU에 비해 속도가 느리다. 따라서 CPU와 RAM 사이에 고속 캐시 메모리영역을 두어서 데이터를 저장하는 경우 속도 향상이 가능하다. CPU가 특정 데이터에 접근 해야 할 떄, 먼저 캐시 메모리를 확인해서, 만약에 데이터가 캐시에 있으면 (캐시히트) CPU는 RAM에 접근하지 않고, 캐시에서 데이터를 빠르게 읽어 올 수 있다. 데이터가 캐시에 없으면 (캐시 미스) CPU는 RAM에서 데이터를 읽어와 캐시에 저장한다.
TC계열 마이크로컨트롤러는 Data Chace와 Program Chach 를 지원하는이를 각각 DSPR, PSPR이라고 부른다. DSPR에서는 데이터 영역을 저장하고, PSPR에서는 코드영역을 저장한다. 이러한 캐시 메커니즘은 마지막 C 초기화 단계에서 설정된다.

C Initialize에 대한 상세한 수행은 다음 절차를 통해 수행된다.

C Initialization

  1. Data / Code영역의 캐시메모리 테스트 수행 및 초기화, 캐시 Enable.
  2. A0, A1, A8,A9의 전역 시스템 레지스터가 초기화된다.
  3. Ssw_C_Init() 이 수행되어서 전역변수를 초기화한다.
  4. 인터럽트 벡터 테이블의 Base 주소를 초기화한다.
  5. Start-up Code가 ISP (인터럽트 스택포인터) 레지스터를 초기화한다.
  6. Ifx_Ssw_Init() 함수으 ㅣ수행에 따라, Flash의 변수를 RAM으로 필요한 경우 복사한다.

멀티코어 스타트업

추가적인 코어 수행을 위해서 이후 멀티코어 스타트업이 시작된다. CPU0만 기본적으로 스타트업이 되고 이후 CPUx들은 수동으로 시작해야한다.
1. 코어들은 총 네가지 상태에 머무른다. "Halt" , "IDLE" "RUN" "RESET"
2. 이때 CPU State들은 SYSCON의 PMCSRx 레지스터를 통해 설정가능하다.
3. Halt상태 CPU의 PC값은 CPU가 HALT에서 RUN으로 바뀌도록 변경되어야한다.

4.2 Start-up Code Example

스타트업 코드 예제를 확인하기 위하여 다음 예제에서 LED Project를 Active Project로 설정하고 Debugger를 실행한다.

이후 Debugger를 통해 RESET 직후 STOP 상태에 있는 CPU의 F11을 눌러 최초로 실행되는 코드를 확인한다. 이 경우 최초 시작이 StartUpSoftware 임을 알 수 있다. 그렇다면 StartUpSoftware는 어떻게 최초로 시작이 된 것일까?

다음과 같이 Startup Software의 주소는 0x80002014임을 알 수 있다. 앞선 글에서 살펴 보았듯 BMHD영역에서 STADD값이 이 값으로 설정되어있는 경우 Boot Mode Evaluation 이후 본 함수를 최초 함수로 시작하게 된다.

그런데, Core0의 BMHD값은 STAD가 0x80000000으로 설정되어있다. 따라서 0x80000000주소값을 살펴보니 시작주소에서 0x80002014주소로 jump하는 어셈블리어가 설정되어있다.

아니 그러면 분명히 0x80000000이 시작일텐데 어떻게 해서 0x80002014로 jump하는 명령어가 써지게 된 것일까?

이는 _START함수가 Tricore에서 시작함수로 예약되어있고, 이때 SSW로 Jump하는 illd 함수가 아래와 같이 있기떄문이다 !

void _START(void)
{
    Ifx_Ssw_jumpToFunction(__StartUpSoftware);
}

따라서 이상의 설정으로 최초 수행되는 SSW는 __StartUpSoftware이 된다.

4.3 StartupSoftware 분석

static void __StartUpSoftware(void)
{
    /* Initialize A1 pointer to use the global constants with small data addressing */
    Ifx_Ssw_setAddressReg(a1, __SDATA2(0));

    /* Set the PSW to its reset value in case of a warm start,clear PSW.IS */
    Ifx_Ssw_MTCR(CPU_PSW, IFX_CFG_SSW_PSW_DEFAULT);

    /* This phase is executed only if last reset is not of type application reset */
    if (Ifx_Ssw_isApplicationReset() != 1)
    {
        Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase2);
    }
    else
    {
        Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase3ApplicationResetPath);
    }
}

Ifx_Ssw_setAddressReg(a1, __SDATA2(0))

SSW가 실행된 뒤 가장 처음으로 실행되는 본 함수의 경우 인라인 어셈블리어로 다음과 같이 구성되어있다.

#define Ifx_Ssw___setAddressReg(aReg, val) \
    {__asm__ volatile ("movh.a\t %"#aReg ", hi:("#val ")\n\tlea\t %"#aReg ",[%"#aReg "] lo:("#val ")"); }

Tricore에는 CPU가 갖고있는 16개의 범용 레지스터가 있는데 이 중 하나인 a1 레지서트의 경우는 특정 메모리 영역을 가리키는 포인터로 쓸 수 가 있다.

이때, 프로그램 코드에서 사용되는 상수나 초기화된 변수들이 저장되는 메모리 영역을 리터럴 데이터 섹션이라고 하는데, 이를테면 const int a = 10; 과 같이 선언된 상수 a 는 리터럴 데이터 섹션에 저장된다.

이때, SDATA2(0)는 CPU0의 리터럴 데이터 섹션 시작주소를 나타내는 심볼이다.
("
A1MEM" = "_LITERAL_DATA";)

한편 small data addresing이라는 개념을 간략히 설명하자면, Tricore CPU는 데이터에 접근하는 여러가지 방법을 제공하는데, 그 중 한개의 방법이 small data addresssing이다. small data addressing은 A0레지스터를 기준으로 상대주소를 접근하여 데이터에 접근하는 방식이다.

따라서, Ifx_Ssw_setAddressReg(a1, __SDATA2(0)) 함수를 실행함으로써, A1레지스터는 CPU0의 리터럴데이터섹션의 시작주소를 가리킨다. 이후 CPU0는 A1레지스터를 사용하여 small data addressing 방식으로 리터럴 데이터 섹션에 저장된 상수값에 접근을 하게된다.

즉, 이 함수는 start-up 과정에서 CPU0가 프로그램 실행에 필요한 상수값을 효율적으로 가져올 수 있도록 환경을 설정하는 역할을 수행한다.

쉽게설명하자면, A1에는 리터럴 데이터 섹션의 시작주소값이 저장되고, A1 레지스터를 기준으로 오프셋값을 더하여 전역상수에 쉽게 접근 할 수 있다는 뜻이다.

Application Reset 판단

    /* This phase is executed only if last reset is not of type application reset */
    if (Ifx_Ssw_isApplicationReset() != 1)
    {
        Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase2);
    }
    else
    {
        Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase3ApplicationResetPath);
    }

상기 코드에서 Ifx_Ssw_isApplicationReset 함수는 마지막 리셋 이벤트가 Application Reset인지를 판단한다. 만약 어플레케이션 리셋이 아닌 경우 __StartUpSoftware_Phase2 함수로 이동하여, 전원시스템/ 클럭 / 플래시 메모리등의 핵심 요소들을 초기화 한다.

만약 애플리케이션 리셋이라고 한다면,상기의 과정들을 건너띄고 __StartUpSoftware_Phase3ApplicationResetPath 함수로 바로 이동하여서 주변 장치 초기화 및 CPU 초기화 단계로 진입하게 된다.

위와 같이 디버거를 통해 Reset하는 경우 Application Reset이 아니므로, SSW Phase2로 넘어가게 된다.

__StartUpSoftware_Phase2

static void __StartUpSoftware_Phase2(void)
{
    /* Power and EVRC configurations */
    IFX_CFG_SSW_CALLOUT_PMS_INIT();

    /* LBIST Tests and evaluation */
    IFX_CFG_SSW_CALLOUT_LBIST();

    /* MONBIST Tests and evaluation */
    IFX_CFG_SSW_CALLOUT_MONBIST();

    Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase3PowerOnResetPath);
}

다음과 같이 LBIST, MONBIST를 수행한 뒤 Pahse3로 넘어가게된다.

이때 잠시 살펴보고 갈 것은 Infenion iLLD에서 함수에 함수를 인자로 받아서 다음 함수를 호출하는 방식이다. 어떻게 함수에 함수명을 넣었는데 그 다음 함수로 Jump를 하게될까?

정답은 아래 함수 정의에 있다.

IFX_SSW_INLINE void Ifx_Ssw_jumpToFunction(void (*fun)(void))
{
    __asm__ volatile ("ji %0" ::"a" (fun));
}

위 함수를 보는 경우 핵심은 어셈블리 명령어 "ji %0"에 있다.
"ji"는 Jump Immediate의 줄임말로, 특정 주소로 즉시 점프하는 어셈블리 명령어입다. 즉, ji 명령어는 fun이 가리키는 함수 주소로 점프한다. %0는 fun 포인터 값이 대입되는 자리다. 즉, fun이 가리키는 함수 주소가 레지스터 a에 로드되고, 이후 "ji %0"가 실행되어 해당 주소로 점프하는것이다.

__StartUpSoftware_Phase3PowerOnResetPath

static void __StartUpSoftware_Phase3PowerOnResetPath(void)
{
    IFX_SSW_INIT_CONTEXT();

    Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase4);
}

Phase3에서는 다음과 같이 Context 초기화를 수행한다.

#define IFX_SSW_INIT_CONTEXT()                                                   \
    {                                                                            \
        /* Load user stack pointer */                                            \
        Ifx_Ssw_setAddressReg(a10, __USTACK(0));                                 \
        Ifx_Ssw_DSYNC();                                                         \
                                                                                 \
        /*Initialize the context save area for CPU0. Function Calls Possible */  \
        /* Setup the context save area linked list */                            \
        Ifx_Ssw_initCSA((unsigned int *)__CSA(0), (unsigned int *)__CSA_END(0)); \
        /* Clears any instruction buffer */                                      \
        Ifx_Ssw_ISYNC();                                                         \
    }

위 함수에서는 CPU0를 위한 컨텍스트 저장영역 (CSA)를 초기화하고 사용자 스택포인터를 설정한다. 컨텍스트 저장영역은 함수 호출, 인터럽트 처리, 트랩 처리 등 컨텍스트 스위칭이 발생 할 때, CPU의 현재상태 (레지스터값) 등을 저장하는데 사용하는 메모리 영역이다.

Ifx_Ssw_setAddressReg(a10, __USTACK(0)); 함수는 A10 레지스터에 USTACK(0) 심볼을 저장한다. A10 레지스터는 사용자 스택포인터를 나타내며, USTACK(0)는 링커에 의해 설정되어 정의된 CPU0 사용자 스택 영역의 시작주소를 나타내므로, 이 코드는 CPU0의 스택 포인터를 초기화하는 함수이다.

이어서 Ifx_Ssw_initCSA((unsigned int *)__CSA(0), (unsigned int *)__CSA_END(0)); 함수는 CPU0의 컨텍스트 저장영역을 초기화한다. CSA(0) 는 CPU0의 컨텍스트 저장영역의 시작주소를 나타내고, CSA_END(0)는 컨텍스트 저장영역 끝주소를 나타내므로, 본 함수는 컨텍스트 저장영역을 초기화하고, 컨텍스트 저장영역 연결리스트를 설정한다.

따라서 본 설정을 통해서 사용자 스택과 컨텍스트 저장 영역을 이후 함수호출, 인터럽트 처리, 트랩처리 등 컨텍스트 스위칭이 발생 할 떄 CPU의 상태를 안전하게 복원할수 있게된다.

__StartUpSoftware_Phase4

static void __StartUpSoftware_Phase4(void)
{
    /* This is for ADAS chip, where clock is provided by MMIC chip. This has to be
     * implemented according the board.
     */
    IFX_CFG_SSW_CALLOUT_MMIC_CHECK();

    {
        /* Update safety and cpu watchdog reload value*/
        unsigned short cpuWdtPassword    = Ifx_Ssw_getCpuWatchdogPasswordInline(&MODULE_SCU.WDTCPU[0]);
        unsigned short safetyWdtPassword = Ifx_Ssw_getSafetyWatchdogPasswordInline();

        /* servicing watchdog timers */
        Ifx_Ssw_serviceCpuWatchdog(&MODULE_SCU.WDTCPU[0], cpuWdtPassword);
        Ifx_Ssw_serviceSafetyWatchdog(safetyWdtPassword);
    }

    /* Initialize the clock system */
    IFX_CFG_SSW_CALLOUT_PLL_INIT();

    /* MBIST Tests and evaluation */
    IFX_CFG_SSW_CALLOUT_MBIST();

    Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase5);
}

위 함수에서 Ifx_Ssw_getCpuWatchdogPasswordInline() 및 Ifx_Ssw_getSafetyWatchdogPasswordInline() 함수를 사용하여 CPU 와치독 타이머와 Safety Timer에 접근하기 위한 비밀번호를 얻습니다. 이후 Watchdog 서비스를 시작한다.

또한 PLL INIT함수를 통해 클럭 시스템을 초기화 하고, MBIST 평가를 통해서 RAM 안정성을 테스트한다. 이후 다음 단계로 넘어간다.

Phase5,6


static void __StartUpSoftware_Phase5(void)
{
    /* SMU alarm handling */
    IFX_CFG_SSW_CALLOUT_SMU();

    Ifx_Ssw_jumpToFunction(__StartUpSoftware_Phase6);
}


static void __StartUpSoftware_Phase6(void)
{
    /* Start remaining cores as a daisy-chain */
#if (IFX_CFG_SSW_ENABLE_TRICORE1 != 0)
    Ifx_Ssw_startCore(&MODULE_CPU1, (unsigned int)__START(1));           /*The status returned by function call is ignored */
#endif /* #if (IFX_CFG_CPU_CSTART_ENABLE_TRICORE1 != 0)*/
#if (IFX_CFG_SSW_ENABLE_TRICORE1 == 0)
#if (IFX_CFG_SSW_ENABLE_TRICORE2 != 0)
    Ifx_Ssw_startCore(&MODULE_CPU2, (unsigned int)__START(2));           /*The status returned by function call is ignored */
#endif
#if (IFX_CFG_SSW_ENABLE_TRICORE2 == 0)
#if (IFX_CFG_SSW_ENABLE_TRICORE3 != 0)
    Ifx_Ssw_startCore(&MODULE_CPU3, (unsigned int)__START(3));           /*The status returned by function call is ignored */
#endif
#endif /* #if (IFX_CFG_SSW_ENABLE_TRICORE2 == 0) */
#endif /* #if (IFX_CFG_SSW_ENABLE_TRICORE1 == 0) */

    Ifx_Ssw_jumpToFunction(__Core0_start);
}

이후 Phase 5,6에서는 각각 SMU 알람을 설정하고, Daisy Chain방식의 CPU Core 1,2,3을 Start한다. 이후 CPU Core start 함수로 이동한다.

Core0_Start

이제부터는 각 코어별로 수행하는 함수들이다. CPU 0 Start 함수에서는 수행하는 내용들이 꽤 많아서 여기서부터는 조금 나눠서 보도록 하자.


static void __Core0_start(void)
{
    /* Update safety and cpu/safety watchdog reload values */
    /* Password value is read again, because there is chance that local variables may be overridden. */
    unsigned short cpuWdtPassword    = Ifx_Ssw_getCpuWatchdogPasswordInline(&MODULE_SCU.WDTCPU[0]);
    unsigned short safetyWdtPassword = Ifx_Ssw_getSafetyWatchdogPasswordInline();

    Ifx_Ssw_clearCpuEndinitInline(&MODULE_SCU.WDTCPU[0], cpuWdtPassword);

    /* Enable/ Disable the caches depending on the configuration. At this point cache are invalidated */
    {
        Ifx_CPU_PCON0 pcon0;
        pcon0.U       = 0;
        pcon0.B.PCBYP = IFX_CFG_SSW_ENABLE_TRICORE0_PCACHE ? 0 : 1; /* depending on the enable bypass bit is reset/set */
        Ifx_Ssw_MTCR(CPU_PCON0, pcon0.U);
        Ifx_Ssw_ISYNC();
    }

    {
        Ifx_CPU_DCON0 dcon0;
        dcon0.U       = 0;
        dcon0.B.DCBYP = IFX_CFG_SSW_ENABLE_TRICORE0_DCACHE ? 0 : 1; /* depending on the enable bypass bit is reset/set */
        Ifx_Ssw_MTCR(CPU_DCON0, dcon0.U);
        Ifx_Ssw_ISYNC();
    }

    /* Set A0 Pointer to access global variables with small data addressing */
    Ifx_Ssw_setAddressReg(a0, __SDATA1(0));

    /* These to be un commented if A8 and A9 are required to be initialized */
    Ifx_Ssw_setAddressReg(a8, __SDATA3(0));
    Ifx_Ssw_setAddressReg(a9, __SDATA4(0));

    /* Trap vector table initialization is necessary if it is not same as default value */
    Ifx_Ssw_MTCR(CPU_BTV, (unsigned int)__TRAPTAB(0));
    /* Base interrupt vector table initialized */
    Ifx_Ssw_MTCR(CPU_BIV, (unsigned int)__INTTAB(0));
    /* Interrupt stack pointer is configured */
    Ifx_Ssw_MTCR(CPU_ISP, (unsigned int)__ISTACK(0));

    Ifx_Ssw_setCpuEndinitInline(&MODULE_SCU.WDTCPU[0], cpuWdtPassword);

    /* CPU and safety watchdogs are enabled by default,
     * C initialization functions are not servicing the watchdogs.
     */
    Ifx_Ssw_disableCpuWatchdog(&MODULE_SCU.WDTCPU[0], cpuWdtPassword);
    Ifx_Ssw_disableSafetyWatchdog(safetyWdtPassword);

    /* Initialization of C runtime variables */
    Ifx_Ssw_C_Init();

    Ifx_Ssw_enableSafetyWatchdog(safetyWdtPassword);

#if (IFX_CFG_SSW_ENABLE_TRICORE0 == 0)
    /* Set the CPU 0 to Idle mode, if it is not needed to be enabled */
    Ifx_Ssw_setCpu0Idle();
#endif

    Ifx_Ssw_enableCpuWatchdog(&MODULE_SCU.WDTCPU[0], cpuWdtPassword);

    /*Call main function of Cpu0 */
    Ifx_Ssw_jumpToFunction(core0_main);
}

CPUU0 Program Cache, Data Cache 사용 설정

    /* Update safety and cpu/safety watchdog reload values */
    /* Password value is read again, because there is chance that local variables may be overridden. */
    unsigned short cpuWdtPassword    = Ifx_Ssw_getCpuWatchdogPasswordInline(&MODULE_SCU.WDTCPU[0]);
    unsigned short safetyWdtPassword = Ifx_Ssw_getSafetyWatchdogPasswordInline();

    Ifx_Ssw_clearCpuEndinitInline(&MODULE_SCU.WDTCPU[0], cpuWdtPassword);

    /* Enable/ Disable the caches depending on the configuration. At this point cache are invalidated */
    {
        Ifx_CPU_PCON0 pcon0;
        pcon0.U       = 0;
        pcon0.B.PCBYP = IFX_CFG_SSW_ENABLE_TRICORE0_PCACHE ? 0 : 1; /* depending on the enable bypass bit is reset/set */
        Ifx_Ssw_MTCR(CPU_PCON0, pcon0.U);
        Ifx_Ssw_ISYNC();
    }

    {
        Ifx_CPU_DCON0 dcon0;
        dcon0.U       = 0;
        dcon0.B.DCBYP = IFX_CFG_SSW_ENABLE_TRICORE0_DCACHE ? 0 : 1; /* depending on the enable bypass bit is reset/set */
        Ifx_Ssw_MTCR(CPU_DCON0, dcon0.U);
        Ifx_Ssw_ISYNC();
    }

상기 코드는 PSPR및 DSPR 활성화에 대한 코드로, 만약 PCBYP 비트가 0이면 캐시가 활성화되고, 아니면 1이면 비활성화 된다.

기타 나머지 함수

Ifx_Ssw_setAddressReg(a0, __SDATA1(0));: A0 레지스터에 SDATA1(0) 심볼 값을 설정한다. A0 레지스터는 전역 변수에 접근하기 위한 기본 포인터로 사용되며, SDATA1(0)은 링커/로케이터 설정에 의해 정의된 CPU0의 small data 영역 시작 주소를 나타낸다.

Ifx_Ssw_setAddressReg(a8, __SDATA3(0));, Ifx_Ssw_setAddressReg(a9, __SDATA4(0));: A8, A9 레지스터에 SDATA3(0), SDATA4(0) 심볼 값을 설정한다. A8, A9 레지스터는 OS 또는 애플리케이션에서 사용하기 위해 예약된 레지스터이며, SDATA3(0), SDATA4(0)은 각각 링커/로케이터 설정에 의해 정의된 CPU0의 특정 데이터 영역 시작 주소를 나타낸다.

Ifx_Ssw_MTCR(CPU_BTV, (unsigned int)__TRAPTAB(0));: CPU_BTV 레지스터에 TRAPTAB(0) 심볼 값을 설정한다. CPU_BTV 레지스터는 트랩 벡터 테이블의 기본 주소를 저장하는 레지스터이며, TRAPTAB(0)은 링커/로케이터 설정에 의해 정의된 CPU0 트랩 벡터 테이블의 시작 주소를 나타낸다. 이때 트랩은 예외적인 상황 (예: 오류, 디버깅)이 발생했을 때 CPU가 처리하는 메커니즘이다.

Ifx_Ssw_MTCR(CPU_BIV, (unsigned int)__INTTAB(0));:CPU_BIV 레지스터에 INTTAB(0) 심볼 값을 설정한다. CPU_BIV 레지스터는 인터럽트 벡터 테이블의 기본 주소를 저장하는 레지스터이며, INTTAB(0)은 링커/로케이터 설정에 의해 정의된 CPU0 인터럽트 벡터 테이블의 시작 주소를 나타낸다. 인터럽트는 외부 장치가 CPU의 처리를 요청하는 메커니즘이다.

Ifx_Ssw_MTCR(CPU_ISP, (unsigned int)__ISTACK(0));: CPU_ISP 레지스터에 ISTACK(0) 심볼 값을 설정한다. CPU_ISP 레지스터는 인터럽트 스택 포인터를 저장하는 레지스터이며, ISTACK(0)은 링커/로케이터 설정에 의해 정의된 CPU0 인터럽트 스택의 시작 주소를 나타낸다.

Ifx_Ssw_setCpuEndinitInline(&MODULE_SCU.WDTCPU, cpuWdtPassword);: CPU 감시 타이머의 Endinit 비트를 설정한다. Endinit 비트는 특정 레지스터에 대한 쓰기 보호를 제어하며, 이를 설정하면 이후 코드에서 보호된 레지스터를 수정할 수 없게 된다.

Ifx_Ssw_disableCpuWatchdog(&MODULE_SCU.WDTCPU, cpuWdtPassword);, Ifx_Ssw_disableSafetyWatchdog(safetyWdtPassword);: CPU 감시 타이머와 안전 감시 타이머를 비활성화합니다. C 런타임 초기화 과정에서 감시 타이머가 트리거되는 것을 방지하기 위해 일시적으로 비활성화한다.

Ifx_Ssw_C_Init();: C 런타임 변수를 초기화한다. 전역 변수 초기화, 메모리 영역 초기화 등 C 런타임 환경을 설정하는 데 필요한 작업을 수행한다.

Ifx_Ssw_enableSafetyWatchdog(safetyWdtPassword);: 안전 감시 타이머를 다시 활성화합니다. C 런타임 초기화가 완료된 후 안전 감시 타이머를 활성화하여 시스템의 안전을 보장합니다.

Ifx_Ssw_setCpu0Idle();: CPU0를 Idle 모드로 설정한다.IFX_CFG_SSW_ENABLE_TRICORE0 설정에 따라 CPU0를 사용하지 않을 경우 Idle 모드로 설정하여 전력 소모를 줄입니다.

Ifx_Ssw_enableCpuWatchdog(&MODULE_SCU.WDTCPU, cpuWdtPassword);: CPU 감시 타이머를 다시 활성화합니다. CPU0를 사용하는 경우 main 함수 실행 전에 CPU 감시 타이머를 다시 활성화합니다.

Ifx_Ssw_jumpToFunction(core0_main);: CPU0의 main 함수 (core0_main)로 점프하여 실행을 시작합니다. 이 코드를 통해 CPU0는 런타임 환경 설정, 인터럽트 및 트랩 처리 준비, 감시 타이머 제어 등을 완료하고 main 함수를 실행할 준비를 갖추게 됩니다.

이상 일련의 과정을 거치면 드디어 User Code에 도달하게 된다.

void core0_main(void)
{
    IfxCpu_enableInterrupts();
    
    /* !!WATCHDOG0 AND SAFETY WATCHDOG ARE DISABLED HERE!!
     * Enable the watchdogs and service them periodically if it is required
     */
    IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
    IfxScuWdt_disableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
    
    /* Wait for CPU sync event */
    IfxCpu_emitEvent(&g_cpuSyncEvent);
    IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
    
    initLED();  /* Initialize the LED port pin      */

    while(1)
    {
        blinkLED(); /* Make the LED blink           */
    }
}
profile
자동차 구동용 인버터 S/W를 개발하고 있습니다. 전력변환제어기의 임베디드 TDD 실천에 많은 노력을 하고있습니다.

0개의 댓글