ASM SCI interrupt driven routines on HC08

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

ASM SCI interrupt driven routines on HC08

9,960 Views
Encoder
Contributor I
I would like to find some fully working examples of interrupt driven SCI routines for HC08 with SCI or ESCI module, in assembler format.
Freescale provides something like that on AN991, which is well documented, perfectly functional but not interrupt driven. I wonder that with over 3000+ AN it does not cover such an issue, considering that a well functioning error-proof SCI routine is not a trivial task. The recent AN3035, other than written in C, is nearly useless, at least fo me...
I'd tried some interrupt variant of AN991 and they had some partial success, but some unkown bug impedites to be perfectly functional.
Some lines from an experienced programmer, with initial declarations would be very helpful to me. Best of all some sort of example like the "Ping-pong" program in AN991.
 
My application is transmission of some bynary data to a master CPU from one or more slaves, in reaction of a decoded received command.
 
Could somebody help me with some code, at least for the SCI routines or addressing me to some specifical article or Application Note?
Labels (1)
0 Kudos
9 Replies

621 Views
peg
Senior Contributor IV

Hi Encoder,

Have a look at this:

;the comms format is <;> header, single byte address, data then <CR> terminator
; the master (a PLC) is address 0
; it is RS-485 multidrop
; this is cut from an actual old application on a GP32

;init the SCI

  mov #%00010010,SCBR  ;9600 BAUD AT 7.3MHZ BUSS
  mov #%01000000,SCC1  ;enable SCI
  mov #%00101100,SCC2  ;SET SCC2 TO ENABLE SCI & REC INT
  mov #%00000000,SCC3  ;set SCC3


;so it always receives, and puts the string in RECBUF and sets a bit when its got the complete string
;and when you want to send a response:
;you put it in TXBUF and do this:

                       BSET TXRXENA,PORTD ;enable transmitter
                       BSET 7,SCC2  ;enable transmit ints

 

************* SCI INTERRUPT SERVICE ROUTINE *********************************

SCITX_SVR   LDA   SCS1
           BRSET 5,SERSTAT,SENTHEAD ;(INT MUST BE SCTE) CHECK IF HEADER SENT
           BSET  5,SERSTAT
           LDA   #$3B              ;SEMICOLON
           STA   SCDR              ;SEND HEADER
           BRA   SCITRET
SENTHEAD    BRSET 6,SERSTAT,SENDMESS ;CHECK IF ADDRESS SENT
           BSET  6,SERSTAT
           LDA   #'0'
           STA   SCDR              ;SEND ADDRESS
           BRA   SCITRET
SENDMESS    LDX   TXCNT             ;GET TX'D CHAR COUNT
           INC   TXCNT
           LDA   TXBUF,X           ;GET NEXT CHAR FROM TXBUF
           STA   SCDR              ;SEND CHAR
           CMP   #CR               ;CHECK IF CARRIAGE RETURN
           BNE   SCITRET           ;KEEP GOING IF NOT CR
           BCLR  7,SCC2            ;DISABLE TX INTERRUPTS
           BCLR  5,SERSTAT
           BCLR  6,SERSTAT

SCITC       BRCLR 6,SCS1,SCITC      ;WAIT FOR TRANSMISSION COMPLETE
           BCLR  TXRXENA,PORTD
           CLR   TXCNT             ;RESET TX COUNTER

SCITRET     RTI                     ;FINISHED TX

************************************************************************

SCIRX_SVR   LDA   SCS1              ;GET STATUS REG
           AND   #%00001110        ;CHECK FOR ERRORS, OR, NF, FE
           BNE   ERROR             ;SET LED ON & EXIT

  LDA SCDR              ;GET RECIEVED CHAR
  CMP #$3B              ;CHECK FOR HEADER (SEMICOLON)
  BNE NOTSEMI
  BSET 1,SERSTAT ;set have header
  BCLR 3,SERSTAT ;clear have address char
  BCLR 4,SERSTAT ;clear my address
  CLR RECCNT  ;clear recieved char count
  BRA SCIRET
