PRÁCTICA 4 SADQ

mail@pastecode.io avatar
unknown
c_cpp
2 years ago
8.0 kB
1
Indexable
Never
#define __STM32__
//#define __ESP32__
//#define __ESP8266__

#include <Arduino.h>
#include <STM32TimerInterrupt.h>
#include "TimerInterrupt_Generic.h"

// INCLUDES FOR AVR BOARDS using Library "FreeRTOS" by Richard Barry
#if defined(__AVR__)
    #include <Arduino_FreeRTOS.h>
    #include <semphr.h>  // add the FreeRTOS functions for Semaphores (or Flags).
    typedef void * xTaskHandle;
#endif
// INCLUDES FOR STM32 BOARDS using Library "STM32duino FreeRTOS" by STM32duino
#if defined(__STM32__)
  #include <STM32FreeRTOS.h>
#endif
// INCLUDES FOR ESPRESSIF BOARDS (ESP32). DO NOT NEED ANY FreeRTOS LIBRARY but needs to include 
// <esp_task_wdt.h> to disable teh WATCHDOG timer
#if defined(__ESP32__)
  #include <esp_task_wdt.h>
#endif

// If no default pin for user button (USER_BTN) is defined, define it
#ifndef USER_BTN
   #define USER_BTN 2
#endif

// Set LED_BUILTIN if it is not defined by Arduino framework
// #define LED_BUILTIN 13

uint8_t pushButton = USER_BTN;

// Declare a mutex Semaphore Handle which we will use to manage the Serial Port.
// It will be used to ensure only only one Task is accessing this resource at any time.
SemaphoreHandle_t xSerialSemaphore;
xTaskHandle xTask1Handle, xTask2Handle, xTaskPriorityHandle;    

int PriorityTask1,PriorityTask2;

// define two Tasks for DigitalRead & AnalogRead
void Task1( void *pvParameters );
void Task2( void *pvParameters );
void TaskPriority( void *pvParameters );

// definir la función de interrupción para la pulsación del botón en el setup() APARTADO 5.3.1
bool button_pressed_setup_switch = true;
void button_pressed_setup() {
  button_pressed_setup_switch = false;
  Serial.print("\nEl botón ha sido pulsado");
  Serial.print("\nA continuación se crearán las tareas.");
  detachInterrupt(digitalPinToInterrupt(USER_BTN));
}

//Declaración de variables tipo BaseType_t para comprobar el estatus de las tareas.
BaseType_t task1Status,task2Status,task3Status;
BaseType_t taskarr[3] = {task1Status, task2Status, task3Status };



// the setup function runs once when you press reset or power the board
void setup() {

  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);

  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.
  }

  // Semaphores are useful to stop a Task proceeding, where it should be paused to wait,
  // because it is sharing a resource, such as the Serial port.
  // Semaphores should only be used whilst the scheduler is running, but we can set it up here.
  if ( xSerialSemaphore == NULL )  // Check to confirm that the Serial Semaphore has not already been created.
  {
    xSerialSemaphore = xSemaphoreCreateMutex();  // Create a mutex semaphore we will use to manage the Serial Port
    if ( ( xSerialSemaphore ) != NULL )
      xSemaphoreGive( ( xSerialSemaphore ) );  // Make the Serial Port available for use, by "Giving" the Semaphore.
  }
  // make the pushbutton's pin an input:
  pinMode(pushButton, INPUT_PULLUP);
  attachInterrupt(USER_BTN,button_pressed_setup,CHANGE);
  //BUCLE WHILE que se asegura que el programa no siga hasta que el usuario pulse el botón.
  while (button_pressed_setup_switch) { 
    Serial.print("Por favor, presione el botón.\n");
    delay(10);
  }

  
  
  // Now set up three Tasks to run independently.

  task1Status = xTaskCreate(
    TaskPriority
    ,  "TaskPriority"
    ,  1000  // Stack size
    ,  NULL
    ,  3  // Priority
    ,  &xTaskPriorityHandle);
  
  task2Status = xTaskCreate(
    Task1
    ,  "Task1"  // A name just for humans
    ,  1000  // This stack size can be checked & adjusted by reading the Stack Highwater
    ,  NULL
    ,  1  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,  &xTask1Handle);

  task3Status = xTaskCreate(
    Task2
    ,  "Task2"
    ,  1000  // Stack size
    ,  NULL
    ,  2  // Priority
    ,  &xTask2Handle);

  for (int i = 0; i < 3; i++) { 
    if (taskarr[i] != pdPASS) {
      Serial.printf("\nLa tarea", i, " no se ha inicializado correctamente");
      continue;
    }
    Serial.printf("\nLa tarea", i, "se ha inicializado correctamente.");
  }

  // start scheduler
  #if !defined(__ESP32__)
     vTaskStartScheduler();  // THIS LINE MUST BE COMMENTED FOR ESPRESSIF BOARDS. THEY ALLREADY CALL THIS FUNCTION INTERNALLY
  #endif
}

