490 likes | 708 Views
Riistvarapõhine programmeerimine. Loeng 14 ARM kontrollerite programmeerimine C-s I osa. ARM programmeerimine. Andmetüübid Tsüklid Registrite jaotus Funktsiooni väljakutsumine Viida pseudonüümid. Kompillaatorid I. void memclr (char *data, int N) { for (N; N>0; N--) { *data = 0;
E N D
Riistvarapõhine programmeerimine Loeng 14 ARM kontrollerite programmeerimine C-s I osa
ARM programmeerimine • Andmetüübid • Tsüklid • Registrite jaotus • Funktsiooni väljakutsumine • Viida pseudonüümid ID218 Riistvaralähedane programmeerimine
Kompillaatorid I void memclr (char *data, int N) { for (N; N>0; N--) { *data = 0; data++; } } ID218 Riistvaralähedane programmeerimine
Kompillaatorid II • N ??? • N = 0 • N != 0 • *data / 4 ??? • *data = 4X, data => int, 32-bits • *data != 4X, data => char, 8-bits ID218 Riistvaralähedane programmeerimine
Andmetüübid I ID218 Riistvaralähedane programmeerimine
Andmetüübid II ID218 Riistvaralähedane programmeerimine
Andmetüübid, local variable I • Char • Sobib 8-bit arvutamisel • Muudel juhtudel vältida • Short • Sobib 8-bit arvutamisel • Muudel juhtudel vältida • Int - saab alati kasutada ID218 Riistvaralähedane programmeerimine
Andmetüübid, local variable II int checksum (int *data) { char i; int sum = 0; for (i = 0; i < 64; i++) { sum = sum + data[i]; } return sum; } ID218 Riistvaralähedane programmeerimine
Andmetüübid, local variable III • Char i • Vajab vähe mälu • Vajab vähe registriruumi • Vajab vähe pinuruumi Asub registris Registrid on 32-bit Pinu on 32-bit ID218 Riistvaralähedane programmeerimine
Andmetüübid, local variable IV checksum MOV r2, r0 ; r2 = data MOV r0, #0 ; sum = 0 MOV r1, #0 ; i = 0 cs_loop: LDR r3, [r2, r1, LSL #2] ; r3 = data ADD r1, r1, #1 ; r1 = i + 1 AND r1, r1, #0xFF ; i = (char)r1 CMP r1, #0x40 ; compare i, 64 ADD r0, r3, r0 ; sum = sum + r3 BCC cs_loop ; if (i < 64) loop MOV pc, r14 ; return Kokku 10 rida, loop 6 rida (char i) ID218 Riistvaralähedane programmeerimine
Andmetüübid, local variable V int checksum (int *data) { unsigned int i; int sum = 0; for (i = 0; i < 64; i++) { sum = sum + data[i]; } return sum; } ID218 Riistvaralähedane programmeerimine
Andmetüübid, local variable VI checksum MOV r2, r0 ; r2 = data MOV r0, #0 ; sum = 0 MOV r1, #0 ; i = 0 cs_loop: LDR r3, [r2, r1, LSL #2] ; r3 = data ADD r1, r1, #1 ; r1 = i + 1 CMP r1, #0x40 ; compare i, 64 ADD r0, r3, r0 ; sum = sum + r3 BCC cs_loop ; if (i < 64) loop MOV pc, r14 ; return Kokku 10 rida, loop 5 rida (int i) ID218 Riistvaralähedane programmeerimine
Andmetüübid, local variable VII short checksum (short *data) { unsigned int i; short sum = 0; for (i = 0; i < 64; i++) { sum = (short)(sum + data[i]); } return sum; } Short checksum, 16-bit ID218 Riistvaralähedane programmeerimine
Andmetüübid, local variable VIII checksum MOV r2, r0 ; r2 = data MOV r0, #0 ; sum = 0 MOV r1, #0 ; i = 0 cs_loop: ADD r3, r2, r1, LSL #1 ; r3 = &data[i] LDRH r3, [r3, #0] ; r3 = data[i] ADD r1, r1, #1 ; r1 = i + 1 CMP r1, #0x40 ; compare i, 64 ADD r0, r3, r0 ; sum = sum + r3 MOV r0, r0, LSL #16 MOV r0, r0, ASR #16 ; sum = (short)r0 BCC cs_loop ; if (i < 64) loop MOV pc, r14 ; return Kokku 12 rida, loop 8 rida (short data) ID218 Riistvaralähedane programmeerimine
Andmetüübid, local variable IX • LDRH • Ei luba scaled register index [r2, r1, LSL #1] • Tuleb lisada eraldi ADD • Kitsendamine 32-bit -> 16-bit • Märk peab säilima (sum) • Vajab 2 x MOV ID218 Riistvaralähedane programmeerimine
Andmetüübid, local variable X short checksum (short *data) { unsigned int i; int sum = 0; for (i = 0; i < 64; i++) { sum += *(data++); } return short)sum; } Indeksi asemel viit (*data) ID218 Riistvaralähedane programmeerimine
Andmetüübid, local variable XI checksum MOV r2, #0 ; sum = 0 MOV r1, #0 ; i = 0 cs_loop: LDRSH r3, [r0], #2 ; r3 = *(data++) ADD r1, r1, #1 ; r1 = i + 1 CMP r1, #0x40 ; compare i, 64 ADD r2, r3, r2 ; sum = sum + r3 BCC cs_loop ; if (i < 64) loop MOV r0, r2, LSL #16 MOV r0, r0, ASR #16 ; sum = (short)r0 MOV pc, r14 ; return Kokku 10 rida, loop 5 rida (viit *data) ID218 Riistvaralähedane programmeerimine
Andmetüübid, function argument I • Argumendi kitsemaks tegemine • Caller • Callee • Pass • Return ID218 Riistvaralähedane programmeerimine
Andmetüübid, function argument II Caller > Callee < Pass Return ID218 Riistvaralähedane programmeerimine
Andmetüübid, function argument III short sum (short a, short b) // a + 2b { return a + (b>>1); } sum ADD r0, r0, r1, ASR #1 ; r0 = (int)a+((int)b>>1) MOV r0, r0, LSL #16 MOV r0, r0, ASR #16 ; r0 = (short)r0 MOV pc, r14 ; return ID218 Riistvaralähedane programmeerimine
Andmetüübid, unsigned vs signed I • Liitmine - Ei ole vahet • Lahutamine - Ei ole vahet • Korrutamine - Ei ole vahet • Jagamine - Unsigned ID218 Riistvaralähedane programmeerimine
Andmetüübid, unsigned vs signed II int average (int a, int b) { return (a + b) / 2; } average ADD r0, r0, r1 ; r0 = a + b ADD r0, r0, r0, LSL #31; if (r0 < 0) r0 = r0 + 1 MOV r0, r0, ASR #1 ; r0 = r0>>1 MOV pc, r14 ; return ID218 Riistvaralähedane programmeerimine
Andmetüübid, unsigned vs signed III • (x < 0) ? ((x + 1)>>1): (x>>1) • x < 0 => (x + 1)>>1 • X => 0 => x>>1 • -3/2 = -2 • -3>>1 = -1 ID218 Riistvaralähedane programmeerimine
Tsükklid • Tsükkel kindla iteratsiooniarvuga • Tsükkel muutuva iteratsiooniarvuga ID218 Riistvaralähedane programmeerimine
Tsükkel kindla iteratsiooniarvuga I int checksum (int *data) { unsigned int i; int sum = 0; for (i = 0; i < 64; i++) { sum += *(data++); } return sum; } ID218 Riistvaralähedane programmeerimine
Tsükkel kindla iteratsiooniarvuga II checksum MOV r2, r0 ; r2 = data MOV r0, #0 ; sum = 0 MOV r1, #0 ; i = 0 cs_loop: LDR r3, [r2], #4 ; r3 = *(data++) ADD r1, r1, #1 ; r1 = i + 1 CMP r1, #0x40 ; compare i, 64 ADD r0, r3, r0 ; sum = sum + r3 BCC cs_loop ; if (i < 64) loop MOV pc, r14 ; return Loop => kolm rida Kokku 9 rida, loop 5 rida ID218 Riistvaralähedane programmeerimine
Tsükkel kindla iteratsiooniarvuga III • Tsükkel for (i = 0; i < 64; i++) • ADD • CMP • BCC • Kolm käsku • Loop overhead ID218 Riistvaralähedane programmeerimine
Tsükkel kindla iteratsiooniarvuga IV int checksum (int *data) { unsigned int i; int sum = 0; for (i = 64; i != 0; i--) { sum += *(data++); } return sum; } ID218 Riistvaralähedane programmeerimine
Tsükkel kindla iteratsiooniarvuga V checksum MOV r2, r0 ; r2 = data MOV r0, #0 ; sum = 0 MOV r1, #0x40 ; i = 0 cs_loop: LDR r3, [r2], #4 ; r3 = *(data++) SUBS r1, r1, #1 ; r1 = i - 1 and flags ADD r0, r3, r0 ; sum = sum + r3 BNE cs_loop ; if (i != 0) loop MOV pc, r14 ; return LOOP => Kaks rida (overhead) Kokku 8 rida, loop 4 rida ID218 Riistvaralähedane programmeerimine
Tsükkel kindla iteratsiooniarvuga VI int checksum (int *data) { int i; int sum = 0; for (i = 64; i > 0; i--) { sum += *(data++); } return sum; } ID218 Riistvaralähedane programmeerimine
Tsükkel kindla iteratsiooniarvuga VII checksum MOV r2, r0 ; r2 = data MOV r0, #0 ; sum = 0 MOV r1, #0x40 ; i = 0 cs_loop: LDR r3, [r2], #4 ; r3 = *(data++) SUB r1, r1, #1 ; r1 = i - 1 CMP r1, #0 ; compare i, 0 ADD r0, r3, r0 ; sum = sum + r3 BGT cs_loop ; if (i != 0) loop MOV pc, r14 ; return Kokku 9 rida, loop 5 rida ID218 Riistvaralähedane programmeerimine
Tsükkel muutuva iteratsiooniarvuga I int checksum (int *data, unsigned int N) { int sum = 0; for (N; N != 0; N--) { sum += *(data++); } return sum; } ID218 Riistvaralähedane programmeerimine
Tsükkel muutuva iteratsiooniarvuga II checksum MOV r2, #0 ; sum = 0 CMP r1, #0 ; compare N, 0 BEQ end ; if (N == 0) end cs_loop: LDR r3, [r0], #4 ; r3 = *(data++) SUBS r1, r1, #1 ; r1 = N - 1 and flags ADD r2, r3, r2 ; sum = sum + r3 BNE cs_loop ; if (N != 0) loop end: MOV r0, r2 ; r0 = sum MOV pc, r14 ; return Kokku 9 rida, loop 4 rida ID218 Riistvaralähedane programmeerimine
Tsükkel muutuva iteratsiooniarvuga III int checksum (int *data, unsigned int N) { int sum = 0; do { sum += *(data++); } while (--N != 0); return sum; } ID218 Riistvaralähedane programmeerimine
Tsükkel muutuva iteratsiooniarvuga IV checksum MOV r2, #0 ; sum = 0 cs_loop: LDR r3, [r0], #4 ; r3 = *(data++) SUBS r1, r1, #1 ; r1 = N - 1 and flags ADD r2, r3, r2 ; sum = sum + r3 BNE cs_loop ; if (N != 0) loop end: MOV r0, r2 ; r0 = sum MOV pc, r14 ; return Kokku 7 rida, loop 4 rida ID218 Riistvaralähedane programmeerimine
Registrite jaotus • Lokaalmuutujad • Registrites • Mälus (spilled) • Kokku 16 registrit • Eriotstarbed - 4 registrit • Muutujatele - 12 registrit ID218 Riistvaralähedane programmeerimine
Funktsiooni väljakutsumine I • Nelja registri reegel • r0 – parameeter, vastus • r1. r2, r3 – parameetrid • Ülejäänud parameetrid pinus ID218 Riistvaralähedane programmeerimine
Funktsiooni väljakutsumine II • Kasutada 1 – 4 parameetrid • Kasutada struktuurid ID218 Riistvaralähedane programmeerimine
Funktsiooni väljakutsumine III char *queue ( char *q_start, /* queue start address */ char *q_end, /* queue end address */ char *q_ptr, /* queue pointer */ char *data, /* data to insert */ unsigned int N) /* number of bytes to insert */ { do { *(q_ptr++) = *(data++); if (q_ptr == q_end) { q_ptr = q_start; } } while (--N); return q_ptr; } ID218 Riistvaralähedane programmeerimine
Funktsiooni väljakutsumine IV queue STR r14, [r13, #-4]! ; save lr to stack LDR r12, [r13, #4] ; r12 = N q_loop LDRB r14, [r3], #1 ; r14 = *(data++) STRB r14, [r2], #1 ; *(q_ptr++) = r14 CMP r2, r1 ; if (q_ptr == q_end) MOVEQ r2, r0 ; q_ptr = q_start SUBS r12, r12, #1 ; --N and flag BNE q_loop ; if (N != 0) loop MOV r0, r2 ; r0 = q_ptr LDR pc, [r13], #4 ; return Pinu operatsioon, N ID218 Riistvaralähedane programmeerimine
Funktsiooni väljakutsumine VI typedef struct { char *q_start, /* queue start address */ char *q_end, /* queue end address */ char *q_ptr, /* queue pointer */ } Queue; void queue_bytes (Queue *queue, char *data, unsigned int N) { char *q_ptr = queue->q_ptr; char *q_end = queue->end; do { *(q_ptr++) = *(data++); if (q_ptr == q_end) { q_ptr = queue->q_start; } } while (--N); queue->q_ptr = q_ptr; } ID218 Riistvaralähedane programmeerimine
Funktsiooni väljakutsumine VII queue STR r14, [r13, #-4]! ; save lr to stack LDR r3, [r0, #8] ; r3 = queue->q_ptr LDR r14, [r0, #4] ; r14 = queue->q_end q_loop LDRB r12, [r1], #1 ; r12 = *(data++) STRB r12, [r3], #1 ; *(q_ptr++) = r12 CMP r3, r14 ; if (q_ptr == q_end) LDREQ r3, [r0, #0] ; q_ptr = queue->q_start SUBS r2, r2, #1 ; --N and flag BNE q_loop ; if (N != 0) loop STR r3, [r0, #8] ; queue->q_ptr = r3 LDR pc, [r13], #4 ; return Ilma pinu operatsioonita ID218 Riistvaralähedane programmeerimine
Viida pseudonüümid I • Viit - viidab mälupesale • Ühele peasle – mitu viida • Viida pseudonüümid ID218 Riistvaralähedane programmeerimine
Viida pseudonüümid II void timers ( int *timer1, int *timer2, int *step) { *timer1 += *step; *timer2 += *step; } ID218 Riistvaralähedane programmeerimine
Viida pseudonüümid III timers LDR r3, [r0, #0] ; r3 = *timer1 LDR r12, [r2, #0] ; r12 = *step ADD r3, r3, r12 ; r3 += r12 STR r3, [r0, #0] ; *timer 1 = r3 LDR r0, [r1, #0] ; r0 = *timer2 LDR r2, [r2, #0] ; r2 = step ADD r0, r0, r2 ; r0 += r2 STR r0, [r1, #0] ; *timer2 = r0 MOV pc, r14 ; return Kaks korda loeme *step ID218 Riistvaralähedane programmeerimine
Viida pseudonüümid IV void timers ( int *timer1, int *timer2, int *step) { int timer_step = *step; *timer1 += timer_step; *timer2 += timer_step; } ID218 Riistvaralähedane programmeerimine
Kokkuvõte I • Lokaalmuutuja - int • Jagamine - unsigned • Massiiv - sobiva suurusega andmetüüb • Massiiv – mäluviit • Kitsendamiseks – LDR ja STR operatsioonid • Vältida 16-bit ja 8-bit funktsioonide kasutamisel ID218 Riistvaralähedane programmeerimine
Kokkuvõte II • Tsükli muutuja -> 0 • Tsükli muutuja - unsigned • Tingimus i != 0, mitte i > 0 • do– while, kui tsükkel täidetakse vähemalt 1 kord ID218 Riistvaralähedane programmeerimine
Kokkuvõte III • Lokaalmuutujatele 12 registrit • Funktsioonid - kuni 4 parameetrit • Viida pseudonüümid – globaalmuutujad avaldistes ID218 Riistvaralähedane programmeerimine