Переглянути джерело

Merge branch 'new/passive-waiting/14'

DricomDragon 5 роки тому
батько
коміт
af2cbe0f17

+ 8 - 8
prog/sources/lcd.cpp

@@ -158,31 +158,31 @@ MACRO_INIT_ROUTINE (setupLCD) ;
 // UTILITY ROUTINES — USER MODE
 
 static void write8bitCommand (USER_MODE_ const uint8_t inCommand) {
-	busyWaitDuring (MODE_ 1) ;
+	waitDuring (MODE_ 1) ;
 	driveLowRS () ;
 	programLcd4BitDataBusOutput ((uint8_t) (inCommand >> 4)) ;
 	driveHighE () ;
-	busyWaitDuring (MODE_ 1) ;
+	waitDuring (MODE_ 1) ;
 	driveLowE () ;
-	busyWaitDuring (MODE_ 1) ;
+	waitDuring (MODE_ 1) ;
 	programLcd4BitDataBusOutput (inCommand) ;
 	driveHighE () ;
-	busyWaitDuring (MODE_ 1) ;
+	waitDuring (MODE_ 1) ;
 	driveLowE () ;
 }
 
 
 static void writeData (USER_MODE_ const uint8_t inData) {
-	busyWaitDuring (MODE_ 1) ;
+	waitDuring (MODE_ 1) ;
 	driveHighRS () ;
 	programLcd4BitDataBusOutput (inData >> 4) ;
 	driveHighE () ;
-	busyWaitDuring (MODE_ 1) ;
+	waitDuring (MODE_ 1) ;
 	driveLowE () ;
-	busyWaitDuring (MODE_ 1) ;
+	waitDuring (MODE_ 1) ;
 	programLcd4BitDataBusOutput (inData) ;
 	driveHighE () ;
-	busyWaitDuring (MODE_ 1) ;
+	waitDuring (MODE_ 1) ;
 	driveLowE () ;
 }
 

+ 10 - 8
prog/sources/time.cpp

