FatFs f_write no funciona en LPC1788 Temporizador ISR

2

Estoy usando MCU LPC1788 con el compilador KeilV5.

Tengo un ISR de temporizador en el que leo un canal de ADC específico de un formulario de valor y lo escribo en una tarjeta SD utilizando la biblioteca FATFS.

Aquí está mi código ISR del temporizador:

void TIMER1_IRQHandler(void){
 if (TIM_GetIntStatus(LPC_TIM1, TIM_MR1_INT)== SET){
    ADC_Init(LPC_ADC,838);
    ADC_ChannelCmd (LPC_ADC,0,ENABLE);
    while (!(ADC_ChannelGetStatus(LPC_ADC,0, ADC_DATA_DONE)));
    ADCResult = ADC_ChannelGetData(LPC_ADC,0);
    sprintf(OutputSample,"%ld\r\n",ADCResultScaled);    
    f_lseek(&File1, f_size(&File1));
    //f_write(&File1,OutputSample,strlen(OutputSample), &FilePointer);              
    Counter++;
    TIM_ClearIntPending(LPC_TIM1, TIM_MR1_INT);
  }     
}

No hay ningún problema con el código anterior, pero cuando elimino el comentario de la función f_write, el programa se detiene y no se ejecuta nada exactamente después de habilitar Timer1.

Por lo tanto, no puedo escribir los datos en la tarjeta SD en el temporizador ISR.

Debo mencionar que la función f_write funciona bien fuera del temporizador ISR.

¿Puedes adivinar dónde está el problema?

Gracias de antemano.

    
pregunta Nima

2 respuestas

4

Por lo general, es una muy, muy mala idea usar FatFS desde interrupciones. El patrón más común es adquirir los datos en el ISR, almacenar en algún lugar y tener una tarea de bucle principal que almacena los datos en cola en algún lugar.

Si su controlador SPI usa interrupciones y usted no habilita las interrupciones anidadas (tema avanzado), entonces sus interrupciones SPI no se ejecutarán hasta que se complete la interrupción del temporizador.

    
respondido por el filo
3

+1 para @filo, que resolvió correctamente el problema de las interrupciones anidadas o no está habilitado (o tiene la misma prioridad, por lo tanto no se activa).

Sin embargo, el problema no es con el SPI (que normalmente no se usa con interrupción en el FatFS, a menos que se realicen algunas modificaciones importantes en el código. El SPI se usa en el sondeo, con las funciones xmit_spi() y xmit_spi_multi() ).

El problema radica en el disk_timerproc() , que debe llamarse (con una interrupción) cada ms, para los tiempos de espera y para actualizar el estado de la tarjeta (tarjeta insertada, protegida contra escritura, etc.).

En el ejemplo de LPC17xx, disk_timerproc() es llamado por SysTick_Handler() .

Por lo tanto, tiene dos formas:

  1. Use un número de prioridad más alto (es decir, dé una prioridad más baja) para el TimerISR, que en realidad lee el ADC.
  2. O deje que Timer_ISR () establezca una variable global volátil "dataAvailable = 1", y luego, en el ciclo principal, guarde los datos, cuando dataAvailable es 1.

Por ejemplo

volatile dataAvailable = 0;
[...] other code[...]
void main (void)
{
   [...] other code [...]
   while (1)
   {
      [...] other code [...]
      if (dataAvailable)
      {
         dataAvailable = 0;
         saveData();
      }
   }
}
void TIMER1_IRQHandler(void)
{
   if (TIM_GetIntStatus(LPC_TIM1, TIM_MR1_INT)== SET)
   {
      [...] other code [...]
      dataAvailable = 1;
      TIM_ClearIntPending(LPC_TIM1, TIM_MR1_INT);
   }     
}
    
respondido por el next-hack

Lea otras preguntas en las etiquetas