NOTSEMI  BRCLR 1,SERSTAT,SCIRET ;no header so bail
  BRSET 3,SERSTAT,READMESS
           BSET  3,SERSTAT
           CMP   ADDRESS
           BNE   SCIRET
           BSET  4,SERSTAT         ;SET MY ADDRESS BIT
           BRA   SCIRET
READMESS    CMP   #LF               ;RECIEVED CHAR IS LF
           BEQ   SCIRET            ;DON'T BUFFER IT
           CMP   #SPACE            ;CHECK IF A SPACE
           BEQ   SCIRET            ;BAIL IF IT IS
  CMP #$08  ;Backspace?
  BNE NOTBS  ;bypass if not
  TST RECCNT  ;bypass if no chars
  BEQ SCIRET
  DEC RECCNT  ;delete last char
  BRA SCIRET  ;and bailout
NOTBS  LDX RECCNT  ;GET CHAR COUNT IN X
           STA   RECBUF,X          ;PUT CHAR IN BUF
           CMP   #CR               ;CHECK IF CARRIAGE RETURN
           BNE   NOCR              ;KEEP GOING IF NOT CR
           BSET  0,SERSTAT         ;SET LINE RECIEVED BIT

NOCR        INCX                    ;INC X REG
           STX   RECCNT            ;INC CHAR COUNT
           CPX   #RBUFSIZ          ;CHECK ROOM LEFT IN BUF
           BEQ   RESETC            ;ROLL OVER IF NO ROOM LEFT
           BRA   SCIRET            ;END IF OK

ERROR       BSET  COMMERR,INTPORT   ;TURN FAULT BIT ON
           LDA   SCDR              ;READ RECIEVED CHAR TO CLEAR

RESETC      CLR   RECCNT            ;RESET CHAR COUNT

SCIRET      RTI                     ;LEAVE

Regards

Peg

0 Kudos

621 Views
bigmac
Specialist III

Hello Encoder & Peg,

With respect to the sample code, a minor (but important) point - I notice that both ISRs are using indexed instructions to access the buffers, so CLRH instructions should be explicitly included.  So the existing H-values would first need to be pushed to the stack, and restored on exit from the ISR.

For multi-drop RS485, the packet structure and handling might need to be a little more complex, for compatibility with half-duplex operation, and to ensure that only a single slave will respond to each command from the master. So, somewhere within the command packet the destination (slave) address would be required.  For the master, a "receive window" timeout period would also be required so that slave polling operation could continue in the event that the slave does not respond.

Many multi-drop systems would also include error detection (checksum or CRC) within each packet, to allow for error detection and re-send of packets.

Regards,

Mac

 

 

0 Kudos

621 Views
peg
Senior Contributor IV
Hi Mac,
 
Agree with all you say *BUT*
 
1. This is converted '05 code and I chose to handle the H reg from the other direction.
 
2. There is an address! and this is only the slave code.
 
3. Dropped/garbled mesages aren't the end of the world here and it was deemed to much of a PITA to implement CRC etc in all the different PLC types.
 
Also I was only trying to show how to do interrupt based serial comms, not implement a full blown protocol.
0 Kudos

621 Views
Encoder
Contributor I
Well,
with your help I was able to debug my routine and now it is working.
I will take some other precious suggestion from your routine, which is far more structured.
It seems anyway only aimed to ASCII transmission: I need to transmitt bynary data and I have to change the format to be able to transmit any byte, including $0D, LF, SPACE etc..
I think to add a leading byte which states the data length, so avoiding skipping or altering reserved characters in the middle of the message.
Another feature I want to include is a timeout to terminate erratic or unclosed messages: it should be not too difficult using the OS RTC.
 
If someone has other suggestions on the matter, or may propose some "standard" format for bynary data exchange, welcome:smileywink:
0 Kudos

