SPI interfacing with ARC32

hey guys,

Im working on a project to create a pretty big robot. and as such, we are using the ARC32 as a means of controlling the servos of the robot, and having an android phone interfacing with the ARC32. We are using it in a smilar fashion to the SSC32, but with movement code and that sort of thing offloaded onto the ARC32.

Anyway, so the problems ive been having are with SPI interfacing. I have the master code set up on the android phone, and so im working on trying to fix the slave SPI on the ARC32. but am having huge problems, i cannot get it to clock in bits at all. and since it is the Slave, it doesnt work to use the SHIFTIN and SHIFTOUT command library. In this case i need to clock in somewhere between 4-8 bits. and in my example code am using 32 for testing.

Does anyone have any suggestions/feedback/help of how i can fix Slave-SPI on the ARC32?
Thanks in advance for all the help and advice, it has been very much appreciated!

Here is the code im currently running, but am having problems with:

[code]'setup vars
baudrate CON i9600
'temp and storage vars
temp VAR WORD 'input var
t VAR BIT
i VAR BYTE 'counting var
j VAR BYTE

'interrupt setup code
IEGR1.bit2 = 1 'sets interrupt to pin 28
PMR1.bit6 = 1 'sets interrupt to be falling edge detection
'interrupt directives
ONINTERRUPT IRQ2INT, sigreceive 'interrupt pin setup directive
ENABLE IRQ2INT 'enables the IRQ2INT on pin 2
ENABLE

'pin constants
CLK_PIN CON P29
Data_pin CON P40

main:
While(1)

Wend

END

sigreceive: 'when handshake pin is high, triggers input interrupt
DISABLE 'disables global interrupts so no compound triggered interrupts occurs
TOGGLE P44 'shows waiting for data
LOW P44 'shows data received
ENABLE 'reenables global interrupts, so data can be read in again
'decode within external interrupt
GOSUB in_data[temp]
RESUME

in_data[temp]:
i = 0
j = 32
WHILE(i<>32)
IF clk_pin = 1 THEN
SERIN Data_pin, [t]
i = i + 1
j = j - 1
ENDIF
temp.bitj = t 'i know this bit is not right, but i want to get it to write to the J-th bit of the var TEMP
WEND[/code]

If you aren’t currently using the second UART on the ARC32 I’d suggest dropping what you are doing and using it’s syncronous serial mode instead. I’t supports slave mode(eg spi clock externally).

Pins 3,4 and 5 on Aux1 are the TX,SCK and RX pins respectively.

See section 16.5 of the H8-3687 manual.

[code];SPI slave receive example using Polling

cs var in0 ;use p0 as a chipselect pin

SCR3_2 = 0x02 ;set external clock mode, clear all interrupt enable bits, clear TE and RE bits
SMR_2 = 0x80 ;enabled syncronous mode
SSR_2 = 0 ;clear all flags

data var byte
main
if(in0=0)then
SCR3_2.bit4 = 1 ;enable reception
else
SCR3_2.bit4 = 1 ;disable reception
endif
if(SSR_2.bit5)then ;check OER flag bit
SSR_2 = 0 ;clear all flags
endif
if(SSR_2.bit6)then ;check RDRF flag bit
data = RDR_2 ;clears RDRF flag when you read RDR
endif
goto main[/code]
Note I have not tested this yet but I think it covers everything and should be a good starting point.

As for your code above:

  1. SERIN is a bitbanged asyncronous serial command so I have no idea why you’d want to try receiving a byte 32 times based on whether a clock pin was high all in a single interrupt. ouch
  2. You should never try to do so much in an interrupt even if what you are doing is actually correct. You’d be much better off setting a flag that something that will take time needs to be done and then process that in your main code(eg as a state machine).

If you really wanted to bitbang slave SPI using an interrupt then you’d:

  1. handle each incoming clock pulse(rising/falling edge depending on the SPI mode you want to support) as a seperate interrupt each.
  2. shift left/right one bit(depending on MSB first or LSB first) of your temporary data byte, then store the received bit in the high or low bit of the temporary data byte
  3. if all 8 bits have been received at that point then move the data byte to a circular queue buffer which can be accessed by main program code(eg properly handling indexing variables to be pointing to the correct start/end bytes of the queue as necessary)
  4. exit the interrupt

Hi Nathan,

I’m working on the same team as herpaderp on this project, so him and I are pretty much one and the same, trying to get the SPI to work on the ARC-32 using BASIC programming language.

