background image

 

 

IAR

KOMPILATOR V4

background image

 

 

Kompilator V3 umożliwia pisanie programów w języku C lub C++. Dla obydwu 
języków można wybrać wersję podstawową (standard języka) lub rozszerzoną. 
Ustawień dokonuje się w nakładce IDE.

Dostęp do nazw rejestrów specjalnych i wybranych bitów poprzez dołączenie do 
programu źródłowego pliku iodevice.h, gdzie device typ procesora, np.: 
io430x14x.h. 

Dla asemblera odpowiedni plik ma nazwę mspdevice.h, np.: 

msp430x14x.h.

background image

 

 

Zmienna typu bool jest dostępna w kompilatorze C++. Jeżeli ma być użyta w C, to należy do
programu dołączyć plik z biblioteką stdbool.h. 

Zmienne całkowite:

zmienna

rozmiar

zakres

rozmieszczenie

bool*

1 bit

0 - 1

1

char

8 bitów

0 – 255

1

signed char

8 bitów

- 128 - +127

1

unsigned char

8 bitów

0 - 255

1

signed short

16 bitów -32768 - 32767

2

unsigned short

16 bitów 0 – 65535

2

signed int 16

16 bitów -32768 - 32767

2

unsigned int

16 bitów 0 – 65535

2

signed long 32

32 bity

2

31

 – 2

31

 - 1

2

unsigned long

32 bity

0 - 2

32

 - 1

2

signed long long 64 bity

-2

63

 – 2

63

 - 1

4

unsigned long

64 bity

0 - 2

64

 - 1

4

background image

 

 

Rozmieszczenie danych w 
pamięci:

Zmienna dwubajtowa: 0x1234

1     2    3    4

adres

ofset

1

0

Zmienna czterobajtowa: 
0x12345678

1     2    3    4

adres

ofset

1

0

5     6    7    8

3

2

background image

 

 

Liczby zmiennoprzecinkowe - wg standardu IEEE 754

Eksponenta              Mantysa      

S

31  30               23 22                           
    0

Typ zmiennej

Zakres

double = 32

Zakres

double = 64

float

32 bity

32 bity

double

32 bity

64 bity

long double

32 bity

64 bity

Zmienna 32 bitowa:

      zakres         ±1.18E-38 to ±3.39E+38

      wyrażenie   (-1)

S

 * 2

(Exponent-127)

 * 1.Mantissa 

      położenie 

      precyzja     operacje (+, -, *, /) w przybliżeniu 7 cyfr dziesiętnych         

background image

 

 

Eksponenta              Mantysa      

S

63  62               52 51                           
    0

Zmienna 64 bitowa:

       eksponenta   11 bitów

       mantysa        51 bitów

       zakres           ±2.23E-308 to ±1.79E+308

       wyrażenie      (-1)

S

 * 2

(Exponent-1023)

 * 1.Mantissa

       położenie

       precyzja        operacje (+, -, *, /)  w przybliżeniu 15 cyfr dziesiętnych    

Zero jest reprezentowane przez w postaci zera mantysy i eksponenty. Bit znaku 
określa zero dodatnie lub ujemne.
Nieskończoność jest przedstawiania przez ustawienie maksymalnej wartości 
eksponenty i zera mantysy.
Brak liczby (NaN) jest przedstawiane przez ustawienie maksymalnej dodatniej 
wartości eksponenty i jedynki na najbardziej znaczącej pozycji mantysy. Wartośc 
znaku jest ignorowana.

UWAGA: Biblioteka CLIB nie w pełni obsługuje specjalne przypadki liczb zmienno 
przecinkowych takie jak nieskończoność i NaN. Należy dokładnie zapoznać się z 
funkcjami obsługującymi te szczególne przypadki. 

background image

 

 

Wskaźniki adresowe - dwa rodzaje:

- wskaźniki do programu

- wskaźniki do danych

Dla procesorów MSP430 oba typy wskaźników są 16 bitowe

Dla procesorów MSP430X wskaźnik do danych jest 16 bitowy i umożliwia 
adresowanie 64 KB pamięci, a wskaźnik do programu jest 32 bitowy i umożliwia 
adresowanie 1 MB pamięci.

background image

 

 

Wstawki asemblerowe:

W tekście źródłowym pisanym w C/C++ można robić wstawki asemblerowe po 
poleceniu __asm lub asm. Polecenie __asm działa zawsze, natomiast asm nie działa w 
C z opcją --strict_ansi.

Użycie jest następujące: asm(”łańcuch_znakowy”)

