How best to introduce a timed-delay whilst in Supervisor mode

Anything QL Software or Programming Related.
Post Reply
martyn_hill
Aurora
Posts: 924
Joined: Sat Oct 25, 2014 9:53 am

How best to introduce a timed-delay whilst in Supervisor mode

Post by martyn_hill »

Hello gurus!

I am researching how best to re-code a software timing loop within the NET device driver that is currently tied to the CPU clock in such a way as to duplicate the intended timing effect in a reliable way inside an emulator such as QPC, QEmuLator, uQLX etc.

This is part of the on-going QLUB Adapter project, which already off-loads 99% of the timing-sensitive NET driver code to the microcontroller firmware, leaving behind only the (non-timing critical) Access layer code plus a small routine used by the NET driver to repeat the last operation (in dd/nd/nd_rept) without the help of the IOSS Scheduler Loop - the call itself being made by the NET Access layer in a few specific situations - and thus already in Supervisor mode, but with Interrupts still enabled.

On the surface, this code fragment appears to remain the same across all the TK2 NET driver versions, even for QXL and (S)GC, where it can't possibly maintain the intended timing as it was originally designed for on a basic QL. That said, some external patching routine might update the relevant loop constants before the routine gets called on those platforms.

I made an attempt in the ND-Q68 NET driver to rewrite these, but there was able to rely on its 40MHz CPU clock to more or less reproduce the intended timings. Under an emulator however, the clock cycle-timings become even more abstract and it is this that I am trying to correct as I modify the NET driver to integrate fully with the QLUB Adapter.

Here's the (annotated) extract of the routine which is called under the following situations (all in Supervisor mode, Interrupts enabled, without using the IOSS 'retry' mechanism):
a) When an NETO channel is closed - to attempt repeatedly to send the final packet for c.25 seconds before giving-up.
b) When an Nx channel attempts to send or receive the next 'request packet' to the remote FSERVE host.

Code: Select all

nd_rept
	...
	move.w	#2500,d7		try 2500 times in all (about 25 seconds)
	tst.b	nd_dest(a0)		is it send broadcast?
	bne.s	ndr_try 		... no
	lsr.w	#1,d7			check immediately   *** I.e. we start to check the keyboard on each iteration for a BCAST, but only after the first 5secs or so for other NET operations.
*
ndr_try
	jsr	(a2)			do operation  *** the entry address to the required NET routine was passed in a2
	beq.s	ndr_rts 		... done
	blt.s	ndr_tbrk		try again if 'Not Complete' - the usual return from the physical NET code that would normally trigger an IOSS 'retry' later
	move.w	#1499,d0		otherwise wait 7ms  *** This 7ms timing (plus the time that each physical NET operation attempt may take before timing-out) needs re-coding
	dbra	d0,*
ndr_tbrk
	cmp.w	#2000,d7		wait about 5-6 seconds before checking for BRK (unless a BCAST)
	bgt.s	ndr_tend
*
	bsr.s	nd_break		check break   *** a simple call to MT.HDOP/IPCOM to read two rows of the keyboard and return NZ if BRK detected
	bne.s	ndr_abort
ndr_tend
	dbra	d7,ndr_try
ndr_abort
	...
So, in short, we need a different way to measure time if we are to duplicate this 'manual NET operation retry' over c25 secs - or until the op completes - plus the (less important) delay before testing the keyboard for BRK, but without recourse to the (unknown) CPU cycle timings when run under an emulator.

Any ideas?


User avatar
tofro
Font of All Knowledge
Posts: 2699
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: How best to introduce a timed-delay whilst in Supervisor mode

Post by tofro »

Martyn,

such long delays >1s should actually be easy.

May I remind you the QL has an RTC ticking away in 1s intervals at $18000.L?

This should be emulated even by emulators (sic).


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Martin_Head
Aurora
Posts: 851
Joined: Tue Dec 17, 2013 1:17 pm

Re: How best to introduce a timed-delay whilst in Supervisor mode

Post by Martin_Head »

