Usar la interrupción STM32 con FreeRTOS

4

Estoy confundido al usar interrupciones definidas por HAL con FreeRTOS. Estoy intentando implementar "6.3 Procesos de interrupción diferida" en la guía de FreeRTOS, pero no sé cómo hacerlo.

El problema es cómo usar los periféricos del STM32 con FreeRTOS. Debería asignar un semáforo a otra tarea (que lea y trate los valores) dentro del irqn "ADC_IRQHandler ()" para el ADC o la devolución de llamada "HAL_ADC_ConvCpltCallback ()" para el ADC o simplemente lea los valores con las funciones HAL y los trato con Tareas de FreeRTOS (esta funciona, pero parece que no usa la potencia RTOS)

El manual del que hablo: (PDF)

    
pregunta shi

1 respuesta

2

En primer lugar, el semáforo se puede dar en "ADC_IRQHandler ()" o "HAL_ADC_ConvCpltCallback ()" (ADC) agregando:

BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(xBinarySemaphore, &xHigherPriorityTaskWoken);
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);

Al final de la función, parece que "HAL_ADC_ConvCpltCallback" también es un ISR cuando uso xSemaphoreGive( xBinarySemaphore); . Con ello se bloquea el programa.

También es importante establecer la prioridad de IRQHandler numéricamente más alta que configMAX_SYSCALL_INTERRUPT_PRIORITY, en mi caso '80', agregando (5 por ejemplo). HAL_NVIC_SetPriority(ADC_IRQn, 5, 0); , prioridad 5? 15 en mi caso. Puede consultar esto para obtener más información: enlace .

De todos modos, este código funciona y toma el inicio de ADC de enlace .

Código

#include "stm32f4xx.h"
#include "stm32f4_discovery.h"


#include <stdlib.h>
#include <string.h>

#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"


SemaphoreHandle_t xBinarySemaphore=NULL;
ADC_HandleTypeDef g_AdcHandle;
uint32_t g_ADCValue=0;

void SystemClock_Config(void);
void ConfigureADC();
static void ledL( void*); // Task to change the brightness of the LED 12 of GPIOD when changing the value of potentiometer
static void vHandlerTask( void*); // Task to toggle GPIOD 13 every time a conversion is achieved and sleep for 300 ms
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef*);
void ADC_IRQHandler();

int main(void){

    HAL_Init();
    SystemClock_Config();
    ConfigureADC();
    HAL_NVIC_SetPriority(ADC_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(ADC_IRQn);

    GPIO_InitTypeDef GPIO_InitStructure;
    __GPIOD_CLK_ENABLE();
    GPIO_InitStructure.Pin = GPIO_PIN_12|GPIO_PIN_13;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStructure.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);


    vSemaphoreCreateBinary(xBinarySemaphore);

    if( xBinarySemaphore != NULL ){

        xTaskCreate(vHandlerTask, "Task 1", 1000, NULL, 1, NULL);
        xTaskCreate(ledL, "Task 2", 1000, NULL, 1, NULL);
        vTaskStartScheduler();
    }

    for(;;){}
}

//ISR
void ADC_IRQHandler(){
    HAL_ADC_IRQHandler(&g_AdcHandle);
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR( xBinarySemaphore, &xHigherPriorityTaskWoken );
    portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}

//CALLBACK CALLED WHEN CONVERTION COMPLETE
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle){

    g_ADCValue = HAL_ADC_GetValue(AdcHandle);
}

static void vHandlerTask( void *pvParameters ){

    HAL_ADC_Start_IT(&g_AdcHandle);

    for( ;; ){
        xSemaphoreTake( xBinarySemaphore, portMAX_DELAY );
        HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_13);
        vTaskDelay(pdMS_TO_TICKS(200UL));

    }
}

static void ledL( void *pvParameters ){
    for (;;)
    {
        int onTime = g_ADCValue;
        int offTime = 4096 - onTime;
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
        for (int i = 0; i < onTime; i++)
            asm("nop");

        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
        for (int i = 0; i < offTime; i++)
            asm("nop");
    }
}

void SystemClock_Config(void)
{
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_OscInitTypeDef RCC_OscInitStruct;

    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 8;
    RCC_OscInitStruct.PLL.PLLN = 288;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ = 6;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4);
    SystemCoreClockUpdate();

    if (HAL_GetREVID() == 0x1001)
        __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
}

void ConfigureADC()
{
    GPIO_InitTypeDef gpioInit;

    __GPIOC_CLK_ENABLE();
    __ADC1_CLK_ENABLE();

    gpioInit.Pin = GPIO_PIN_1;
    gpioInit.Mode = GPIO_MODE_ANALOG;
    gpioInit.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &gpioInit);

    HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(ADC_IRQn);

    ADC_ChannelConfTypeDef adcChannel;

    g_AdcHandle.Instance = ADC1;

    g_AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
    g_AdcHandle.Init.Resolution = ADC_RESOLUTION_12B;
    g_AdcHandle.Init.ScanConvMode = DISABLE;
    g_AdcHandle.Init.ContinuousConvMode = ENABLE;
    g_AdcHandle.Init.DiscontinuousConvMode = DISABLE;
    g_AdcHandle.Init.NbrOfDiscConversion = 0;
    g_AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    g_AdcHandle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
    g_AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    g_AdcHandle.Init.NbrOfConversion = 1;
    g_AdcHandle.Init.DMAContinuousRequests = ENABLE;
    g_AdcHandle.Init.EOCSelection = DISABLE;

    HAL_ADC_Init(&g_AdcHandle);

    adcChannel.Channel = ADC_CHANNEL_11;
    adcChannel.Rank = 1;
    adcChannel.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    adcChannel.Offset = 0;

    if (HAL_ADC_ConfigChannel(&g_AdcHandle, &adcChannel) != HAL_OK)
    {
        asm("bkpt 255");
    }
}
    
respondido por el shi

Lea otras preguntas en las etiquetas

Comentarios Recientes

_r o más por un poco de velocidad y sintonice su sonda STM32 M0 para maximizar el voltaje real que sentiría la sonda en el momento de la aplicación.16) Aplique voltaje para todos los núcleos según sea necesario y luego vuelva a probar. Por lo general, la corriente de muestra de prueba en los parámetros de reposo y las rutas ajustadas ya no son posibles al abrir la tabla de muestra para esta CPU. Tendrá que ajustar los voltajes para obtener más núcleos de CPU con los que desee intentar aplicaciones de overclocking,... Lees verder