gdzie łańcuch_znakowy oznacza instrukcję asemblerową lub asemblerową definicję 
danej, ale nie może być komentarzem. Np.:

......

__asm("MOV.B &P1IN,&flag");

asm(”Label: nop\n”

         ”jmp Label”);

Ograniczenia:

    optymalizacja wykonywana przez kompilator może być znacznie ograniczona dla 
instrukcji        

asemblerowych,

    dyrektywy asemblera mogą wywoływać błędy lub być pomijane,

    nie jest kontrolowane poprawne położenie zmiennych,

    nie ma dostępu do zmiennych automatycznych.

background image

 

 

Funkcje.

Funkcja może być z atrybutem lub nie. Miejsce umieszczenia atrybutu podaje 
poniższy przykład:

__interrupt void int_func(void)

 {.....}

lub

void(__interrupt int_func)(void)

{.....}

lub

#pragma type_attribute=__interrupt

void int_func(void)

{.....}

background image

 

 

Funkcje obsługujące przerwania:

- Przerwania podstawowe

#pragma vector = 0x14

--interrupt void int_func(void)

  {.......}

-Generator przerwań (Timer A, Timer B, I

2

C, ADC12)

#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A1_ISR(void)
 {
  switch (__even_in_range(TAIV, 10))
  {
   case 2: P1POUT = 0x04;
   break;
   case 4: P1POUT = 0x02;
   break;
   case 10: P1POUT = 0x01;
   break;
  }
 }

background image

 

 

Funkcja obsługująca przerwanie chowa na stos wszystkie używane rejestry. Można to 
zmienić przez użycie polecenia __raw lub __task:

__raw __interrupt void int_func()

__task __interrupt void int_func()

Polecenie __monitor blokuje przerwanie dla funkcji, przed którą występuje:

__monitor int test(void);

Funkcje ustawiające stan przerwań:

void __enable_interrupt(void);

//odblokowanie przerwania

void __disable_interrupt(void);

//zablokowanie przerwania

background image

 

 

Łączenie programów pisanych w C i w asemblerze.

Parametry mogą być wnoszone do funkcji poprzez rejestry lub/i stos. Do 
wnoszenia parametrów są wykorzystywane następujące rejestry:

Parametry

Rejestry

 8 bitowe

R12,  R14

16 bitowe

R12,  R14

32 bitowe

R13:R12, R15:R14

64 bitowe

R15:R14:R13:R12, 

R11:R10:R9:R8

Pozostałe parametry wejściowe są wnoszone poprzez stos:

Zmienne lokalne

Parametr n

........

Parametr 2

Parametr 1

Adres powrotu

Wolna pamięć stosu

wskaźnik stosu

adres wysoki

adres niski

background image

 

 

Poprzez stos są również wnoszone parametry związane z uniami, strukturami i 
klasami, a także nienazwane parametry do funkcji o zmiennej liczbie parametrów, 
np. funkcji  printf.

Zwracanie parametrów przez funkcje:

Parametr

Rejestr

8 bitowy

R12

16 bitowy

R12

32 bitowy

R13:R12

64 bitowy

R15:R14:R13:R12

Jeżeli funkcja zwraca strukturę, adres w pamięci, pod którym struktura się 
znajduje jest przekazywany poprzez rejestr R12 jako parametr ukryty.

background image

 

 

Przykład 1:

    int prz_1(int a);

Asembler:

    add

#1,R12

    ret

Przykałd 2:

struct a_struct { int a; };
int a_function(struct a_struct x, int y);

    Funkcja wywołująca rezerwuje na górze stosu 4 bajty gdzie umieszcza dane 
związane ze strukturą. Parametr y jest przenoszony poprzez rejestr R12. Wartośc 
funkcji jest zwracana również w rejestrze R12.

Przykład 3:

struct a_struct { int a; };
struct a_struct a_function(int x);

    Wskaźnik do struktury, która jest umieszczona na stosie, jest przenoszony jako 
parametr ukryty w rejestrze R12. Zmienna x jest przenoszona poprzez rejestr R14. 
Wskaźnik do struktury jest zwracany poprzez rejestr R12.

background image

 

 

Funkcja szkieletowa:

extern int gInt;
extern double gDouble;
int func(int arg1, double arg2)
{
int locInt = arg1;
gInt = arg1;
gDouble = arg2;
return locInt;
}
int main()
{
int locInt = gInt;
gInt = func(locInt, gDouble);
return 0;
}

Optym,alizacja musi być ustawiona na niskim poziomie.

background image

 

 

Funkcje specjalne

a = __bcd_add_short(b, c)

        - operacje dodawania na liczbach BCD