void loop()
{
  // Idle task.
}

//--------------------------------------------------
//---------------------- Tasks ---------------------
//--------------------------------------------------

void TaskPriority( void *pvParameters __attribute__((unused)) )  // This is a Task.
{  
  #if defined(__ESP32__)
    esp_task_wdt_init(30, false);  // Disable the HW watchdog for 30 seconds, only for ESPRESSIF BOARDS (ESP32)
  #endif

  for (;;) // A Task shall never return or exit.
  {
    // read the input pin:
    int buttonState = digitalRead(pushButton);
    
    if (buttonState==1){
      PriorityTask1 = 1;
      PriorityTask2 = 2;
    } else {
      PriorityTask1 = 2;
      PriorityTask2 = 1;
    }
    vTaskPrioritySet(xTask1Handle, PriorityTask1);
    vTaskPrioritySet(xTask2Handle, PriorityTask2);

    vTaskDelay(1000);  // one tick delay == 1ms
  }
}


void Task1(void* pvParameters __attribute__((unused)))  // This is a Task.
{
    int i;

#if defined(__ESP32__)
    esp_task_wdt_init(30, false);  // Disable the HW watchdog for 30 seconds, only for ESPRESSIF BOARDS (ESP32)
#endif

    for (;;)
    {
        // See if we can obtain or "Take" the Serial Semaphore.
        // If the semaphore is not available, wait 500 ticks of the Scheduler to see if it becomes free.
        //if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 500 ) == pdTRUE )
        {
            // We were able to obtain or "Take" the semaphore and can now access the shared resource.
            // We want to have the Serial Port for us alone, as it takes some time to print,
            // so we don't want it getting stolen during the middle of a conversion.
            // print out the value you read:      
            Serial.print("{");
            for (i = 0; i < 150; i++) {
                Serial.print("_");
            }
            Serial.print("T1: "); Serial.print(PriorityTask1);
            Serial.print(" T2: "); Serial.print(PriorityTask2);
            Serial.println("}");

            //xSemaphoreGive( xSerialSemaphore ); // Now free or "Give" the Serial Port for others.
        }

        //vTaskDelay(15);  // 15 ticks delay (15ms) in between reads for stability    
    }
}


void Task2( void *pvParameters __attribute__((unused)) )  // This is a Task.
{  
  //    Task1: Higher priority (initially)
  int i;

  #if defined(__ESP32__)
    esp_task_wdt_init(30, false);  // Disable the HW watchdog for 30 seconds, only for ESPRESSIF BOARDS (ESP32)
  #endif

  for (;;) // A Task shall never return or exit.
  {
    // See if we can obtain or "Take" the Serial Semaphore.
    // If the semaphore is not available, wait 500 ticks of the Scheduler to see if it becomes free.
    //if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 500 ) == pdTRUE )
    {
      // We were able to obtain or "Take" the semaphore and can now access the shared resource.
      // We want to have the Serial Port for us alone, as it takes some time to print,
      // so we don't want it getting stolen during the middle of a conversion.
      // print out the state of the button:
      Serial.print("[");        
      for (i=0;i<2;i++){
         Serial.print("1");
      }    
      Serial.print("]");

      //xSemaphoreGive( xSerialSemaphore ); // Now free or "Give" the Serial Port for others.
    }
    vTaskDelay(15);  // 15 ticks delay (15ms) in between reads for stability
  }
}