PDA

View Full Version : [PASM] Subroutine causing coginit() to fail



Wossname
10-26-2011, 07:48 PM
I seem to have a problem where the placement of a subroutine seems to prevent execution of the function nominated by the call to coginit. I've used my logic analyser to verify this behaviour.

I want Cog zero to run beginning at the line marked "AAAA". Now this works fine ONLY if I move the subroutine called "LCD_WriteNibbles" so that it is not above the line marked AAAA.



CON _clkmode = RCFAST


VAR




PUB Main


coginit(0, @AAAA, 0)


DAT

org 0


'################################################# ################
LCD_WriteNibbles


:lcdwritenibbles_loop
mov lcd_temp, lcd_data
shl lcd_data, #4 'shift the low nibble into position ready for the next iteration
and lcd_temp, #$f0 'mask off all unwanted bits
shl lcd_temp, #8 'shift the nibble into the positions corresponding to the IO pins

andn outa, LCD_DATA_MASK 'clear data lines to LCD
or outa, lcd_temp 'put the nibble on the data lines


andn outa, LCD_E_PIN 'clock the nibble into the LCD by clearing the E pin
or outa, LCD_E_PIN 'raise E again to reset clock

djnz lcd_nibblecount, #:lcdwritenibbles_loop

LCD_WriteNibbles_ret ret
'################################################# ################


'----------------------------z- SET IO PIN ASSIGNMENTS
AAAA mov dira, #0 'default all IO pins to inputs

or dira, LCD_DATA_MASK 'set LCD control pins to outputs
or dira, LCD_E_PIN ' "
or dira, LCD_RS_PIN ' "


or dira, #1
'-----------------------------


mov outa, #0 'zero all IO pins
or outa, LCD_E_PIN 'raise E pin ready for data transfer
andn outa, LCD_DATA 'clear LCD data pins
andn outa, LCD_RS_PIN 'clear RS pin

mov time, cnt
add time, POWER_ON_DELAY
waitcnt time, #0



mov time, cnt
add time, LED_DELAY

:loop waitcnt time, LED_DELAY
xor outa, #1
jmp #:loop













LCD_FUNCTION_SET '--------------------------

'0010 == set 4 bit comms mode
'0010 == hard coded as per datasheet
mov lcd_data, #%0010_0010
mov lcd_nibblecount, #2
call #LCD_WriteNibbles

'2 line mode and 5x11 font
mov lcd_data, #%1100_0000
mov lcd_nibblecount, #1
call #LCD_WriteNibbles

mov time, cnt
add time, FUNCTION_SET_DELAY
waitcnt time, #0




LCD_DISPLAY_CONTROL '--------------------------
'0000 == hard coded as per datasheet
'1111 == display on, cursor on, blink on
mov lcd_data, #%0000_1111
mov lcd_nibblecount, #2
call #LCD_WriteNibbles


mov time, cnt
add time, DISPLAY_CONTROL_DELAY
waitcnt time, #0




LCD_DISPLAY_CLEAR '--------------------------
'0000 == hard coded as per datasheet
'0001 == hard coded as per datasheet
mov lcd_data, #%0000_0001
mov lcd_nibblecount, #2
call #LCD_WriteNibbles

mov time, cnt
add time, DISPLAY_CLEAR_DELAY
waitcnt time, #0






LCD_ENTRY_MODE '--------------------------
'0000 == hard coded as per datasheet
'0110 == increment cursor, entire shift off
mov lcd_data, #%0000_0110
mov lcd_nibblecount, #2
call #LCD_WriteNibbles




mov time, cnt
add time, ENTRY_MODE_DELAY
waitcnt time, #0






LCD_WRITE_CHARACTERs '------This is a nasty hardcoded sequence to write "ADAM" to the LCD panel--------
mov lcd_data, #%0100_0001
mov lcd_nibblecount, #2
call #LCD_WriteNibbles


mov time, cnt
add time, CHAR_DELAY
waitcnt time, #0






mov lcd_data, #%0100_0100
mov lcd_nibblecount, #2
call #LCD_WriteNibbles


mov time, cnt
add time, CHAR_DELAY
waitcnt time, #0






mov lcd_data, #%0100_0001
mov lcd_nibblecount, #2
call #LCD_WriteNibbles


mov time, cnt
add time, CHAR_DELAY
waitcnt time, #0





mov lcd_data, #%0100_1011
mov lcd_nibblecount, #2
call #LCD_WriteNibbles


mov time, cnt
add time, CHAR_DELAY
waitcnt time, #0











:donothing waitcnt time, LONG_WAIT
jmp #:donothing

































'for delay timings please see the datasheet for the DEM16217 LCD panel ("4 bit interface mode" initialisation info)
POWER_ON_DELAY long 1_200_000
FUNCTION_SET_DELAY long 600
DISPLAY_CONTROL_DELAY long 600
DISPLAY_CLEAR_DELAY long 50_000
ENTRY_MODE_DELAY long 50_000 'arbitrary - ANW
CHAR_DELAY long 1000
LONG_WAIT long 1_000_000
LCD_DATA_MASK long %1111_0000_0000_0000
LCD_E_PIN long %0000_1000_0000_0000
LCD_RS_PIN long %0000_0100_0000_0000


LED_DELAY long 10_000

time res 1


lcd_data res 1
lcd_nibblecount res 1
lcd_temp res 1

fit






This program is clearly a work in progress but I can't figure out why the position of the subroutine would make any difference if I'm specifying the label of the line that I want cog zero to begin at. All I want to do right how is have cog zero blink a led by calling the code starting at AAAA, but that doesn't happen apparently, the chip just sits there seemingly doing nothing I expect it to. If I move that "LCD_WriteNibbles" subroutine down to just before the final declarations then hey presto the code flashes the LED as expected and I can trigger my logic analyser like I wanted to 2 hours ago.

I'm stumped.

Heater.
10-26-2011, 08:24 PM
When the PASM code is started by cogint it loads the 496 longs of code from the given address and starts it. Anything before that in the DAT section will not be loaded.
Further, it starts the code expecting it to be compiled to offset zero in the COG. I.e. the initial program counter is zero. If you have any instructions or data before that start location in DAT the code will be compiled as if it is executed at some other address in COG. Unless you have an ORG 0 just prior to the start label.

Wossname
10-27-2011, 06:50 AM
Thank you for the explanation, now I understand. It seems a bit redundant to have to include both ORG and a start label for the cog's entry point though. Perhaps it is implemented that way to enable more advanced tricks that I haven't learned yet :)

Anyway problem solved, cheers for that.
:thumb:

Heater.
10-27-2011, 09:01 AM
Actually for normal PASM coding I don't think you need the ORG 0 as that will be the default anyway. Just put your start label at the beginning, don't have any data or instructions before that.

Yes ORG does have "advanced" uses. Such as creating "overlays". Chunks of code that are not loaded at start of COG but perhaps your COG program loads them into some free space and runs them when required. Thus allowing one to have PASM code bigger than the 496 LONGs that fits in a COG. Have a look for Cluso's overlay loader to see how that works.