a = __bcd_add_long(b, c)

a = __bcd_add_long_long(b, c)

__bic_SR_register(unsigned short);         - kasuje wskazane w danej bity rejestru SR

__bic_SR_register_on_exit(unsigned short);  - kasuje wskazane w danej bity rejestru 
SR przed 

           powrotem funkcji typu interrupt 

lub monitor  

__bis_SR_register(unsigned short);          - ustawia wskazane w danej bity rejestru SR

__bis_SR_register_on_exit(unsigned short);  - ustawia wskazane w danej bity rejestru 
SR przed 

           powrotem funkcji typu interrupt 

lub monitor __disable_interrupt();

 

       - blokuje przerwania

__enable_interrupt();

       - odblokowuje przerwania

unsigned short __even_in_range(adr, zakr)   - przekazuje wartość ze wskazanego 
adresu i 

         podanym zakresie. Dla funkcji 

switch przy 

         obsłudze przewań

background image

 

 

__get_interrupt_state(void):

- pobiera stan przerwań

__istate_t s = __get_interrupt_state();

__disable_interrupt();

/* ..................... */

__set_interrupt_state(s);

unsigned short __get_R4_register(void);

                - zwraca zawartość rejestru 

R4*

unsigned short __get_R5_register(void);

               - zwraca zawartość rejestru 

R5*

unsigned short __get_SP_register(void);               - zwraca zawartość rejestru SP

unsigned short __get_SR_register(void);               - zwraca zawartość rejestru SR

unsigned short __get_SR_register_on_exit(void); - zwraca zawartość rejestru SR w 
funkcjach 

interrupt monitor

void __low_power_mode_n(void);

              - wprowadza tryb oszczędnościowy n (0 - 

4)

void __low_power_mode_off_on_exit(void);         - wyprowadza procesor z trybu 

oszczędnościowego przy 

wyjściu z procedury 

obsługi przerwania

void __set_interrupt_state(__istate_t);

             - odtwarza stan przerwań

void __set_R4_register(unsigned short);

             - wpisuje daną do rejestru R4*

void __set_R5_register(unsigned short);              - wpisuje daną do rejestru R5*

* Tylko dla zablokowanych rejestrów

background image

 

 

void __no_operation(void);

- rozkaz nop

void __set_SP_register(unsigned short);

- wpisuje daną do rejestru SP

unsigned short __swap_bytes(unsigned short);

- zamiana połówkowa danej

a = __swap_bytes(0x1234);

//a = 3412

background image

 

 

Plik źródłowy 
*.C

Plik źródłowy 
*.s43

Kompilator

Asembler

Linke
r

Symulator

Debugger

background image

 

 

W kompilatorze (ale tylko dla procesorów MSP430X) można uzyskać 
domyślny dostęp do pamięci poprzez wybór modelu danych, co nie 
przeszkadza na ulokowanie wybranej danej w dowolnym miejscu pamięci.

Modele pamięci:

Small – określa segment data16 co oznacza pierwszych 64 KB pamięci. 
Dostęp  do 

pełnego obszaru 1MB jest tylko poprzez użycie funkcji 

intrinsic.
Medium – wyznacza segment data16 jako domyślny i tam są lokowane 
dane, ale 

nie ogranicza to dostępu do całej pamięci 1MB.

Large – określa segment data20 jako pamięć domyślną, co oznacza dostęp 
do całej 

pamięci.

Model pamięci może być wybierany opcją --data_model
Zmiana modelu dla wybranej danej lub danych może nastąpić poleceniem

#pragma type_attribute

__data20 int i, j;
int __data20 k, l;

background image

 

 

background image

 

 

typedef char __data20 Byte;
typedef Byte *BytePtr;
Byte b;
BytePtr bp;

Odpowiada:

__data20 char b;
char __data20 *bp;

Wskaźniki:

int __data20 * p;

//deklaracja wskaźnika do zmiennej 

umieszczonej w 

//zakresie 1MB. Położenie 

wskaźnika nie jest określone. 
char __data16 * __data20 p2;

//wskaźnik jest umieszczony w obszarze 

1MB a 

//zmienna w obszarze 64 KB.

background image

 

 

struct MyStruct
{
int alpha;
int beta;
};
__data20 struct MyStruct gamma;

//zmienna gamma jest strukturą 

umieszczoną w 

//1 MB pamięci.

Zła deklaracja:
struct MySecondStruct
{
int blue;
__data20 int green; 

//błąd. Cała struktura musi być w tym 

samym 

//obszarze pamięci

};

background image

 

 

int a; 