tofro wrote:May I remind you the QL has an RTC ticking away in 1s intervals at $18000.L?

This should be emulated even by emulators (sic).
I don't think that's implemented in QPC2. Try PRINT PEEK_L($18000) you just get 0 back


martyn_hill
Aurora
Posts: 924
Joined: Sat Oct 25, 2014 9:53 am

Re: How best to introduce a timed-delay whilst in Supervisor mode

Post by martyn_hill »

Thanks Martin and Tobias!

Yes, for 1s granularity, the emulation of the IPC timer (where available) would suffice for the overall 25s timeout.

However, the 7ms 'pause' between manual attempts to re-try the last NET operation remains an open requirement. In fact, as well as the 7ms pause, the actual call to the physical layer adds between 0 and 3ms (send) and 0 and 20ms (receive) between each (unsuccessful) iteration - for what its worth.

These delay timings are far from critical - in a classic QL, only the Interrupt handler is still running once nd_rept is invoked (no task-switch or Scheduler calls occur as we remain in Supervisor mode throughout), so its only the responsiveness to BRK that a user is likely to notice.

In the design of the QLUB Adapter, it is the asynchronous 'Message-Queue' Scheduler task that brokers the messages between the OS/client and the microcontroller itself and any calls effectively return immediately if the response from the microcotnroller has yet to be received, which works well when the IOSS is left to manage the retries via the Scheduler Loop. It may be that I can redesign the 'manual retry' mechanism used in the traditional NET driver to use the IOSS retry as well, but its not yet clear to me how this would interfere with the overall driver design. I thought to take the path of least resistance by blindly re-implementing what is already coded, but perhaps re-factoring an approximation of nd_rept would meet the design well enough.

Thinking about this further, simply watching the 50Hz/20ms counter maintained in the SVs by the Polling Interrupt handler might prove sufficient here... I'll give it some more thought.


martyn_hill
Aurora
Posts: 924
Joined: Sat Oct 25, 2014 9:53 am

Re: How best to introduce a timed-delay whilst in Supervisor mode

Post by martyn_hill »

... And in articulating the original question, it now dawns on me a more fundamental issue in blindly re-coding the 'manual retry' as it appears in the existing NET driver...

For as long as we remain in Supervisor mode, the Message Queue Scheduler task won't be running concurrently, so we'll never see a fresh response from the QLUB Adapter (from a previous RECV request), nor any new SEND requests actually being delivered to the microcontroller! It would be a lonely wait, if we tried...

OK, so whilst the original question remains interesting in general terms, I need to rethink how the manual retry mechanism is achieved anyway. Fortunately, its only used in a select few situations within the NET/Nx drivers and, I suspect, it was really only ever a workaround anyways (no offence meant, TT!) as it usurps the usual, elegant IOSS retry mechanism as used throughout the rest of the driver.

Thanks for reading... Back to the drawing board for me!


User avatar
mk79
QL Wafer Drive
Posts: 1349
Joined: Sun Feb 02, 2014 10:54 am
Location: Esslingen/Germany
Contact:

Re: How best to introduce a timed-delay whilst in Supervisor mode

Post by mk79 »

This has always been a bit of a sore point. $18000 is supported by the QL and Q68 as far as I can see, no other platform. Under SMSQ/E you have sys_rtc, but also not supported by all platforms :( I think we should at list try fixing that. The only platform independent way to check the time is the clock trap and linking in a poll routine.

Under SMSQ/E in supervisor mode with interrupts enabled you can also get 20ms ticks by watching sys_pict. This is reset once the scheduler runs, so outside of a supervisor routine it's usually 0.

The SD calibrates a delay loop, but it knows it's running on a QL, so it can use the poll interrupt registers for that. Other drives do something similar, but they are always platform dependent.

QMON has a similar routine for QL and a different for Atari ST. As that was about the time QMON development stopped it was never extended to other platforms, but my yet to be released version uses SMS.SSJB instead in the hopes that it doesn't crash (the old behavior was guaranteed to crash, so at least it's not worse)...

Truly difficult stuff, this time thing.


Post Reply