I have two questions I’d like to ask:
(1) We were able to get some SPI transmission going on the ARC-32 via interrupts. But when we print the data received in binary format on the ARC-32, it is backwards from how we sent it, so we’re inferring that the ARC-32 is currently putting data into the receive register in MSB-0 fashion. The Android phone is transmitting MSB first, and the ARC-32 is putting that in bit position 0. Is there a way to fix this on the ARC-32 so that it puts data into its receive data register MSB first, and LSB last? Maybe a register setting? We could not find anything in the manual to swap the bit order on the SCR3_2 hardware.
(2) The manual says that the ARC-32 supports both C and BASIC. But, it doesn’t compile when we try to use both programming languages. If we used only C, then we can’t access commands like HSERVO, and if we used only BASIC, some of the programmers on the team will have to learn BASIC, and we cannot use any of the C libraries. Is there a way to cross-compile both languages?

Hi, Nathan can probably answer some of this better than I can but will take a shot.

on #1) I could not tell if you converted to using the 2nd serial port or kept with your earlier code. If you went with your own code you are in control and can input or output the bits in any order you like.

on #2) Yes you can do C or basic. Yes you can do C, but as you mentioned, You can not mix with Basic. There are at least 2 of us who have generated somlibrariesries for the Basic Atom Pros. I have not played it for awhile, but my libraries did include things like hservo support. But thlibrariesries are not supported… More details in the thread: viewtopic.php?f=8&t=6196&start=45

Kurt

Hi Kurt,

Thanks for answering #2. I figured as much, so I’ll have to keep continue using BASIC.

A little more on #1, I am definitely using the second serial port as the code snippet herpaderp and Nathan used (SCR3_2, RDR_2, and etc. similarly named registers). I am not bit-banging in the serial data as herpaderp is. I’m using interrupts and the hardware to take care of it. I was able to set the SCR3_2 to synchronous serial mode. However, the received data is inverted hardware-wise. I’m looking to see if anyone’s encountered a register bit that can swap which way data is shifted in to the receive register.

#1. No you can’t change the order the SCI3_2 reads in the data bits. So in your case you will need to reverse the bits after reading them in. You can ujse the REV command to do this(rev 8 to reverse 8 bits) or if you want more speed you can do it like this.

mov.b @MYVAR:16,r0l shlr.b r0l rotxl.b r0h shlr.b r0l rotxl.b r0h shlr.b r0l rotxl.b r0h shlr.b r0l rotxl.b r0h shlr.b r0l rotxl.b r0h shlr.b r0l rotxl.b r0h shlr.b r0l rotxl.b r0h shlr.b r0l rotxl.b r0h mov.b r0h,@MYVAR:16

Replace MYVAR with your byte variable name. You could also take the byte out of the receive register with this code, reverse the bits and then store it in your byte variable by just replacing the mov.b @MYVAR:16,r0l at the top with mov.b @RDR_2:16,r0l

This takes 28 clock cycles to reverse the bits in the byte.

Hi Nathan and thanks everyone for your suggestions,

We didn’t bit-bang SPI. We were able to get the ARC32 hardware to interrupt when slave selected and the ARC32 serial hardware was able to transmit and receive data in duplex. We did find a quirk though. Sometimes the ARC32 would get interrupted twice on its slave select line. This would result in us usually losing 2-3 bits in the receive register.

Near as we can tell, we scoped the slave select line and it works properly as we expect it to. The SS line is logic high before SPI transmission, and pulled low when an SPI transmission from the SPI master (phone) to the SPI slave (ARC32) is about to begin, and the SS line is kept low always until the end of the transmission. We do not see anything on the SS line going back high and then low again within a single SPI transmission.

We found this quirk because in our ARC32 slave select (IRQ2) interrupt service routine, we print to the terminal that the ARC32’s been interrupted and enable SPI reception (kind of like what you wrote in your first post). Then, at the completion of the SPI transmission, the RDRF interrupt service routine kicks off, and we read the RDR_2 register into our variable, reverse the order using REV command, print the received number in binary form to the terminal, and lastly disable SPI reception.

In order for the slave select ISR to fire twice, we think that the ARC32 is thinking that the SS line went high and back to low during the middle of a SPI transmission, thus running the slave select ISR again and re-enabling SPI reception. So, logically, after this quirk and because it happened in the middle of a SPI transmission, there are only 5-6 more SPI clock cycles left, and so the RDR_2 receives the last 5-6 bits of the SPI transmission, but loses the first 2-3 bits of the SPI transmission.

The most confusing thing is that this problem doesn’t show up on an oscilloscope and only happens on the ARC32 once in awhile and not every SPI transmission.

Any one have any ideas about this?