¿Qué instrucción en el STM32 consume la menor cantidad de energía?

3

El módulo ADC del STM32 se usa en mi aplicación, que es muy sensible al consumo de energía.

En esta aplicación, se requiere que el ADC funcione solo a 20 muestras por segundo. Usar el DMA usa más poder del que esperaba. Decidí hacer que funcionara en modo de muestra única haciendo que una tarea (FreeRTOS) active un converso y espere a que se realice cada 50 ms.

Aquí está mi código:

 u16 i;
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
 ADC_Cmd(ADC1, ENABLE);
 for(i=0;i<sizeof(ADC_Channel_Table)/sizeof(u8);i++)
 {
     ADC_RegularChannelConfig(ADC1, ADC_Channel_Table[i], 1, ADC_SampleTime_71Cycles5);
     ADC_SoftwareStartConvCmd(ADC1, ENABLE);
     while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC))
     {
     }
     ADCConvertedValue[i] = ADC_GetConversionValue(ADC1);
 }
 ADC_Cmd(ADC1, DISABLE);
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE);

Donde "sizeof (ADC_Channel_Table)" es 5 porque se muestrean 5 canales.

El tiempo de muestra es ADC_SampleTime_239Cycles5 (en realidad 256 ciclos donde se incluye el tiempo de conversión). 5 canales por lo tanto requieren aproximadamente 1500 ciclos. El reloj ADC es de 12 MHz y 1500 ciclos son aproximadamente 120 µs.

Y mira el código:

while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC))
{
}

Esto significa que la CPU se mantiene ocupada esperando a que se realice la conversión, y el tiempo de espera es de 120 µs en total.

120 µs es grande ya que la CPU debe esperar tanto tiempo y esto desperdicia energía, pero este nivel de tiempo es demasiado pequeño para el RTOS. El RTOS no puede usar tan poco tiempo.

Así que quiero insertar algunas instrucciones de "ahorro de energía" en el ciclo de espera.

Por ejemplo:

while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC))
{
    __ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");
}

Pero NOP consume la misma cantidad de energía que cualquier otra instrucción que haya probado.

¿Qué instrucción puedo insertar en mi bucle while que consumiría la menor cantidad de energía?

    
pregunta user123179

6 respuestas

21

Si desea ahorrar energía, ponga la MCU en reposo. Las instrucciones relevantes son WFI y WFE: espera para interrupción y espera para evento, respectivamente.

WFI se explica por sí mismo: se despierta cuando se produce una interrupción. (¡La interrupción debe estar habilitada, sin embargo!)

WFE podría merecer un poco más de explicación. Para usarlo, probablemente sea suficiente saber que si configura SEVONPEND, una interrupción que no está habilitada en el NVIC califica como un evento. Entonces, si habilita la interrupción ADC en el periférico pero no en el NVIC, puede esperar a que se complete con WFE. Aún use el bucle con la marca de verificación, ya que podría haber otros eventos que activen la MCU. (Simplemente reemplace los NOP con un WFE) Como es habitual, para obtener información más detallada, consulte el manual de referencia.

Probablemente también querrá seleccionar a qué tiempo de sueño profundo desea ir, pero la forma en que se haga dependerá de la MCU STM32 específica que esté usando. Al menos en un modelo, las banderas relevantes fueron PDDS, LPDS y SLEEPDEEP. En cualquier caso, querrá leer la sección correspondiente del manual de referencia.

    
respondido por el Aleksi Torhamo
6

Intentemos responder la pregunta opuesta para explicar por qué NOP no ahorra energía. El Cortex-M3 es un procesador diseñado para ser pequeño y relativamente simple: no tiene muchos de los circuitos diseñados para realizar tareas dedicadas (cachés, punto flotante, predicción de bifurcaciones) o, en su caso, son implementaciones limitadas a obtén el mayor impacto al menor costo.

La mayoría de las instrucciones avanzan por el conducto de 3 etapas haciendo cantidades similares de trabajo. Obtención de instrucciones, decodificación y una operación ALU. Para aumentar la potencia, tal vez podríamos agregar una transferencia de datos (que ilumine más lógica fuera del núcleo, pero lo más probable es que se detenga toda la tubería ya que el núcleo está en orden). Tal vez podríamos usar la división de un solo ciclo justo después de realizar una transferencia de datos; allí es posible que se realicen simultáneamente dos partes adicionales de actividad. Sin embargo, tal vez hacer esto reducirá la actividad del archivo de registro, por lo que no todos ayudan a alcanzar la potencia máxima.

