Su flex full vorrei mettere in atto un semplice meccanismo che sfrutta gli ISR di tipo 2, per interrompere la lettura da UART nel caso di interrupt del timer1; in pratica sto cercando di realizzare un rudimentale Timeout.
Il main() setta l'oscillatore interno con PLL, a 40MIPS a questo punto inizializza i leds e poi la UART infine attiva il task1 se protocol_comunication_start() ritorna 1.
main:
Code: Select all
int main()
{
/* Clock setup initialization for 40MIPS */
CLKDIVbits.DOZEN = 0;
CLKDIVbits.PLLPRE = 0;
CLKDIVbits.PLLPOST = 0;
PLLFBDbits.PLLDIV = 78;
/* Wait for PLL to lock */
while(OSCCONbits.LOCK!=1);
/* let's start the multiprogramming environment...*/
StartOS(OSDEFAULTAPPMODE);
/* Init leds */
EE_leds_init();
/* Init UART */
ee_usb_init(); //richiama la funzione di libreria, eeuart.h, EE_UART1_Init()
//START TASK1--HANDSHAKING -> protocol_comunication_start()
while ( !protocol_comunication_start() );
EE_led_on();
ActivateTask(Task1);
/* now the background activities: in this case, we do nothing. */
for (;;);
return 0;
}
protocol_comunication_start():
Code: Select all
BYTE protocol_comunication_start(){
BYTE msg, reply[2];
msg = 0x3A;
ee_usb_write(&msg, 1);
EE_led_on();
T1_program(); //programma il timer1 così che possa generare un interrupt dopo 1ms
ee_usb_read_len(&reply[0],2, &timeout);
/* spengo il led, lettura completata */
EE_led_off();
/* se la lettura è andata a buon fine non mi serve più il timeout, perciò spengo il timer1 */
T1_clear();
T1CONbits.TON = 0;
if (reply[0]==0x30 && reply[1]==0x31){
return 1; //se i dati letti sono quelli che mi servono per la corretta inizializzazione allora ritorna 1
}
return 0; //ripeti invio di msg
}
Code: Select all
__INLINE__
void ee_usb_write(BYTE *ch, BYTE len)
{
unsigned int i;
for (i=0;i<len;i++)
{
EE_UART1_Send(*(ch++)); //dalla libreria eeuart.h
}
}
Code: Select all
__INLINE__
void ee_usb_read_len(BYTE *data, BYTE len, volatile int* timeout)
{
BYTE i;
for (i=0;i<len;i++){
while (!IFS0bits.U1RXIF || (*timeout) != 1);
/* ho ricevuto qualcosa sulla UART allora spengo il timer1 */
T1_clear();
T1CONbits.TON = 0;
if( (*timeout) != 1){
while (EE_UART1_Receive(data++)); //dalla libreria eeuart.h
IFS0bits.U1RXIF = 0;
}
else {
(*timeout)=0;
break;
}
}
}
Il Timer1 ogni 1ms (PR1 = 0x9c40) fa scattare un interrupt gestito da un semplice ISR2 che spegne il timer e cambia il valore della variabile globale timeout impostandola ad 1.
Timer1 e funzioni associate:
Code: Select all
void T1_program(void)
{
T1CON = 0; /* Stops the Timer1 and reset control reg */
TMR1 = 0; /* Clear contents of the timer register */
PR1 = 0x9c40; /* Load the Period register wit the value 0x9c40 (1ms @ 40MIPS) */
IPC0bits.T1IP = 5; /* Set Timer1 priority to 1 */
IFS0bits.T1IF = 0; /* Clear the Timer1 interrupt status flag */
IEC0bits.T1IE = 1; /* Enable Timer1 interrupts */
T1CONbits.TON = 1; /* Start Timer1 with prescaler settings at 1:1
* and clock source set to the internal
* instruction cycle */
}
void T1_clear(void)
{
IFS0bits.T1IF = 0;
}
ISR2(_T1Interrupt)
{
/* clear the interrupt source */
T1_clear();
T1CONbits.TON = 0; //spengo il timer
timeout=1;
}
Quello che posso notare è che effettivamente il valore di timeout viene cambiato nel momento in cui si attiva l'interrupt ma il valore utilizzato nel while di ee_usb_read_len() invece non cambia, timeout vale sempre 0, nonostante abbia utilizzato un passaggio per riferimento.
Dove sto sbagliando?
Sicuramente ci sono metodi più furbi per implementare il timeout, magari qualche registro della UART che gestiste proprio questo...gentilmente potreste indicarmi la strada?
Inoltre ne approfitto per altre 2 domandine:
-Ho visto sulla flex full che ci sono ben 6 leds, però con le istruzioni EE_led_init(), EE_led_on() e EE_led_off() posso sfruttare solo 1 led, esso è collegato alla porta PORTB.
Per poter usare gli altri leds (con escusione dei primi 3 led verdi che segnalano l'alimentazione) quali registri dovrei attivare? E' possibile scrivere una fuzione tipo EE_led_on() che agisca su i registri opportuni per attivare quei leds? Sul datasheet della flex non ho trovato riferimenti a quali registri fossero collegati.
-Gli ISR2 vanno dichiarati con una stringa associata ad un tipo di interrupt tipo (_T1Interrupt) o (_U1RXInterrupt) dove posso trovare un elenco delle stringhe che mi permettono di associare interrupt agli IRS2 ?
Grazie mille e scusate il post chilometrico.