SCALETTA LEZIONE SERT E8 -- 22 novembre 2012 *** Funzioni e macro di utilita' per lo sviluppo 1. Aggiungere funzioni _iomem_high, _iomem_low, _iomem_toggle in ts7250.h +--------------------------------------------------------------+ |static inline void _iomem_high(unsigned int reg, u32 mask) | |{ | | iomem[reg] |= mask; | |} | |static inline void _iomem_low(unsigned int reg, u32 mask) | |{ | | iomem[reg] &= ~mask; | |} | |static inline void _iomem_toggle(unsigned int reg, u32 mask) | |{ | | iomem[reg] ^= mask; | |} | +--------------------------------------------------------------+ 2. Aggiungere macro per i led in ts7250.h +-----------------------------------------------------+ |#define _led_on(V) _iomem_high(LED, (V)) | |#define _led_off(V) _iomem_low(LED, (V)) | |#define _led_toggle(V) _iomem_toggle(LED, (V)) | |#define led_red_on() _led_on(2UL) | |#define led_red_off() _led_off(2UL) | |#define led_red_toggle() _led_toggle(2UL) | |#define led_green_on() _led_on(1UL) | |#define led_green_off() _led_off(1UL) | |#define led_green_toggle() _led_toggle(1UL) | +-----------------------------------------------------+ 3. Aggiungere funzioni _panic() e _greenpanic() in init.c +---------------------------------+ |void _panic(void) | |{ | | unsigned long d; | | for (;;) { | | d = 75000UL; | | while (d-- > 0) | | __memory_barrier(); | | led_red_toggle(); | | } | |} | |void _greenpanic(void) | |{ | | unsigned long d; | | for (;;) { | | d = 75000UL; | | while (d-- > 0) | | __memory_barrier(); | | led_green_toggle(); | | } | |} | +---------------------------------+ *** Inizializzazione della tabella di vettori d'interruzione 4. Aggiungere a _init() l'inizializzazione della tabella dei vettori di interruzione +-------------------------------------------------------------+ |extern int _reset(void); | |#define LDR_PC_PC 0xe59ff018 | |#define FAKE_ENTRY 0x2badc0dea | |void _init(void) | |{ | | volatile u32 * vector = (u32 *) 0; | | vector[0] = LDR_PC_PC; /* Reset */ | | vector[1] = LDR_PC_PC; /* Undefined instruction */ | | vector[2] = LDR_PC_PC; /* Software interrupt */ | | vector[3] = LDR_PC_PC; /* Prefetch abort */ | | vector[4] = LDR_PC_PC; /* Data abort */ | | vector[5] = FAKE_ENTRY; /* Reserved */ | | vector[6] = LDR_PC_PC; /* IRQ vector */ | | vector[7] = LDR_PC_PC; /* FIQ vector */ | | vector[8] = (u32) _reset; /* Reset */ | | vector[9] = (u32) _panic; /* Undefined instruction */ | | vector[10] = (u32) _panic; /* Software interrupt */ | | vector[11] = (u32) _panic; /* Prefetch abort */ | | vector[12] = (u32) _panic; /* Data abort */ | | vector[13] = FAKE_ENTRY; /* Reserved */ | | vector[14] = (u32) _panic; /* IRQ vector */ | | vector[15] = (u32) _panic; /* FIQ vector */ | +-------------------------------------------------------------+ 4.1 Prova del funzionamento: aggiungere asm("swi 0") in main() 4.2 Sostituire _panic() con _greenpanic() in vector[10] *** Supporto per l'output su porta seriale 5 Consultare i manuali per informazioni su come si programma la porta seriale 5.1 Il manuale della scheda TS-7250 rimanda al manuale del chip EP9301 5.2 Il manuale del chip EP9301 dedica piu' di 70 pagine alla programmazione della porta seriale. Tre possibilita': 5.2.1 Programmazione tramite DMA: nel trasferimento dei dati non e' coinvolta la CPU 5.2.2 Programmazione tramite interruzioni: la CPU trasferisce i dati, e le interruzioni segnalano la presenza di dati in ricezione o la disponibilita' di spazio nel buffer di trasmissione 5.2.3 Programmazione tramite CPU polling: la CPU trasferisce i dati, e controlla attivamente lo stato dei buffer di ricezione e trasmissione 5.3 Scegliere la strada piu' semplice: programmiamo la porta seriale tramite CPU polling. Determinare posizione e funzionamento dei registri di I/O della porta seriale, in particolare il registro di dati e quello che informa sullo stato del buffer di trasmissione 5.3.1 Registro UART1Data (0x808c0000) R/W Lettura: dato ricevuto. Scrittura: dato da trasmettere 5.3.2 Registro UART1Flag (0x808c0018) R Bit 0: CTS (Clear To Send) Bit 1: DSR (Data Set Ready) Bit 2: DCD (Data Carrier Detect) Bit 3: BUSY (Busy while transmitting) Bit 4: RXFE (Receive FIFO Empty) Bit 5: TXFF (Trasmit FIFO Full) Bit 6: RXFF (Receive FIFO Full) Bit 7: TXFE (Transmit FIFO Empty) 5.4 Aggiornare ts7250.h aggiungendo le definizioni occorrenti +-------------------------------------------------------+ |/*** UART1 ***/ | |static const unsigned int UART1Data = 0x808c0000 / 4; | |static const unsigned int UART1Flag = 0x808c0018 / 4; | |#define UART1FlagTXFF (1UL<<5) | +-------------------------------------------------------+ 5.5 Scrivere file uart1.c 5.5.1 Funzione putc() per scrivere un singolo carattere +-----------------------------------------------+ |void putc(int ch) | |{ | | while ((iomem[UART1Flag] & UART1FlagTXFF)) | | /* do nothing */ ; | | iomem[UART1Data] = ch; | |} | +-----------------------------------------------+ 5.5.2 Aggiungere extern per putc() in comm.h: extern void putc(int); 5.5.3 Provare la funzione putc() modificando main() 5.5.4 Funzione puts() per scrivere una stringa di caratteri +----------------------------+ |void puts(const char * st) | |{ | | while (*st) { | | putc(*st); | | if (*st++ == '\n') | | putc('\r'); | | } | |} | +----------------------------+ 5.5.5 Aggiungere extern per puts() in comm.h: extern void puts(const char *); 5.6 Rinominare main() in endless_led_blinking() 5.7 Scrivere nuova main() che stampa su seriale ed invoca endless_led_blinking() +--------------------------------------------------------------------------+ |void main(void) | |{ | | puts("==========================================================\n"); | | puts("SERT: System Environment for Real-Time, version 2012.11.22\n"); | | puts("SERT is a learning tool for the SERT course\n"); | | puts("Marco Cesati, SPRG, DISP, University of Rome Tor Vergata\n"); | | puts("==========================================================\n"); | | endless_led_blinking(); | |} | +--------------------------------------------------------------------------+ *** Stampa di numeri in esadecimale 6 Scrivere funzione puth() in uart1.c per stampare un valore senza segno in esadecimale 6.1 Valore a 32 bit in esadecimale --> 8 caratteri in '0'...'9','a'...'f' 6.2 Scrivere la funzione puth() +--------------------------------------------+ |void puth(unsigned long v) | |{ | | int i, d; | | u32 mask; | | mask = 0xf0000000; | | for (i=0; mask != 0; i+=4, mask>>=4) { | | d = (v & mask) >> (28-i); | | putc(d+(d>9?'a'-10:'0')); | | } | |} | +--------------------------------------------+ 6.3 Aggiungere extern per puth() in comm.h: extern void puth(unsigned long); 6.4 Provare la funzione stampando in main() il valore 195936478 =========