Browse Source

Merge branch 'new/synchronisation/15'

DricomDragon 5 years ago
parent
commit
4407837fea
5 changed files with 77 additions and 3 deletions
  1. 23 0
      prog/sources/Semaphore.cpp
  2. 20 0
      prog/sources/Semaphore.h
  3. 9 1
      prog/sources/lcd.cpp
  4. 17 1
      prog/sources/xtr.cpp
  5. 8 1
      prog/sources/xtr.h

+ 23 - 0
prog/sources/Semaphore.cpp

@@ -0,0 +1,23 @@
+#include "all-headers.h"
+
+Semaphore::Semaphore (const uint32_t inInitialValue) :
+mWaitingTaskList(), mValue (inInitialValue) {}
+
+void Semaphore::sys_P (KERNEL_MODE) {
+	if (mValue == 0) {
+		kernel_blockRunningTaskInList(MODE_ mWaitingTaskList);
+	}
+	else {
+		mValue --;
+	}
+}
+
+void Semaphore::sys_V (IRQ_MODE) {
+	TaskControlBlock * taskToRelease( mWaitingTaskList.removeFirstTask(MODE) );
+	if (taskToRelease == nullptr) {
+		mValue ++;
+	}
+	else {
+		kernel_makeTaskReady(MODE_ taskToRelease);
+	}
+}

+ 20 - 0
prog/sources/Semaphore.h

@@ -0,0 +1,20 @@
+# include "task-list-32-tasks.h"
+
+class Semaphore {
+	protected: TaskList mWaitingTaskList ;
+	protected: uint32_t mValue ;
+
+	public: Semaphore (const uint32_t inInitialValue) ;
+
+	//$service semaphore.V
+	public: void V (USER_MODE) asm ("semaphore.V") ;
+	public: void sys_V (IRQ_MODE) asm ("service.semaphore.V") ;
+
+	//$service semaphore.P
+	public: void P (USER_MODE) asm ("semaphore.P") ;
+	public: void sys_P (KERNEL_MODE) asm ("service.semaphore.P") ;
+
+	// Disable copy
+	private: Semaphore (const Semaphore &) = delete ;
+	private: Semaphore & operator = (const Semaphore &) = delete ;
+};

+ 9 - 1
prog/sources/lcd.cpp

@@ -27,7 +27,11 @@ static const DigitalPort LCD_RS = DigitalPort::D18 ;
 
 static const DigitalPort LCD_E  = DigitalPort::D17 ;
 
-// UTILITY ROUTINES — ANY MODE                                                                                                  *
+// SEMAPHORE
+
+static Semaphore sem(1);
+
+// UTILITY ROUTINES — ANY MODE
 
 static void driveHighE (void) {
 	digitalWrite (LCD_E, true) ;
@@ -173,6 +177,8 @@ static void write8bitCommand (USER_MODE_ const uint8_t inCommand) {
 
 
 static void writeData (USER_MODE_ const uint8_t inData) {
+	sem.P(MODE);
+
 	waitDuring (MODE_ 1) ;
 	driveHighRS () ;
 	programLcd4BitDataBusOutput (inData >> 4) ;
@@ -184,6 +190,8 @@ static void writeData (USER_MODE_ const uint8_t inData) {
 	driveHighE () ;
 	waitDuring (MODE_ 1) ;
 	driveLowE () ;
+
+	sem.V(MODE);
 }
 
 // PRINT ROUTINES — USER MODE

+ 17 - 1
prog/sources/xtr.cpp

@@ -154,7 +154,7 @@ static TaskList gReadyTaskList ;
 static TaskList gDeadlineWaitingTaskList ;
 
 
-static void kernel_makeTaskReady (IRQ_MODE_ TaskControlBlock * inTaskPtr) {
+void kernel_makeTaskReady (IRQ_MODE_ TaskControlBlock * inTaskPtr) {
 	XTR_ASSERT_NON_NULL_POINTER (inTaskPtr) ;
 	gReadyTaskList.enterTask (MODE_ inTaskPtr) ;
 }
@@ -229,3 +229,19 @@ static void irq_makeTasksReadyFromCurrentDate (IRQ_MODE_ const uint32_t inCurren
 }
 
 MACRO_REAL_TIME_ISR (irq_makeTasksReadyFromCurrentDate) ;
+
+// Synchronisation
+void kernel_blockRunningTaskInList (KERNEL_MODE_ TaskList & ioWaitingList) {
+	XTR_ASSERT_NON_NULL_POINTER (gRunningTaskControlBlockPtr) ;
+	ioWaitingList.enterTask (MODE_ gRunningTaskControlBlockPtr) ;
+	kernel_makeNoTaskRunning (MODE) ;
+}
+
+bool irq_makeTaskReadyFromList (IRQ_MODE_ TaskList & ioWaitingList) {
+	TaskControlBlock * taskPtr = ioWaitingList.removeFirstTask (MODE) ;
+	const bool found = taskPtr != nullptr ;
+	if (found) {
+		kernel_makeTaskReady (MODE_ taskPtr) ;
+	}
+	return found ;
+}

+ 8 - 1
prog/sources/xtr.h

@@ -1,7 +1,7 @@
 #pragma once
 
-
 #include "software-modes.h"
+#include "task-list-32-tasks.h"
 
 // Task routine type
 
@@ -17,6 +17,8 @@ void kernel_createTask (INIT_MODE_
 
 struct TaskControlBlock ;
 
+void kernel_makeTaskReady (IRQ_MODE_ TaskControlBlock * inTaskPtr);
+
 TaskControlBlock * descriptorPointerForTaskIndex (const uint8_t inTaskIndex) ;
 
 uint8_t indexForDescriptorTask (const TaskControlBlock * inTaskPtr) ; // should be not nullptr
@@ -31,3 +33,8 @@ void kernel_blockOnDeadline (KERNEL_MODE_ const uint32_t inDeadline);
 
 // Task reactivation
 void irq_makeTasksReadyFromCurrentDate (IRQ_MODE);
+
+// Synchronization
+void kernel_blockRunningTaskInList (KERNEL_MODE_ TaskList & ioWaitingList);
+
+bool irq_makeTaskReadyFromList (IRQ_MODE_ TaskList & ioWaitingList);