Engineering Agit

[Session 02 TM4C123GXL Study 03] - Programming methods with CCS 본문

Embedded Lab. @ Modu inst./2020 Session 02 (2020.06~)

[Session 02 TM4C123GXL Study 03] - Programming methods with CCS

Sean_Kim95 2020. 8. 11. 16:17

◈ 

 Embedded system의 SW를 설계하는 방식에는 크게 3가지가 있다. 첫번째는 machine language(0과 1로 이루어진 언어)로 프로그래밍하는 것이다. 이 방식은 system이 작동하기에 가장 효율적인 코드를 짤 수 있다는 장점이 있지만 그 방법이 어렵고 프로그램의 가독성이 좋지 못하다. 두번째는 assembly language이다. 이 방식은 machine language보다는 프로그래밍이 쉽고 가독성도 좋으며 한 줄 한 줄이 한 개의 instruction이므로 작동시간을 계산하는 것이 가능하다. 세번째는 C/C++과 같은 고급언어이다. 이번 session에서는 코딩시에는 C를 이용할 것이며 동작체크 시와 instruction 수행시간등을 체크하는 용도로 assembly language를 이용할 것이다.

1. Intro

 'TI peripheral driver library'는 두 가지의 프로그램 방식을 제공하는 데, 하나는 기본적인 register set을 define하고 있는 header를 include하여 모든 설정을 register에 직접 접근하여 하는 방식이고 나머지 하나는 library에서 제공하는 함수들(API functions)를 이용하는 방법이다. 전자를 'Direct register access model', 후자를 'Software driver model'이라고 부른다. 아래는 'TivaWare peripheral driver library user's guide'의 일부분을 발취한 것이다. 아래의 내용에서 

<Fig. 1-1> Introduction 01
<Fig. 1-2> Introduction 02

 

2. Programming model

 위에서 언급했듯이 2가지의 방식의 model이 존재하는데, 각각의 장단점이 있다. DRA(Direct Register Access) model은 SW driver model보다 작고 효율적인 코드를 작성할 수 있지만, 각각의 register과 bit field에 관해 자세한 지식이 필요하고 또한 이들 각각의 상호작용과 peripheral의 적합한 작동을 위해 일련의 정해진 단계로 설정하는 것이 필요하다. SW driver model의 경우 이를 프로그래머가 덜 생각해도 괜찮으므로 공부하는 시간을 단축시킬 수 있다.

  • DRA model

 이 model은 peripheral의 register에 직접 값을 씀으로써 기능을 사용할 수 있는 방식이다. Macro로 register를 먼저 만들어두면 좀 더 단순화해서 프로그래밍이 가능한데 이러한 macro들은 ‘inc’ directory에 part-specific header file로 담겨 있다. TM4C123GXL의 경우에는 ‘inc/ tm4c123gh6pm.h’가 macro들을 담고 있다. 사용하는 부품(MCU)에 맞는 header를 include하여 사용하면 된다. 이 include는 부품의 모든 register에 접근할 수 있고 또한 해당 register의 bit field에도 접근할 수 있다. 사용하지 않는 register의 경우에는 macro로 지정되지 않는다. 

DRA model에서 사용되는 define들은 특정 macro를 어떻게 사용해야하는지 보다 쉽게 알기 위해 다음과 같은 naming convention을 따른다.

  1. Values that end in _R are used to access the value of a register. For example, SSI0_CR0_R is used to access the CR0 register in the SSI0 module.

  2. Values that end in _M represent the mask for a multi-bit field in a register. If the value placed in the multi-bit field is a number, there is a macro with the same base name but ending with _S (for example, SSI_CR0_SCR_M and SSI_CR0_SCR_S). If the value placed into the multi-bit field is an enumeration, then there are a set of macros with the same base name but ending with identifiers for the various enumeration values (for example, the SSI_CR0_FRF_M macro de- fines the bit field, and the SSI_CR0_FRF_NMW, SSI_CR0_FRF_TI, and SSI_CR0_FRF_MOTO macros provide the enumerations for the bit field).

  3. Values that end in _S represent the number of bits to shift a value in order to align it with a multi-bit field. These values match the macro with the same base name but ending with _M.

  4. All other macros represent the value of a bit field.

  5. All register name macros start with the module name and instance number (for example, SSI0 for the first SSI module) and are followed by the name of the register as it appears in the data sheet (for example, the CR0 register in the data sheet results in SSI0_CR0_R).

  6. All register bit fields start with the module name, followed by the register name, and then followed by the bit field name as it appears in the data sheet. For example, the SCR bit field in the CR0 register in the SSI module is identified by SSI_CR0_SCR.... In the case where the bit field is a single bit, there is nothing further (for example, SSI_CR0_SPH is a single bit in the CR0 register). If the bit field is more than a single bit, there is a mask value (_M) and either a shift (_S) if the bit field contains a number or a set of enumerations if not.

 이러한 정의를 이용하면 CR0 reg.(SSIxCRx: Synchronous Serial Interface x Control x; 이 register에서 SSI module의 다양한 기능을 control할 수 있다.)는 다음과 같은 방식으로 프로그래밍할 수 있다:

SSI0_CR0_R = ((5 << SSI_CR0_SCR_S) | SSI_CR0_SPH | SSI_CR0_SPO | SSI_CR0_FRF_MOTO | SSI_CR0_DSS_8);

 다른 방식으로는 다음과 같이 작성할 수 있으며 이는 위의 코드와 같은 효과를 발휘한다. 하지만 이해하기에는 난해하다:

SSI0_CR0_R = 0x000005c7;

<Fig. 2-1> SSIxCR0 bit field diagram

 첫번째 코드에 비해 두번째 코드가 난해한 이유는 둘다 결과는 같은 값이지만, 코드를 짜고 해석하는 사람의 입장에서는 각 bit field 영역이 나누어져 있는 것이 좋기 때문이다.  

 위의 그림에서 보이는 SSIxCR0의 bit field에서 SCR만을 추출해 내는 코드는 다음과 같이 작성할 수 있다. 

ulValue = (SSI0_CR0_R & SSI_CR0_SCR_M) >> SSI0_CR0_SCR_S;

 

 ※주의: Library 내의 driver들에 의해 사용되는 'hw_*.h' header들은 DRA에서 include하는 header들과 동일한 definition을 갖는 것들이 많다. 이 때문에 이들 header들은 symbol들의 redifinition에 대한 경고를 제공하는 컴파일러 없이는 같은 source file에 include될 수 없다.  

 

  • Software driver model

 SW driver model에서 peripheral driver library에 의해 제공되는 API는 peripheral을 control하기 위한 application에 사용된다. 이들 driver들은 작동 정상모드 내에서 peripheral들을 완전히 control하는 것을 제공하기 때문에, HW에 직접 access(register에 access)할 필요없이 총체적인 application을 만들 수 있다. 이 방식은 peripheral을 프로그래밍하는 방식에 대한 자세한 지식없이 빠른 개발이 가능하게 한다.

  DRA model에서의 예시와 같은 코드를 SW driver model을 이용하여 만들면 다음과 같다:

SSIConfigSetExpClk(SSI0_BASE, 50000000, SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER, 1000000, 8);

  위의 코드로 CR0 reg.에 입력된 값은 정확히 DRA model과 같지는 않을 수 있는데 이는 'SSIConfigSetExpClk()'가 계산하는 SCR bit field의 값이 DRA의 그 영역에서의 값과 다를 수 있기 때문이다.

 

  • Combining the models

 위의 두 model을 하나의 application에 사용할 수 있는데, application 내에서 각각의 경우에 따라 적절한 model을 적용한다. 예를 들어, SW driver model은 peripheral을 configure(이는 프로그램의 성능에 영향을 적게 미치는 부분)할 때, DRA model은 peripheral의 동작(프로그램의 성능에 영향을 보다 크게 미치는 부분)에서 사용된다. 혹은, SW driver model은 프로그램의 성능에 크게 영향을 미치지 않는 peripheral(ex. data logging을 위한 UART)에 사용되고, DRA model은 프로그램의 성능에 크게 영향을 미칠 수 있는 peripheral(ex. 실시간 analog data를 capture하는 데에 사용되는 ADC module)에 사용된다.

 

TivaWare™ Peripheral Driver Library for C Series User's Guide (Rev. E)
Comments