|
@@ -0,0 +1,225 @@
|
|
|
|
+#include "rtos.h"
|
|
|
|
+#include "stm8l15x_it.h"
|
|
|
|
+
|
|
|
|
+/* Private define ------------------------------------------------------------*/
|
|
|
|
+#define TIM4_PERIOD (uint8_t)124
|
|
|
|
+
|
|
|
|
+/******************************************************************************************
|
|
|
|
+ * Ïåðåìåííûå ìîäóëÿ
|
|
|
|
+ */
|
|
|
|
+static __IO task TaskArray[MAX_TASKS]; // î÷åðåäü çàäà÷
|
|
|
|
+static __IO uint8_t arrayTail; // "õâîñò" î÷åðåäè
|
|
|
|
+static __IO uint16_t TimingDelay;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/******************************************************************************************
|
|
|
|
+ * Èíèöèàëèçàöèÿ ÐÒÎÑ, âðåìÿ òèêà - 1 ìñ
|
|
|
|
+ */
|
|
|
|
+inline void RTOS_Init()
|
|
|
|
+{
|
|
|
|
+ /* TIM4 configuration:
|
|
|
|
+ - TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter
|
|
|
|
+ clock used is 16 MHz / 128 = 125 000 Hz
|
|
|
|
+ - With 125 000 Hz we can generate time base:
|
|
|
|
+ max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms
|
|
|
|
+ min time base is 0.016 ms if TIM4_PERIOD = 1 --> ( 1 + 1) / 125000 = 0.016 ms
|
|
|
|
+ - In this example we need to generate a time base equal to 1 ms
|
|
|
|
+ so TIM4_PERIOD = (0.001 * 125000 - 1) = 124 */
|
|
|
|
+
|
|
|
|
+ /* Time base configuration */
|
|
|
|
+ TIM4_TimeBaseInit(TIM4_Prescaler_128, TIM4_PERIOD);
|
|
|
|
+ /* Clear TIM4 update flag */
|
|
|
|
+ TIM4_ClearFlag(TIM4_FLAG_Update);
|
|
|
|
+ /* Enable update interrupt */
|
|
|
|
+ TIM4_ITConfig(TIM4_IT_Update, ENABLE);
|
|
|
|
+ /* enable interrupts */
|
|
|
|
+ enableInterrupts();
|
|
|
|
+
|
|
|
|
+ /* Enable TIM4 */
|
|
|
|
+ TIM4_Cmd(ENABLE);
|
|
|
|
+
|
|
|
|
+ /* "õâîñò" â 0 */
|
|
|
|
+ arrayTail = 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/******************************************************************************************
|
|
|
|
+ * Äîáàâëåíèå çàäà÷è â ñïèñîê
|
|
|
|
+ */
|
|
|
|
+void RTOS_SetTask (void (*taskFunc)(void), uint16_t taskDelay, uint16_t taskPeriod)
|
|
|
|
+{
|
|
|
|
+ uint8_t i;
|
|
|
|
+
|
|
|
|
+ if(!taskFunc) return;
|
|
|
|
+
|
|
|
|
+ for(i = 0; i < arrayTail; i++) // ïîèñê çàäà÷è â òåêóùåì ñïèñêå
|
|
|
|
+ {
|
|
|
|
+ if(TaskArray[i].pFunc == taskFunc) // åñëè íàøëè, òî îáíîâëÿåì ïåðåìåííûå
|
|
|
|
+ {
|
|
|
|
+ DISABLE_INTERRUPT;
|
|
|
|
+
|
|
|
|
+ TaskArray[i].delay = taskDelay;
|
|
|
|
+ TaskArray[i].period = taskPeriod;
|
|
|
|
+ TaskArray[i].run = 0;
|
|
|
|
+
|
|
|
|
+// RESTORE_INTERRUPT;
|
|
|
|
+ ENABLE_INTERRUPT;
|
|
|
|
+ return; // îáíîâèâ, âûõîäèì
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (arrayTail < MAX_TASKS) // åñëè òàêîé çàäà÷è â ñïèñêå íåò
|
|
|
|
+ { // è åñòü ìåñòî,òî äîáàâëÿåì
|
|
|
|
+ DISABLE_INTERRUPT;
|
|
|
|
+
|
|
|
|
+ TaskArray[arrayTail].pFunc = taskFunc;
|
|
|
|
+ TaskArray[arrayTail].delay = taskDelay;
|
|
|
|
+ TaskArray[arrayTail].period = taskPeriod;
|
|
|
|
+ TaskArray[arrayTail].run = 0;
|
|
|
|
+
|
|
|
|
+ arrayTail++; // óâåëè÷èâàåì "õâîñò"
|
|
|
|
+// RESTORE_INTERRUPT;
|
|
|
|
+ ENABLE_INTERRUPT;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/******************************************************************************************
|
|
|
|
+ * Óäàëåíèå çàäà÷è èç ñïèñêà
|
|
|
|
+ */
|
|
|
|
+void RTOS_DeleteTask (void (*taskFunc)(void))
|
|
|
|
+{
|
|
|
|
+ uint8_t i;
|
|
|
|
+
|
|
|
|
+ for (i=0; i<arrayTail; i++) // ïðîõîäèì ïî ñïèñêó çàäà÷
|
|
|
|
+ {
|
|
|
|
+ if(TaskArray[i].pFunc == taskFunc) // åñëè çàäà÷à â ñïèñêå íàéäåíà
|
|
|
|
+ {
|
|
|
|
+
|
|
|
|
+ DISABLE_INTERRUPT;
|
|
|
|
+ if(i != (arrayTail - 1)) // ïåðåíîñèì ïîñëåäíþþ çàäà÷ó
|
|
|
|
+ { // íà ìåñòî óäàëÿåìîé
|
|
|
|
+ TaskArray[i] = TaskArray[arrayTail - 1];
|
|
|
|
+ }
|
|
|
|
+ arrayTail--; // óìåíüøàåì óêàçàòåëü "õâîñòà"
|
|
|
|
+// RESTORE_INTERRUPT;
|
|
|
|
+ ENABLE_INTERRUPT;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/******************************************************************************************
|
|
|
|
+ * Äèñïåò÷åð ÐÒÎÑ, âûçûâàåòñÿ â main
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+void RTOS_DispatchTask(void)
|
|
|
|
+{
|
|
|
|
+ uint8_t i;
|
|
|
|
+ void (*function) (void);
|
|
|
|
+
|
|
|
|
+ for (i=0; i<arrayTail; i++) // ïðîõîäèì ïî ñïèñêó çàäà÷
|
|
|
|
+ {
|
|
|
|
+ if (TaskArray[i].run == 1) // åñëè ôëàã íà âûïîëíåíèå âçâåäåí,
|
|
|
|
+ { // çàïîìèíàåì çàäà÷ó, ò.ê. âî
|
|
|
|
+ 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)(); // âûïîëíÿåì çàäà÷ó
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/******************************************************************************************
|
|
|
|
+ * Òàéìåðíàÿ ñëóæáà ÐÒÎÑ (ïðåðûâàíèå àïïàðàòíîãî òàéìåðà)
|
|
|
|
+ */
|
|
|
|
+/*
|
|
|
|
+static void RTOS_Timer(void)
|
|
|
|
+{
|
|
|
|
+ uint8_t i;
|
|
|
|
+
|
|
|
|
+ for (i=0; i<arrayTail; i++) // ïðîõîäèì ïî ñïèñêó çàäà÷
|
|
|
|
+ {
|
|
|
|
+ if (TaskArray[i].delay == 0) { // åñëè âðåìÿ äî âûïîëíåíèÿ èñòåêëî
|
|
|
|
+ TaskArray[i].run = 1; // âçâîäèì ôëàã çàïóñêà,
|
|
|
|
+ } else {
|
|
|
|
+ TaskArray[i].delay--; // èíà÷å óìåíüøàåì âðåìÿ
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+*/
|
|
|
|
+/**
|
|
|
|
+ * @brief Inserts a delay time.
|
|
|
|
+ * @param nTime: specifies the delay time length, in milliseconds.
|
|
|
|
+ * @retval None
|
|
|
|
+ */
|
|
|
|
+void Delay(__IO uint16_t nTime)
|
|
|
|
+{
|
|
|
|
+ TimingDelay = nTime;
|
|
|
|
+ while (TimingDelay != 0) {
|
|
|
|
+ // çäåñü ìîæíî ñïàòü è æäàòü ïðåðûâàíèå
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief Decrements the TimingDelay variable.
|
|
|
|
+ * @note This function should be called in the
|
|
|
|
+ * TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler in the stm8l15x_it.c file.
|
|
|
|
+ *
|
|
|
|
+ * // INTERRUPT_HANDLER(TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler, 19)
|
|
|
|
+ * // {
|
|
|
|
+ * // TimingDelay_Decrement();
|
|
|
|
+ * // TIM2_ClearITPendingBit(TIM2_IT_Update);
|
|
|
|
+ *
|
|
|
|
+ * // }
|
|
|
|
+ * @param None
|
|
|
|
+ * @retval None
|
|
|
|
+ */
|
|
|
|
+/*
|
|
|
|
+static void TimingDelay_Decrement(void)
|
|
|
|
+{
|
|
|
|
+ if (TimingDelay != 0x00)
|
|
|
|
+ {
|
|
|
|
+ TimingDelay--;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+*/
|
|
|
|
+/**
|
|
|
|
+ * @brief TIM4 Update/Overflow/Trigger Interrupt routine.
|
|
|
|
+ * @param None
|
|
|
|
+ * @retval None
|
|
|
|
+ */
|
|
|
|
+INTERRUPT_HANDLER(TIM4_UPD_OVF_TRG_IRQHandler,25)
|
|
|
|
+{
|
|
|
|
+ /* In order to detect unexpected events during development,
|
|
|
|
+ it is recommended to set a breakpoint on the following instruction.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ /* Cleat Interrupt Pending bit */
|
|
|
|
+// TIM4_ClearITPendingBit(TIM4_IT_Update);
|
|
|
|
+ TIM4->SR1 = (uint8_t)(~(uint8_t)TIM4_IT_Update);
|
|
|
|
+
|
|
|
|
+// TimingDelay_Decrement();
|
|
|
|
+ if (TimingDelay > 0) {
|
|
|
|
+ TimingDelay --;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+// RTOS_Timer();
|
|
|
|
+ uint8_t i;
|
|
|
|
+
|
|
|
|
+ for (i=0; i<arrayTail; i++) { // ïðîõîäèì ïî ñïèñêó çàäà÷
|
|
|
|
+ if (TaskArray[i].delay == 0) { // åñëè âðåìÿ äî âûïîëíåíèÿ èñòåêëî
|
|
|
|
+ TaskArray[i].run = 1; // âçâîäèì ôëàã çàïóñêà,
|
|
|
|
+ } else {
|
|
|
|
+ TaskArray[i].delay--; // èíà÷å óìåíüøàåì âðåìÿ
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|