hspi and hardware interrupts - 28X2 :(

MartinM57

Moderator
My latest headache which I have simplified right down to show the problem

Hardware is an SPI device connected to HSPI SDO(MOSI), SDI(MISO) and SCK(CLK), with its Slave Select on pin B.7, plus a DS1307 SQW output at 1Hz attached in the HINT1 pin

The following code sends data to an SPI device (nice and slowly at m4) and reads the return code - it runs fine for hours on end...note that interrupts are disabled
Code:
#picaxe 28x2
#no_table
#slot 0
#terminal 4800

symbol hint_setting = b36

'deselect SPI slave
high B.7

setfreq m4

'stabilise
pause 500

sertxd ("started...", CR, LF)

'setup hspi
hspisetup spimode00, spislow

'set up interrupt on falling edge of hint1 - note COMMENTED OUT FOR SUCCESS
'hint_setting = %00000010 
'hintsetup hint_setting
'setintflags %00000010,%00000010	' enable hint1

main:
	'select SPI slave
	low B.7
	'send data
	hspiout ($11,$05,$1B,$5A,$54,$30,$00,$0F)
	'get response
	hspiin (b0)
	'deselect SPI slave
	high B.7
goto main

interrupt:
	hint1flag = 0
	return
If I uncomment the three lines that set up the HINT1 interrupt, so that I get a 1Hz interrupt that does nothing except re-enable the interrupt for next time, the code runs for between 1 and 10 seconds (seemingly randomly) before locking the PICAXE up completely - no more HSPI commands are sent and a new download can only be made after a hard reset.

If i put some sertxds into the main loop to see what's going on, with HINT1 enabled, it runs perfectly. but very slowly of course e.g.
Code:
main:
	'select SPI slave
	sertxd("low B.7", CR, LF)
	low B.7
	'send data
	sertxd("hspiout ($11,$05,$1B,$5A,$54,$30,$00,$0F)", CR, LF)
	hspiout ($11,$05,$1B,$5A,$54,$30,$00,$0F)
	'get response
	sertxd("hspiin (b0)", CR, LF)
	hspiin (b0)
	'deselect SPI slave
	sertxd("high B.7", CR, LF)
	high B.7
	sertxd("goto main", CR, LF)
goto main
It seems that hardware interrupting whilst using hardware SPI at a reasonably fast rate has a nasty interaction...thoughts?
 

hippy

Ex-Staff (retired)
I don't have an answer and no SPI hardware at hand to test. The two possibilities that spring to mind are that HINTSETUP changes on input pin are interfering with HSPIIN/HSPIOUT or the handling of the interrupt with SETINTFLAGS is.

You can perhaps test if it's the later by putting "SETINTFLAGS OFF" before the HSPIOUT and then re-enable SETINTFLAGS to interrupt on hint1flag after HSPIIN, You can later try enabling then disabling between the HSPIOUT and HSPIIN.

Though you've disabled interrupts, the hint1flag should still be set when the signal line changes, and when interrupts are enabled it should cause an immediate interrupt. This should have effect of deferring the interrupt until after HSPI completes. If it is a clash of interrupts issue this should overcome that.
 

MartinM57

Moderator
Thanks for the ideas.

Bracketing the whole of the inside of the main loop with setintflags manipulation
Code:
main:
	setintflags off
	'select SPI slave
	low B.7
	'send data
	hspiout ($11,$05,$1B,$5A,$54,$30,$00,$0F)
	'get response
	hspiin (b0)
	'deselect SPI slave
	high B.7
	setintflags %00000010,%00000010	' enable hint1
goto main
makes no difference - still locks up after a short time :(

However it does work fine if I also turn off the hintsetup
Code:
main:
	'select SPI slave
	hintsetup 0
	setintflags off
	low B.7
	'send data
	hspiout ($11,$05,$1B,$5A,$54,$30,$00,$0F)
	'get response
	hspiin (b0)
	'deselect SPI slave
	high B.7
	hintsetup hint_setting
	setintflags %00000010,%00000010	' enable hint1
goto main
The bad news is that I miss most of the incoming interrupts as they are edge triggered and edge detection is off for most of the time :(
 

tiscando

Senior Member
Try this:
Code:
main:
 'select SPI slave
	low B.7
	'send data
	hspiout ($11,$05,$1B,$5A,$54,$30,$00,$0F)
	'get response
	hspiin (b0)
	'deselect SPI slave
	high B.7
if hint1flag=1 then gosub interrupt
goto main
Just to narrow down the issue whether if it is on setintflags due to hinsetup, or solely hintsetup.
 

MartinM57

Moderator
Code:
#picaxe 28x2
#no_table
#slot 0
#terminal 4800

symbol hint_setting		= b36

'deselect SPI slave
high B.7

setfreq m4

'stabilise
pause 500

sertxd ("started...", CR, LF)

'setup hspi
hspisetup spimode00, spislow

'set up interrupt on falling edge of hint1
hint_setting = %00000010 
hintsetup hint_setting

main:
	'select SPI slave
	low B.7
	'send data
	hspiout ($11,$05,$1B,$5A,$54,$30,$00,$0F)
	'get response
	hspiin (b0)
	'deselect SPI slave
	high B.7
	if hint1flag = 1 then gosub interrupt
goto main

interrupt:
	inc b1
	sertxd ("interrupt ",#b1,CR,LF)
	hint1flag = 0
return
Nope - locks up randomly between 2 and 30 interrupts :(
 

MartinM57

Moderator
I suppose the work around is to abandon the hardware interrupt detection have a 'this time' and 'last time' value of the (interrupt) pin in the main loop (using a simple read of the pin) and call the (interrupt) routine if they are different...

...but that's like having a dog and barking yourself
 

MartinM57

Moderator
Like this, which works fine and gives me a reliable 'interrupt' every 0.5 seconds...
Code:
#picaxe 28x2
#no_table
#slot 0
#terminal 4800

symbol this_time = b0
symbol last_time = b1

'deselect SPI slave
high B.7

setfreq m4

'stabilise
pause 500

sertxd ("started...", CR, LF)

last_time = pinB.1

'setup hspi
hspisetup spimode00, spislow

main:

	'select SPI slave
	low B.7
	'send data
	hspiout ($11,$05,$1B,$5A,$54,$30,$00,$0F)
	'get response
	hspiin (b0)
	'deselect SPI slave
	high B.7

	this_time = pinB.1
	if this_time<>last_time then gosub interrupt
	last_time = this_time

goto main

interrupt:
	inc b2
	sertxd ("interrupt ",#b2,CR,LF)
return
 

hippy

Ex-Staff (retired)
Two possible suggestions for improving things -

First use traditional SETINT to determine when the pin goes high and low, switching between the two required SETINT's for that and only counting going highs.

Second, use HINTSETUP and SETINTFLAGS as previously but set the pin for INT1 to be an output and don't connect anything to that pin. Put the interrupting signal in to another pin and then in the loop ( before, between and after the HSPI commands ) copy the signal pin to the INT1 output pin. The INIT1 pin going high will automatically set the hInt1Flag and the interrupt will then occur automatically. This worked for me ( and also 20X2 changing xxxB.1 to xxxB.0 ) ...

#Picaxe 28X2
#No_Table
#No_Data
#Terminal 9600

dirB.1 = 1
HIntSetup %00100010
SetIntFlags %00000010, %00000010

Do
pinB.1 = pinC.3
Loop

Interrupt:
w0 = w0 + 1
SerTxd( #w0, " " )
hInt1Flag = 0
SetIntFlags %00000010, %00000010
Return

I can't actually test SPI itself but this code didn't seem to crash in the testing I've done ...

Do
pinB.1 = pinC.3 : Low B.7
pinB.1 = pinC.3 : HSpiOut ($11,$05,$1B,$5A,$54,$30,$00,$0F)
pinB.1 = pinC.3 : HSpiIn (b9)
pinB.1 = pinC.3 : High B.7
Loop
 
Last edited:

MartinM57

Moderator
Thanks H.

I'll try the first method (can't see why it won't work) but I'll pass on the second - my real main loop has tens of sets of hspiout/hspiin sets and I don't fancy all those pin assignments in the code.

It would be good if someone could confirm what I'm seeing and whether there could/might/will be a proper fix

Ta, Martin
 

hippy

Ex-Staff (retired)
Sorry forgot to mention that ... Yes, I can demonstrate the problem happening and it seems to happen with either HSPIIN or HSPIOUT in the program. Without any actual SPI device connected the code jams up and a couple of seconds later resets the PICAXE. It's on the list of things to investigate.

If you are only interrupting on a 1Hz signal you may be able to get away with using the second trick and only copying pins rarely. Half a second is a long time and you may only need one per loop.
 
Last edited:

womai

Senior Member
Wasn't there a previous thread where Technical explained that the SPI input must never be left unconnected when using hardware SPI - doing so would cause a timeout and this may explain the reset? As a workaround - maybe just use bit-banged SPI (shiftin/shoftout commands)? That still runs at around 20 kHz bit rate.
 

MartinM57

Moderator
Wasn't there a previous thread where Technical explained that the SPI input must never be left unconnected when using hardware SPI - doing so would cause a timeout and this may explain the reset?
Yes there was - but I am using a real SPI device that is returning valid values to hspiin...
 
Top