Browse Source

Added module for Task Sheduler.

Vladimir N. Shilov 3 years ago
parent
commit
7c59cf421b
7 changed files with 243 additions and 0 deletions
  1. 1 0
      Inc/main.h
  2. 55 0
      Inc/rtos.h
  3. 4 0
      MNC-IN12x5.cbp
  4. 1 0
      Makefile
  5. 3 0
      Src/main.c
  6. 177 0
      Src/rtos.c
  7. 2 0
      Src/stm32g0xx_it.c

+ 1 - 0
Inc/main.h

@@ -51,6 +51,7 @@ extern "C" {
 #include "gpio.h"
 #include "ds3231.h"
 #include "bme280.h"
+#include "rtos.h"
 
 /* USER CODE END Includes */
 

+ 55 - 0
Inc/rtos.h

@@ -0,0 +1,55 @@
+/******************************************************************************************
+ * За основу взят планировщик задач с сайта ChipEnable.ru                                 *
+ * http://chipenable.ru/index.php/programming-avr/item/110-planirovschik.html             *
+ *                                                                                        *
+ * Доработал Шибанов Владимир aka KontAr                                                  *
+ * Дата: 26.03.2014                                                                       *
+ *                                                                                        *
+ * Изменения:                                                                             *
+ * - добавлен однократный вызов задачи                                                    *
+ * - добавлено удаление задачи по имени                                                   *
+ * - при повторном добавлении задачи обновляются ее переменные                            *
+ * - добавлен указатель на "хвост" списка                                                 *
+ * - функции РТОС скорректированы с учетом "хвоста"                                       *
+ ******************************************************************************************
+ * shilov, 2015.04.07									  *
+ * совместил с модулем милисекундных задержек на таймере				  *
+ ******************************************************************************************/
+#pragma once
+#ifndef RTOS_H
+#define RTOS_H
+
+#include "stm32g0xx.h"
+
+/* Количество задач */
+#define MAX_TASKS      20
+
+/**
+ * Структура задачи
+ */
+typedef struct task
+{
+   void (*pFunc) (void);  // указатель на функцию
+   uint32_t delay;  // задержка перед первым запуском задачи
+   uint32_t period; // период запуска задачи
+   uint8_t run;     // флаг готовности задачи к запуску
+} task;
+
+/**
+ * Прототипы фукнций
+ */
+void RTOS_Init (void);
+void RTOS_SetTask (void (*taskFunc)(void), uint32_t taskDelay, uint32_t taskPeriod);
+void RTOS_DeleteTask (void (*taskFunc)(void));
+void RTOS_DispatchTask (void);
+void RTOS_Timer (void);
+
+void tdelay_ms(uint32_t msek);
+
+inline void tdelay_us(uint32_t usek) {
+  uint32_t us = usek + SysTick->VAL;
+
+  while ((SysTick->VAL + usek) < us) { };
+}
+
+#endif

+ 4 - 0
MNC-IN12x5.cbp

@@ -98,6 +98,7 @@
 		<Unit filename="Inc/ds3231.h" />
 		<Unit filename="Inc/gpio.h" />
 		<Unit filename="Inc/main.h" />
+		<Unit filename="Inc/rtos.h" />
 		<Unit filename="Inc/stm32_assert.h" />
 		<Unit filename="Inc/stm32g0xx_it.h" />
 		<Unit filename="Makefile" />
@@ -111,6 +112,9 @@
 		<Unit filename="Src/main.c">
 			<Option compilerVar="CC" />
 		</Unit>
+		<Unit filename="Src/rtos.c">
+			<Option compilerVar="CC" />
+		</Unit>
 		<Unit filename="Src/stm32g0xx_it.c">
 			<Option compilerVar="CC" />
 		</Unit>

+ 1 - 0
Makefile

@@ -43,6 +43,7 @@ Src/main.c \
 Src/stm32g0xx_it.c \
 Src/ds3231.c \
 Src/bme280.c \
+Src/rtos.c \
 Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_utils.c \
 Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_exti.c \
 Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_ll_gpio.c \

+ 3 - 0
Src/main.c

@@ -147,6 +147,7 @@ int main(void)
   MX_TIM16_Init();
   MX_TIM17_Init();
   /* USER CODE BEGIN 2 */
+  RTOS_Init();
   // __enable_irq();
   //LL_Init1msTick(rcc_clocks.HCLK_Frequency);
   //LL_mDelay(1);
@@ -198,6 +199,7 @@ int main(void)
   RTC_ReadAll(&Clock);
   while (Flag.I2C_RX_End == 0) { __NOP(); };
 
+  tdelay_ms(10);
   /* BME280 Recommended mode of operation: Indoor navigation */
   SensorDev.settings.osr_h = BME280_OVERSAMPLING_1X;
   SensorDev.settings.osr_p = BME280_OVERSAMPLING_16X;
@@ -268,6 +270,7 @@ int main(void)
     }
     SPI_StartTX();
 
+    RTOS_DispatchTask();
     //__WFI();
   }
   /* USER CODE END 3 */

+ 177 - 0
Src/rtos.c

