Tasks, memoria e ISR2

Forum relativo alle schede FLEX, ERIKA Enterprise, RT-Druid, ScicosLab, ...

Moderator: paolo.gai

Locked
Bezul

Tasks, memoria e ISR2

Post by Bezul »

Salve a tutti, vi porgo un problemino che mi sta dando parecchi grattacapo, probabilmente è una sciocchezza ma data la mia inesperienza non riesco a venirne fuori.

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() invia semplicemente un carattere tramite UART, utilizzando la funzione ee_usb_send(BYTE *data) e poi la flex si mette in attesa di una risposta con ee_usb_read_len(BYTE *data, BYTE *len, volatile int* timeout).

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

}
ee_usb_write:

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
	}
}
ee_usb_read_len:

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;
                         }
		}
}
Quello che vorrei realizzare è un timeout per impedire che la flex resti in un attesa infinita nel caso non arrivi nulla sulla RX della uart, per fare ciò nella la ee_usb_read_len() c'è un parametro che è il puntatore a una variabile globale, volatile int timeout (inizializzata a 0), che viene utilizzata per interrompere il while di attesa del flag dell'interrupt hardware di ricezione IFS0bits.U1RXIF.
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.
paolo.gai
Administrator
Posts: 877
Joined: Thu Dec 07, 2006 12:11 pm

Re: Tasks, memoria e ISR2

Post by paolo.gai »

wow che post... alcuni consigli veloci:

- a proposito di volatile:
http://www.eetimes.com/discussion/begin ... le-Keyword
verifica hai messo quasi sicuramente il volatile nel punto sbagliato!

- gestisci la lettura all'interno di una macchina a stati finiti che funziona carattere per carattere ad interrupt invece che usare la readlen che usa un ciclo infinito

- se non sbaglio la flex full ha : 3 led alimentazione, 1 led controllato dal dspic, 1 led controllato dal pic18, 1 led per l'usb controllato dal pic18.

- la lista degli interrupt è nel locator file e comunque dipende dal microcontrollore...

PJ
Locked