MRT (Multi-Rate Timer) [54102 & 824]

Questions on other types of hardware and getting it talking to the ARM CPU
Post Reply
TodWulff
Posts: 51
Joined: Fri Oct 19, 2012 4:03 am
Location: The Mitten State - Shores of Lake Huron

MRT (Multi-Rate Timer) [54102 & 824]

Post by TodWulff » Sat Nov 24, 2018 9:33 am

Following are two examples of using the MRT peripheral on different Coridium Targets - the 54102 and the LPC-800DIP (OEM 824 board).

The samples are pretty similar. Coridium's LPC8xx.bas library was missing a #def for the MRT GFlag register (which used to clear the MRT Interrupt(s)), and had an error therein too, so that is why the #defs exists only in the 824 sample. Other register names on each device differ, but it does work.

824 Code

Code: Select all

#include "LPC8xx.bas"				' needed for the header #defs 

#define MRT_IRQ_GFLAG 	   *0x400040F8			'mia from LPC8xx lib
#define MRT_Channel0_TIMER       *&H40004004		'fix an error in LPC8xx lib


_MRT_InitGlobals:
	dim MRT_INT_Flag,MRT_INT_Time as integer		' this is a MRT user flag
	return
	
interrupt sub _MRT_INT_ISR			' this isr only sets a flag, clears the interrupt and exits - a handler will perform outside of an interrupt context
	MRT_INT_Flag = MRT_IRQ_GFLAG		' assert the user flag during the ISR, saving the GFLAG0-4
	MRT_IRQ_GFLAG = MRT_IRQ_GFLAG		' clear the MRT interrupt 
	MRT_INT_Time = timer
	endsub
	
sub _MRT_INT_Handler				' this is the handler to do more stuff at time of interrupt, outside the isr
	print "Interrupt ";MRT_INT_Flag;" Fired @ "; MRT_INT_Time
	'do stuff here
	MRT_INT_Flag = 0				' clear the user flag
	endsub
	
main:
	print "Started @ Timer:", timer
	
	call _MRT_InitGlobals
	MRT_INT_Flag = 0				' deassert the MRT user flag

	'set up the MRT timer here
	SYSCON_SYSAHBCLKCTRL or= (1<<10)	' set the MRT bit to enable the clock to the register interface.
	SYSCON_PRESETCTRL or= (1<<7) 		' Clear reset to the MRT.
	
	MRT_Channel0_INTVAL = 0x81C9C380 		' immediately load the MRT IntVal
	'824	= 100hz = 0x493E0	250Hz=0x1D4C0	500Hz=0xEA60	1000Hz=0x7530
	'max is 0x7FFFFFFF  which is 71.6 Seconds  -  you can set b31 too, to force immediate load, per UM.
	'use 0x81C9C380 for an immediate load of a 1HZ repeating interrupt.

	
	
	MRT_Channel0_CTRL = 0x00000001			' enable TIMERn Interrupt in repeat interrupt mode

	' default MRT int priority is fine - so noeffwidit
	
	' set up the MRT Interrupt here
	MRT_ISR = (addressof _MRT_INT_ISR) or 1	' assign the isr sub addy to the NVIC vector table for MRT_irq  (the 'or 1' is for thumb code purposes)
	VICIntEnable or= (1<<10)				' enable the MRT interrupt

	do
		if MRT_INT_Flag then _MRT_INT_Handler
'		print MRT_Channel0_TIMER
	loop
	
end
54102 Code

Code: Select all

#define CORE_M4						' needed for this dual core device, & given we're working with the NVIC on the M4
#include "LPC54102.bas"				' needed for the header #defs 

_MRT_InitGlobals:
	dim MRT_INT_Flag,MRT_INT_Time as integer		' this is a MRT user flag
	return
	
interrupt sub _MRT_INT_ISR			' this isr only sets a flag, clears the interrupt and exits - a handler will perform outside of an interrupt context
	MRT_INT_Flag = MRT_IRQ_FLAG		' assert the user flag during the ISR, saving the GFLAG0-4
	MRT_IRQ_FLAG = MRT_IRQ_FLAG		' clear the MRT interrupt 
	MRT_INT_Time = timer
	endsub
	
sub _MRT_INT_Handler				' this is the handler to do more stuff at time of interrupt, outside the isr
	print "Interrupt ";MRT_INT_Flag;" Fired @ "; MRT_INT_Time
	'do stuff here
	MRT_INT_Flag = 0				' clear the user flag
	endsub
	
main:
	print "Started @ Timer:", timer
	
	call _MRT_InitGlobals
	MRT_INT_Flag = 0				' deassert the MRT user flag

	'set up the MRT timer here
	SCB_AHBCLKCTRL(1) or= SYSCON_CLOCK_MRT	' set the MRT bit to enable the clock to the register interface.
	SCB_PRESETCTRL(1) and= 0xFFFFFFFE 		' Clear reset to the MRT.
	
	MRT_INTVAL(0) = 0x800EA600				' immediately load the MRT IntVal
	'100hz = 0x800EA600	250Hz=0x8005DC00	500Hz=0x8002EE00  1000Hz=0x80017700 -  set b31 too, to force immediate load, per UM.
	'max is 0x80FFFFFF  which is ~175mS - I don't get why the time range is so different from the 824 design
	'but it is what it is - per the UM:  24-bit interrupt timer clocked from CPU clock
	'you can set b31 too, to force immediate load, per UM, as I have done above
	
	
	MRT_CTRL(0) = 0x00000001			' enable TIMERn Interrupt in repeat interrupt mode

	' default MRT int priority is fine - so noeffwidit
	
	' set up the MRT Interrupt here
	MRT_IRQn = (addressof _MRT_INT_ISR) or 1	' assign the isr sub addy to the NVIC vector table for MRT_irq  (the 'or 1' is for thumb code purposes)
	VICIntEnable0 or= (1<<10)				' enable the MRT interrupt

	do
		if MRT_INT_Flag then _MRT_INT_Handler
'		print MRT_TIMER(0)
	loop
	
end
If you set the MRT's INTVAL register to a large valid value and, In the do loops at the end of the main section, if you uncomment the print MRT_TIMER(0) | print MRT_Channel0_TIMER line, you can watch the value get reset and decrease on each pass, as the MRT counts down to zero/interrupt.

-t



Post Reply