621 Views
Wings
Contributor I
Encoder said: Another feature I want to include is a timeout to terminate erratic or unclosed messages: it should be not too difficult using the OS RTC.

If the data being sent to you has no gaps between bytes (rather, is not supposed to), you can implement a timeout using the SCI's IDLE bit in the SCI Status Register. Using that feature you can generate an IRQ whenever the line goes idle for more than a character time.
0 Kudos

621 Views
bigmac
Specialist III
Hello Encoder,
 

Encoder wrote:
...  I need to transmitt bynary data and I have to change the format to be able to transmit any byte, including $0D, LF, SPACE etc..
I think to add a leading byte which states the data length, so avoiding skipping or altering reserved characters in the middle of the message.

If your data packets are not too long, you could handle the binary data as a pair of hexadecimal characters for each data byte (as used by Motorola S19 or Intel Hex formats).  Of course, this would be impractical for very long packets because each byte requires two characters be sent.

Another possibility would be to identify two different packet types, one containing (encoded) binary data, and the other containing ASCII string data.  Here, you might use different ASCII control characters (not normally used within the string data), to delimit the packet.  An example might be <SOH> for the start of the packet, and <ETX> for the end of the packet.  So the packet structure might look something like:

<SOH>
<destination byte>
<packet type byte>
[<length byte>]
[<STX>]
<packet data N bytes>
<ETX>
<check>

With this structure, the <length byte> and <STX> character are probably optional.  The only special requirement would be that <ETX> value did not occur within the <packet data>.  For simplicity, <check> might be a single checksum byte (XOR of previous characters).
 
Regards,
Mac
 
0 Kudos

621 Views
Encoder
Contributor I
Hallo Mac and Peg,
I correctly took the Peg's code sample for a guideline, not for Bible. And it was precious. Obviously I manage H and X register throughfully on every interrupt service, pushing them forth and back on the stack, whenever I work with X in the service routine.
I extensively saw bin data cut in 2 nibbles and transmitted as ASCII: obviously there is an important overheading and nearly a doubling of the message length.
 
I am convincing myself that the only standard in this matter is a "lack of standard". So fine the suggestions for slave address, for type of data, checksum, opening and closing of the packet and so on. They will be very usefull especially on long messages and I will issue a general format that sense.
 
In my own application this time, I will probably simplify the format in favour of message shrinkage, considering also the possible number of master & slave units in the system. Also timeout will heavely depend on the system: a matter is having to consider a manual command or answer by an hyperterminal, a different task is an automatic and presumably fast response by a CPU
 
Thanks a lot for your time spent on the subject. I think to be on the final track but other suggenstions or point of view or even code samples are welcome.
 
Encoder 
0 Kudos

621 Views
peg
Senior Contributor IV
Hi Encoder,
 
yeah I was going to ask you all the questions first like is it ASCII/binary?, is it multi-drop? How bullet proof does it need to be? But in the end just decided to throw what I did at you to see what you thought. Seems like it was the best idea!
It obviously got the interrupt part undestood for you.
 
The only "standard" is there is no standard as it *VERY* much depends on what you need.
 
BTW, in this application I have now moved it to S08 and in doing so dropped the transmit back to non interrupt based as the application has a lot of intensive interrupt action going on and while you have to catch the bytes on the way in, it doesn't matter if you drip feed them on the way out. Well not for this app anyway!
 
I did not timeout, if you get another semicolon it just resets the buffer and starts again. This is one advantage of ASCII I know there is going to be no stray semicolons or <CR>'s in the data. (don't need length!)
 
BR
Peg
0 Kudos

621 Views
Encoder
Contributor I
It seems much like I need. My obvious need is to continue to work while SCI interrupts serve main receveir and transmitter tasks.
 
I will have a busy night today to test at home...:smileyhappy:
 
I'll let you know the results. Thanks a lot
Encoder
0 Kudos