@@ -92,13 +92,13 @@ uint32_t systick (ANY_MODE) {
 
 // SYSTICK interrupt service routine
 
-void systickInterruptServiceRoutine (SECTION_MODE) {
+void systickInterruptServiceRoutine (IRQ_MODE) {
 	const uint32_t newUptime = gUptime + 1 ;
 	gUptime = newUptime ;
 	// Run real.time.interrupt.routine.array section routines
-	extern void (* __real_time_interrupt_routine_array_start) (SECTION_MODE_ const uint32_t inUptime) ;
-	extern void (* __real_time_interrupt_routine_array_end) (SECTION_MODE_ const uint32_t inUptime) ;
-	void (* * ptr) (SECTION_MODE_ const uint32_t) = & __real_time_interrupt_routine_array_start ;
+	extern void (* __real_time_interrupt_routine_array_start) (IRQ_MODE_ const uint32_t inUptime) ;
+	extern void (* __real_time_interrupt_routine_array_end) (IRQ_MODE_ const uint32_t inUptime) ;
+	void (* * ptr) (IRQ_MODE_ const uint32_t) = & __real_time_interrupt_routine_array_start ;
 	while (ptr != & __real_time_interrupt_routine_array_end) {
 		(* ptr) (MODE_ newUptime) ;
 		ptr ++ ;
@@ -107,13 +107,15 @@ void systickInterruptServiceRoutine (SECTION_MODE) {
 
 // busyWaitDuring, busyWaitUntil — USER MODE
 
-void busyWaitDuring (USER_MODE_ const uint32_t inDelayMS) {
-	busyWaitUntil (MODE_ gUptime + inDelayMS) ;
+void waitDuring (USER_MODE_ const uint32_t inDelayMS) {
+	waitUntil (MODE_ gUptime + inDelayMS) ;
 }
 
 
-void busyWaitUntil (USER_MODE_ const uint32_t inDeadlineMS) {
-	while (inDeadlineMS > gUptime) {}
+void service_waitUntil (KERNEL_MODE_ const uint32_t inDeadlineMS) {
+	if (inDeadlineMS > gUptime) {
+		kernel_blockOnDeadline(MODE_ inDeadlineMS);
+	}
 }
 
 

+ 10 - 5
prog/sources/time.h

@@ -14,9 +14,14 @@ void busyWaitDuring_faultMode (FAULT_MODE_ const uint32_t inDelayMS) ;
 
 // USER MODE
 
-void busyWaitDuring (USER_MODE_ const uint32_t inDelayMS) ;
+void waitDuring (USER_MODE_ const uint32_t inDelayMS) ;
 
-void busyWaitUntil (USER_MODE_ const uint32_t inDeadlineMS) ;
+void waitUntil (USER_MODE_ const uint32_t inDeadlineMS) asm ("wait.until");
+
+// SERVICE
+
+void service_waitUntil (KERNEL_MODE_ const uint32_t inDeadLineMS) asm ("service.wait.until");
+//$service wait.until
 
 // ANY MODE
 
@@ -34,13 +39,13 @@ uint64_t section_micros (SECTION_MODE) asm ("section.time.micros") ;
 
 // INTERRUPT ROUTINE
 
-//$interrupt-section SysTick
-void systickInterruptServiceRoutine (SECTION_MODE) asm ("interrupt.section.SysTick") ;
+//$interrupt-service SysTick
+void systickInterruptServiceRoutine (IRQ_MODE) asm ("interrupt.service.SysTick") ;
 
 // Insert routine address into 'real.time.interrupt.routine.array' section
 
 #define MACRO_REAL_TIME_ISR(ROUTINE) \
-	static void (* UNIQUE_IDENTIFIER) (SECTION_MODE_ const uint32_t inUptime) \
+	static void (* UNIQUE_IDENTIFIER) (IRQ_MODE_ const uint32_t inUptime) \
 __attribute__ ((section ("real.time.interrupt.routine.array"))) \
 __attribute__ ((unused)) \
 __attribute__ ((used)) = ROUTINE ;

+ 15 - 6
prog/sources/user-tasks.cpp

@@ -3,22 +3,31 @@
 static uint64_t gStack1 [64] ;
 
 static void task1 (USER_MODE) {
+	digitalWrite(L0_LED, true);
 	for (unsigned int i(0); i < 20; i++) {
-		digitalToggle(L0_LED);
-		printChar (MODE_ '>') ;
-		busyWaitDuring(MODE_ 500);
+		printChar (MODE_ '1') ;
+
+		digitalWrite(L0_LED, false);
+		waitDuring(MODE_ 500);
+		digitalWrite(L0_LED, true);
 	}
+
+	digitalWrite(L0_LED, false);
 }
 
 
 static uint64_t gStack2 [64] ;
 
 static void task2 (USER_MODE) {
+	digitalWrite(L1_LED, true);
 	for (unsigned int i(0); i < 20; i++) {
-		digitalToggle(L1_LED);
-		printChar (MODE_ '<') ;
-		busyWaitDuring(MODE_ 400);
+		printChar (MODE_ '2') ;
+
+		digitalWrite(L1_LED, false);
+		waitDuring(MODE_ 400);
+		digitalWrite(L1_LED, true);
 	}
+	digitalWrite(L1_LED, false);
 }
 
 

+ 25 - 0
prog/sources/xtr.cpp

@@ -121,6 +121,9 @@ typedef struct TaskControlBlock {
 	// Context buffer
 	TaskContext mTaskContext ; // SHOULD BE THE FIRST FIELD
 
+	// Store reactivation deadline
+	uint32_t mDeadline ;
+
 	// Task index
 	uint8_t mTaskIndex ;
 } TaskControlBlock ;
@@ -148,6 +151,8 @@ TaskControlBlock * gRunningTaskControlBlockPtr asm ("var.running.task.control.bl
 
 static TaskList gReadyTaskList ;
 
+static TaskList gDeadlineWaitingTaskList ;
+
 
 static void kernel_makeTaskReady (IRQ_MODE_ TaskControlBlock * inTaskPtr) {
 	XTR_ASSERT_NON_NULL_POINTER (inTaskPtr) ;
@@ -200,7 +205,27 @@ static void kernel_makeNoTaskRunning(KERNEL_MODE) {
 	gRunningTaskControlBlockPtr = nullptr; // No running task
 }
 
+void kernel_blockOnDeadline (KERNEL_MODE_ const uint32_t inDeadline) {
+	XTR_ASSERT_NON_NULL_POINTER (gRunningTaskControlBlockPtr) ;
+	gRunningTaskControlBlockPtr->mDeadline = inDeadline ;
+	gDeadlineWaitingTaskList.enterTask (MODE_ gRunningTaskControlBlockPtr) ;
+	kernel_makeNoTaskRunning (MODE) ;
+}
+
 // Task termination
 void service_taskSelfTerminates(KERNEL_MODE) {
 	kernel_makeNoTaskRunning(MODE);
 }
+
+static void irq_makeTasksReadyFromCurrentDate (IRQ_MODE_ const uint32_t inCurrentDate) {
+	TaskList::Iterator iterator (MODE_ gDeadlineWaitingTaskList) ;
+	TaskControlBlock * task ;
+	while ((task = iterator.nextTask (MODE))) {
+		if (inCurrentDate >= task->mDeadline) {
+			gDeadlineWaitingTaskList.removeTask (MODE_ task) ;
+			kernel_makeTaskReady (MODE_ task) ;
+		}
+	}
+}
+
+MACRO_REAL_TIME_ISR (irq_makeTasksReadyFromCurrentDate) ;

+ 6 - 0
prog/sources/xtr.h

@@ -25,3 +25,9 @@ uint8_t indexForDescriptorTask (const TaskControlBlock * inTaskPtr) ; // should
 void taskSelfTerminates(USER_MODE) asm ("task.self.terminates");
 void service_taskSelfTerminates(KERNEL_MODE) asm ("service.task.self.terminates");
 //$service task.self.terminates
+
+// Task suspension
+void kernel_blockOnDeadline (KERNEL_MODE_ const uint32_t inDeadline);
+
+// Task reactivation
+void irq_makeTasksReadyFromCurrentDate (IRQ_MODE);