Aunque hay alguna instrucción de variación de instrucción (y una buena cantidad de esfuerzo de diseño para optimizar esto), la mayor parte de la potencia activa no depende demasiado de las instrucciones. Claro, llenar la tubería con varios NOP detendrá cualquier actividad de alternancia, pero la tubería aún avanzará. El bloqueo de la tubería (para una transferencia de datos lenta) hará mucho más, pero el único estado bien definido en el que puede confiar para ser óptimo será WFI y los diversos estados de suspensión.

Los núcleos más grandes tendrán mucho más picos a la media porque una mayor proporción de su silicio estará inactivo en un bucle inactivo predicho y predicho (y probablemente más lógica activa en el chip, que a menudo también puede ser reloj). / Power Gated)

    
respondido por el Sean Houlihane
4

Si está satisfecho con las muestras cada 62.5ms o 31.25ms (a diferencia de los 50ms), puede usar la función de alarma RTC para activar el STM32 y el modo de espera / parada entre conversiones. Esto ahorrará energía de forma masiva, especialmente si configura el ADC para que pase al modo de bajo consumo después de la conversión (esto puede depender de la serie STM32). Si inicia una conversión, entra en modo de espera / parada, una vez que despierte, la conversión se completará de todos modos. Esto agrega una latencia de una muestra y requiere que usted procese la muestra antes de comenzar una nueva muestra, pero dependiendo de su aplicación, esto puede ser factible.

Flujo:

Inicie la conversión de ADC y habilite la alarma RTC

Entrar en modo de parada / modo de espera

Una vez que RTC haya despertado el microcontrolador, tome el valor de conversión ADC

Muestra de proceso (tienda / filtro, etc.)

¡Comienza el proceso otra vez!

Los modos de parada y de espera usan muy poca energía, por lo que, dependiendo de su aplicación, este puede ser un método adecuado.

    
respondido por el Pyrohaz
3

Buscaría usar un temporizador para iniciar la conversión y una interrupción para recopilar el resultado.

El núcleo de la CPU puede dormir hasta que los datos estén disponibles.

    
respondido por el Simon Richter
0

Como alternativa a dormir, es posible que pueda configurar el generador de reloj para que solo proporcione al núcleo uno de cada 2, 4, 8, etc. relojes que entren en el chip. Si la CPU tendrá que realizar muchas operaciones que requieran seis ciclos de código, pero solo puede activarse una vez cada 64 ciclos debido a restricciones de hardware externo, reducir la velocidad de la CPU a 1/8 puede ser el boleto. Si bien el uso de un modo inactivo con activación de interrupción puede ser mejor que dejar la CPU a toda velocidad, es posible que la CPU deba pasar muchos ciclos para cada evento en la configuración de las transiciones de inactividad / activación. Algunos controladores tienen opciones para establecer velocidades por separado para la línea principal en comparación con los controladores de interrupción, de modo que incluso si la línea principal reduce la velocidad de la CPU a 1/8, los controladores de interrupción funcionarán a la velocidad normal. Sin embargo, no creo que esa sea una característica terriblemente común. De lo contrario, deberá elegir una velocidad que sea lo suficientemente rápida para trabajar con cualquier controlador de interrupción que pueda ejecutarse mientras se realiza la E / S en cuestión.

    
respondido por el supercat
0
  1. Configura un temporizador con un intervalo de 1 / 20s para iniciar una conversión
  2. Habilite la interrupción ADC y maneje el resultado allí

O si un ligero jitter del reloj no es un problema.

  1. Configure un temporizador FreeRTOS de 50 ms. Son eficientes
  2. Habilite la interrupción ADC y maneje el resultado allí

Para poner el MCU en modo de suspensión, simplemente coloca a asm ("WFI") en el bucle inactivo de FreeRTOS.

Tengo una situación similar, pero acabo de alinear todo con el temporizador de tick de FreeRTOS 1ms.

    
respondido por el pkuhar

Lea otras preguntas en las etiquetas