Browse Source

made AXI DMA controller access thread-safe

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@8665 8c9fc860-2736-0410-a75d-ab315db34111
eth.morozova 6 years ago
parent
commit
58cb8c37a3
2 changed files with 130 additions and 124 deletions
  1. 124 118
      source/AcAxiDma.Mod
  2. 6 6
      source/Zynq.DisplayLinear.Mod

+ 124 - 118
source/AcAxiDma.Mod

@@ -1,13 +1,13 @@
-(** 
+(**
 	AUTHOR: Alexey Morozov, HighDim GmbH, 2013-2018
 	PURPOSE: ActiveCells AXI DMA component driver
 *)
-module AcAxiDma;
+MODULE AcAxiDma;
 
-import
+IMPORT
 	Channels;
 
-const
+CONST
 	CmdSetAddr = 1*2;
 	CmdSetCount = 2*2;
 	CmdSetBurstLen = 3*2;
@@ -16,117 +16,123 @@ const
 	CmdGetCount = 6*2;
 	CmdGetPendingFlag = 7*2;
 
-type
-
-	Address = longint;
-
-	Controller* = record
-		cfgCmd-: port out;
-		cfgData-: port out;
-		status-: port in;
-
-		dataSize-: longint; (** size of one data element in bytes *)
-		addr-: Address;
-		count-: Address;
-		maxBurstLen-: longint;
-		burstLen-: longint;
-		wrap-: boolean;
-
-		transferPending: boolean;
-	end;
-	
-	ReadController* = record(Controller)
-	end;
-	
-	WriteController* = record(Controller)
-	end;
-
-	procedure InitController*(var ctl: Controller; cfgCmd, cfgData: port out; status: port in; dataSize, maxBurstLen: longint);
-	begin
-		ctl.cfgCmd := cfgCmd;
-		ctl.cfgData := cfgData;
-		ctl.status := status;
-		ctl.dataSize := dataSize;
-		ctl.maxBurstLen := maxBurstLen;
-		
-		Stop(ctl);
-		SetCount(ctl,0);
-		SetBurstLen(ctl,maxBurstLen);
-		SetWrap(ctl,false);
-	end InitController;
-
-	procedure SetAddr*(var ctl: Controller; addr: Address);
-	begin
-		ctl.cfgCmd << CmdSetAddr;
-		ctl.cfgData << addr;
-		ctl.addr := addr;
-	end SetAddr;
-
-	procedure SetCount*(var ctl: Controller; count: Address);
-	begin
-		ctl.cfgCmd << CmdSetCount;
-		ctl.cfgData << count;
-		ctl.count := count;
-	end SetCount;
-
-	procedure SetBurstLen*(var ctl: Controller; burstLen: longint);
-	var d: longint;
-	begin
-		d := (burstLen-1) + lsh(burstLen*ctl.dataSize,4);
-		ctl.cfgCmd << CmdSetBurstLen;
-		ctl.cfgData << d;
-		ctl.burstLen := burstLen;
-	end SetBurstLen;
-
-	procedure SetWrap*(var ctl: Controller; wrap: boolean);
-	begin
-		ctl.cfgCmd << CmdSetWrapFlag;
-		if wrap then ctl.cfgData << 1; else ctl.cfgData << 0; end;
-		ctl.wrap := wrap;
-	end SetWrap;
-
-	procedure Start*(var ctl: Controller);
-	begin
-		ctl.cfgCmd << 1;
-		ctl.cfgData << 0;
-		ctl.transferPending := true;
-	end Start;
-
-	procedure Stop*(var ctl: Controller);
-	begin
-		ctl.cfgCmd << 0;
-		ctl.cfgData << 0;
-		ctl.transferPending := false;
-	end Stop;
-
-	procedure GetCurrentAddr*(var ctl: Controller): Address;
-	var addr: Address;
-	begin
-		ctl.cfgCmd << CmdGetAddr;
-		ctl.cfgData << 0;
-		addr << ctl.status;
-		return addr;
-	end GetCurrentAddr;
-
-	procedure GetCurrentCount*(var ctl: Controller): Address;
-	var count: Address;
-	begin
-		ctl.cfgCmd << CmdGetCount;
-		ctl.cfgData << 0;
-		count << ctl.status;
-		return count;
-	end GetCurrentCount;
-
-	procedure TransferPending*(var ctl: Controller): boolean;
-	var d: longint;
-	begin
-		if ctl.transferPending then
-			ctl.cfgCmd << CmdGetPendingFlag;
-			ctl.cfgData << 0;
-			d << ctl.status;
-			ctl.transferPending := d mod 2 = 1;
-		end;
-		return ctl.transferPending;
-	end TransferPending;
-
-end AcAxiDma.
+TYPE
+
+	Address* = LONGINT;
+	Size* = LONGINT;
+
+	(**
+		ActiveCells AXI DMA component controller
+	*)
+	Controller* = OBJECT
+	VAR
+		cfgCmd: PORT OUT;
+		cfgData: PORT OUT;
+		status: PORT IN;
+
+		dataSize-: WORD; (** size of one data element in bytes *)
+		addr-: Address; (** DMA transfer starting address *)
+		count-: Size; (** DMA transfer size in number of elements *)
+		maxBurstLen-: WORD; (** maximal burst length in number of elements *)
+		burstLen-: WORD; (** current burst length in number of elements *)
+		wrap-: BOOLEAN; (** TRUE in case of a recurrent transfer *)
+
+		PROCEDURE &InitController*(cfgCmdOut, cfgDataOut: PORT OUT; statusInp: PORT IN; dataSize, maxBurstLen: WORD);
+		BEGIN
+			ASSERT(dataSize > 0);
+			ASSERT(maxBurstLen > 0);
+
+			cfgCmd := cfgCmdOut;
+			cfgData := cfgDataOut;
+			status := statusInp;
+			SELF.dataSize := dataSize;
+			SELF.maxBurstLen := maxBurstLen;
+
+			Stop;
+			SetCount(0);
+			SetBurstLen(maxBurstLen);
+			SetWrap(FALSE);
+		END InitController;
+
+		PROCEDURE SetAddr*(startAddr: Address);
+		BEGIN{EXCLUSIVE}
+			cfgCmd << CmdSetAddr;
+			cfgData << startAddr;
+			addr := startAddr;
+		END SetAddr;
+
+		PROCEDURE SetCount*(transferCount: Size);
+		BEGIN{EXCLUSIVE}
+			cfgCmd << CmdSetCount;
+			cfgData << transferCount;
+			count := transferCount;
+		END SetCount;
+
+		PROCEDURE SetBurstLen*(len: WORD);
+		VAR d: LONGINT;
+		BEGIN{EXCLUSIVE}
+			d := (burstLen-1) + LSH(LONGINT(burstLen)*dataSize,4);
+			cfgCmd << CmdSetBurstLen;
+			cfgData << d;
+			burstLen := len;
+		END SetBurstLen;
+
+		PROCEDURE SetWrap*(enableWrap: BOOLEAN);
+		BEGIN{EXCLUSIVE}
+			cfgCmd << CmdSetWrapFlag;
+			IF enableWrap THEN cfgData << 1; ELSE cfgData << 0; END;
+			wrap := enableWrap;
+		END SetWrap;
+
+		PROCEDURE Start*();
+		BEGIN{EXCLUSIVE}
+			IF SELF IS WriteController THEN
+				cfgCmd << 0;
+			ELSE
+				cfgCmd << 1;
+			END;
+			cfgData << 1;
+		END Start;
+
+		PROCEDURE Stop*();
+		BEGIN{EXCLUSIVE}
+			cfgCmd << 0;
+			cfgData << 0;
+		END Stop;
+
+		PROCEDURE GetCurrentAddr*(): Address;
+		VAR addr: Address;
+		BEGIN{EXCLUSIVE}
+			cfgCmd << CmdGetAddr;
+			cfgData << 0;
+			addr << status;
+			RETURN addr;
+		END GetCurrentAddr;
+
+		PROCEDURE GetCurrentCount*(): Address;
+		VAR count: Address;
+		BEGIN{EXCLUSIVE}
+			cfgCmd << CmdGetCount;
+			cfgData << 0;
+			count << status;
+			RETURN count;
+		END GetCurrentCount;
+
+		PROCEDURE IsTransferPending*(): BOOLEAN;
+		VAR d: LONGINT;
+		BEGIN{EXCLUSIVE}
+			cfgCmd << CmdGetPendingFlag;
+			cfgData << 0;
+			d << status;
+			RETURN (d MOD 2) = 1;
+		END IsTransferPending;
+
+	END Controller;
+
+	ReadController* = OBJECT(Controller)
+	END ReadController;
+
+	WriteController* = OBJECT(Controller)
+	END WriteController;
+
+END AcAxiDma.

+ 6 - 6
source/Zynq.DisplayLinear.Mod

@@ -256,19 +256,19 @@ VAR
 		Machine.Fill32(bufAddr,Width*Height*4,DefaultColor); (* fill the framebuffer with the default color *)
 		Machine.FlushDCacheRange(bufAddr,Width*Height*4);
 
-		AcAxiDma.InitController(rdma,rCfgCmd,rCfgData,rStatus,4,16);
-		AcAxiDma.SetBurstLen(rdma,DmaBurstLen);
+		NEW(rdma,rCfgCmd,rCfgData,rStatus,4,16);
+		rdma.SetBurstLen(DmaBurstLen);
 
 		(* configure read DMA transfer *)
-		AcAxiDma.SetAddr(rdma,bufAddr);
-		AcAxiDma.SetCount(rdma,Width*Height);
-		AcAxiDma.SetWrap(rdma,TRUE); (* recurring transfer *)
+		rdma.SetAddr(bufAddr);
+		rdma.SetCount(Width*Height);
+		rdma.SetWrap(TRUE); (* recurring transfer *)
 		
 		(*
 			Enable video output
 		*)
 		Video.Enable(vout,TRUE);
-		AcAxiDma.Start(rdma);
+		rdma.Start;
 		
 		(*
 			Install the display