//zmienna deklarowana w pamięci domyślnej określonej 

przez 

//model pamięci

int __data16 b;  //zmienna w obszarze 64 KB
__data20 int c; // zmienna w obszarze 1 MB 
int * d;

//wskaźnik w pamięci domyślnej do zmiennej typu int w 

pamięci 

//domyślnej. 

int __data16 * e;

// wskaźnik w pamięci domyślnej do zmiennej typu 

int w pamięci 

// 64 KB

int __data16 * __data20 f; 

// wskaźnik w pamięci 1 MB do zmiennej w 

pamięci 64 KB int __data20 * myFunction(int __data16 *);

//deklaracja funkcji z parametrem który jest wskaźnikiem 

zmiennej 

//int w pamięci 64 KB. Funkcja zwraca wskaźnik do 

zmiennej int w 

//pamięci 1 MB. 

background image

 

 

C++
//deklaracja klasy umieszczona w pliku nagłówkowym:

class MyClass
{
public:
int alpha;
int beta;
__data20 static int gamma;
};

//potrzebna deklaracja w pliku źródłowym:

__data20 int MyClass::gamma;

// deklaracja zmiennej:

__data16 MyClass delta;

background image

 

 

Zmienne deklarowane wewnątrz funkcji nazywane auto zmiennymi są 
umieszczane w rejestrach lub na stosie. Zmienne te są aktualne tylko na 
czas wykonywania funkcji

Funkcje obsługi przerwań dla modelu Small chowają na stos tylko 16 bitów 
z 20 bitowych rejestrów. Można to zmienić poleceniem __save_reg20

background image

 

 

Lokowanie zmiennych globalnych i statycznych pod adresami 
absolutnymi.

Dwie możliwości:
 - operator @
 - dyrektywa #pragma location 
Dane muszą być zadeklarowane jako no_init i/lub const.
Jeżeli dana jest deklarowana jako const to musi być inicjalizowana chyba 
że jest deklarowana jako __no_init.
Lokowanie zmiennej pod adresem absolutnym wymaga by argument 
operatora @ lub dyrektywy #pragma location liczbą wskazującą na 
określony adres. Adres musi być zgodny z typem deklarowanej zmiennej.

Uwaga: Definicja zmiennej lokowanej pod adresem absolutnym może 
być umieszczona w pliku nagłówkowym który może być dołączany do 
każdego modułu wykorzystującego tę zmienną. Wystarczy normalna 
deklaracja extern. Niewykorzystana w module definicja będzie 
ignorowana. 

background image

 

 

W C++ zmienne const są typu static (w lokalnych modułach). Oznacza to, 
że każdy moduł, w którym deklaruje się pewną liczbę zmiennych typu 
const będzie zawierał oddzielne zmienne o tej samej nazwie. Jeżeli 
nastąpi linkowanie kilku takich modułów zawierających , poprzez plik 
nagłówkowy, deklaracje:
volatile const __no_init int x @ 0x100
linker zgłosi, że jest więcej jak jedna zmienna ulokowana pod adresem 
0x100. problem ten można rozwiązać w C i C++ poleceniem extern:
extern volatile const __no_init int x @ 0x100; 
extern upublicznia zmienną x.

__no_init volatile char alpha @ 0x0200;
Zmienna deklarowana poleceniem __no_init jest lokowana pod stałym 
adresem. Ułatwia to komunikacje pomiędzy różnymi modułami, procesami 
itp.
#pragma location=0x0202
__no_init const int beta;
 

//bez inicjalizacji

const int gamma @ 0x0204 = 3; 

//z inicjalizacją

background image

 

 

Deklaracje z błedami:
int delta @ 0x0206; 

//brak "__no_init" ,lub "const"

__no_init int epsilon @ 0x0207; 

//zły adres – dla int powinien by 

parzysty

background image

 

 

Lokowanie funkcji pod wskazanym adresem:
void f(void) @ "FUNCTIONS";
void g(void) @ "FUNCTIONS"
{
}
#pragma location="FUNCTIONS"
void h(void);
Dla zmiany domyślnego obszaru pamięci można użyć deklaracji:
__data20 void f(void) @ "FUNCTIONS";

background image

 

 

Deklaracje asemblera

background image

 

 

background image

 

 

background image

 

 

Poniższy przykład pokazuje tablicę adresów do podprogramów:

NAME table
RSEG CONST
table DW addsubr, subsubr, clrsubr
RSEG CODE
addsubr ADD R4,R5
RET
subsubr SUB R4,R5
RET
clrsubr CLR R4
RET
END


Document Outline