@@ -0,0 +1,177 @@
+#include "main.h"
+
+/*
+ * Переменные модуля
+ */
+static volatile task TaskArray[MAX_TASKS]; // очередь задач
+static volatile uint8_t arrayTail;         // "хвост" очереди
+
+// счётчик задержки
+static volatile uint32_t TDelay;
+
+/*
+ * Инициализация РТОС и t_delay, время тика - 1 мс
+ */
+inline void RTOS_Init(void) {
+  // настраиваем основной таймер
+  SysTick->LOAD  = (uint32_t)(SystemCoreClock/1000 - 1UL);          /* set reload register */
+  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
+  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
+                   SysTick_CTRL_TICKINT_Msk   |
+                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
+
+  // "хвост" в 0
+  arrayTail = 0;
+}
+
+/*
+ * Добавление задачи в список
+ */
+void RTOS_SetTask (void (*taskFunc)(void), uint32_t taskDelay, uint32_t taskPeriod) {
+   int i;
+
+   if (!taskFunc) {
+    return;
+   }
+
+   // поиск задачи в текущем списке
+   for(i = 0; i < arrayTail; i++) {
+      // если нашли, то обновляем переменные
+      if (TaskArray[i].pFunc == taskFunc) {
+         __disable_irq();
+
+         TaskArray[i].delay  = taskDelay;
+         TaskArray[i].period = taskPeriod;
+         TaskArray[i].run    = 0;
+
+         __enable_irq();
+         // обновив, выходим
+         return;
+      }
+   }
+
+   // если такой задачи в списке нет
+   if (arrayTail < MAX_TASKS) {
+      // и есть место, то добавляем
+      __disable_irq();
+
+      TaskArray[arrayTail].pFunc  = taskFunc;
+      TaskArray[arrayTail].delay  = taskDelay;
+      TaskArray[arrayTail].period = taskPeriod;
+      TaskArray[arrayTail].run    = 0;
+
+      // увеличиваем "хвост"
+      arrayTail++;
+      __enable_irq();
+   } else {
+     //!!! no left space for new task :-(
+     while (1);
+   }
+}
+
+/*
+ * Удаление задачи из списка
+ */
+inline void RTOS_DeleteTask (void (*taskFunc)(void)) {
+   int i;
+
+   // проходим по списку задач
+   for (i=0; i<arrayTail; i++) {
+      // если задача в списке найдена
+      if (TaskArray[i].pFunc == taskFunc) {
+         __disable_irq();
+         // переносим последнюю задачу
+         if (i != (arrayTail - 1)) {
+            // на место удаляемой
+            TaskArray[i] = TaskArray[arrayTail - 1];
+         }
+         // уменьшаем указатель "хвоста"
+         arrayTail--;
+         __enable_irq();
+         return;
+      }
+   }
+}
+
+/*
+ * Диспетчер РТОС, вызывается в main
+ */
+void RTOS_DispatchTask(void) {
+   int i;
+   void (*function) (void);
+   // проходим по списку задач
+   for (i=0; i<arrayTail; i++) {
+      // если флаг на выполнение взведен,
+      if (TaskArray[i].run != 0) {
+        // запоминаем задачу, т.к. во время выполнения может измениться индекс
+        function = TaskArray[i].pFunc;
+        if (TaskArray[i].period == 0) {
+          // если период равен 0, удаляем задачу из списка,
+          RTOS_DeleteTask(TaskArray[i].pFunc);
+        } else {
+          // иначе снимаем флаг запуска
+          TaskArray[i].run = 0;
+          // если задача не изменила задержку
+          if (!TaskArray[i].delay) {
+            // задаем ее
+            TaskArray[i].delay = TaskArray[i].period-1;
+            // задача для себя может сделать паузу
+          }
+        }
+        // выполняем задачу
+        (*function)();
+      }
+   }
+}
+
+/**
+  * @brief  Inserts a delay time.
+  * @param  nTime: specifies the delay time length, in milliseconds.
+  * @retval None
+  */
+void tdelay_ms(uint32_t msek) {
+
+  TDelay = msek;
+
+  do {
+    if (TDelay > 1) {
+      /* что-бы зря не терять время -- крутим диспетчер */
+      RTOS_DispatchTask();
+    }
+    /* делать нехрен -- спим, ждём прерывание */
+    __WFI();
+  } while (TDelay != 0);
+
+}
+
+/******************************************************************************************
+ * Таймерная служба РТОС и tdelay (прерывание аппаратного таймера)
+ */
+#pragma GCC optimize ("O3")
+/**
+  * @brief  This function handles SysTick Handler.
+  * @param  None
+  * @retval None
+  */
+void SysTick_Handler(void) {
+
+  /* RTOS_Timer */
+  int i;
+  // проходим по списку задач
+  for (i=0; i<arrayTail; i++) {
+    // если время до выполнения истекло
+    if (TaskArray[i].delay == 0) {
+      // взводим флаг запуска,
+      TaskArray[i].run = 1;
+    } else {
+      // иначе уменьшаем время
+      TaskArray[i].delay--;
+    }
+  }
+
+  /* TDelay_Timer -- уменьшим счётчик */
+  if (TDelay != 0) {
+    TDelay --;
+  }
+}

+ 2 - 0
Src/stm32g0xx_it.c

@@ -120,6 +120,7 @@ void PendSV_Handler(void)
   /* USER CODE END PendSV_IRQn 1 */
 }
 
+#ifdef DONT_USE_SHED
 /**
   * @brief This function handles System tick timer.
   */
@@ -133,6 +134,7 @@ void SysTick_Handler(void)
 
   /* USER CODE END SysTick_IRQn 1 */
 }
+#endif /* DONT_USE_SHED */
 
 /******************************************************************************/
 /* STM32G0xx Peripheral Interrupt Handlers                                    */