XC8 & Assembler: local function param variables are not unique

Thread Starter

MMcLaren

Joined Feb 14, 2010
842
Just started experimenting with inline assembler on XC8. My problem is that XC8 is using location 70h for the wrchar@ascii parameter and using locations 70h and 71h for the putstr@str parameter/pointer in the program below so the wrchar() function is destroying the pointer in the putstr() function.

I've been searching for a few hours now but probably not using the correct search terms. Can I impose on your guys for help, please?

TIA... Cheerful regards, Mike, K8LH
Code:
/************************************************************************
 *                                                                      *
 *  Project: Nokia_Fonts                                                *
 *   Source: XC8_Font_v2.c                                              *
 *   Author: Mike McLaren, K8LH                                         *
 *  (C)2013: Micro Application Consultants                              *
 *     Date: 25-May-2018                                                *
 *                                                                      *
 *   Experimental Nokia 5110 LCD display driver demo using a 96         *
 *   character packed 2.5-word-per-character 5x7 font table on a        *
 *   PIC16F1823.                                                        *
 *                                                                      *
 *      IDE: MPLAB v8.92                                                *
 *     Lang: XC8 v1.45, Lite/Free version                               *
 *                                                                      *
 ************************************************************************/

/* CONFIG1 */
  #pragma config FOSC = INTOSC  // INTOSC oscillator: I/O on CLKIN pin
  #pragma config WDTE = OFF     // Watchdog Timer Enable (WDT disabled)
  #pragma config PWRTE = OFF    // Power-up Timer Enable (PWRT disabled)
  #pragma config MCLRE = ON     // MCLR/VPP pin function is MCLR
  #pragma config CP = OFF       // Code protection is disabled
  #pragma config CPD = OFF      // Data memory code protection disabled
  #pragma config BOREN = ON     // Brown-out Reset Enable
  #pragma config CLKOUTEN = OFF // Clock Out Enable (off)
  #pragma config IESO = OFF     // Internal/External Switchover (off)
  #pragma config FCMEN = OFF    // Fail-Safe Clock Monitor Enable (off)

/* CONFIG2 */
  #pragma config WRT = OFF      // Write protection off
  #pragma config PLLEN = OFF    // PLL Enable (4x PLL disabled)
  #pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable
  #pragma config BORV = LO      // Brown-out Reset Low Trip Point
  #pragma config LVP = ON       // Low-Voltage Programming Enable


  #include <xc.h>

  #define _XTAL_FREQ 8000000

/************************************************************************
 *   hardware                                                           *
 ************************************************************************/

   #define clk       LATC0      // 5110 'clk' pin, SPI 'SCK'
   #define dc        LATC1      // 5110 'dc' pin
   #define dat       LATC2      // 5110 'dat' pin, SPI 'SDO' ('MOSI')
   #define ce        LATC3      // 5110 'ce' pin
   #define rst       LATC4      // 5110 'reset' input

/************************************************************************
 *                                                            12 words  *
 ************************************************************************/
   void putwreg()                   // bank 0 (inserted by compiler)  |00
   { PIR1bits.SSP1IF = 0;           // clear the MSSP interrupt flag  |00
   //asm("banksel LATC          "); // bank 2 (inserted by compiler)  |02
     ce = 0;                        // spi enable on                  |02
     asm("banksel SSP1BUF       "); // bank 4                         |04
     asm("movwf SSP1BUF         "); // send byte                      |04
   //asm("banksel PIR1          "); // bank 0 (inserted by compiler)  |00
     while(!PIR1bits.SSP1IF);       // wait for MSSP interrupt flag   |00
   //asm("banksel LATC          "); // bank 2 (inserted by compiler)  |02
     ce = 1;                        // spi enable off                 |02
   }

/************************************************************************
 *                                                                      *
 ************************************************************************/
   void putcmd(char cmd)            // bank 2 (inserted by compiler)  |02
   { dc = 0;                        // set lcd 'command' mode         |02
     asm("call  _putwreg       ");  //                                |02
   }

/************************************************************************
 *                                                                      *
 ************************************************************************/
   void rdflash()                   //
   { asm("banksel EECON1       ");  // bank 3                         |03
     asm("bcf   EECON1,6       ");  // CFGS = 0 (not config)          |03
     asm("bsf   EECON1,7       ");  // EEPGD = 1 (program memory)     |03
     asm("bsf   EECON1,0       ");  // RD = 1 (initiate read)         |03
     asm("nop                  ");  // required nop                   |03
     asm("nop                  ");  //  "                             |03
     asm("incf  EEADRL,F       ");  // bump EEADR                     |03
     asm("rlf   EEDATL,W       ");  // move b7 into Carry             |03
     asm("rlf   EEDATH,W       ");  // wreg = the 7 bit hi byte       |03
     asm("bcf   EEDATL,7       ");  // eedatl = the 7 bit lo byte     |03
   }                                //

/************************************************************************
 *                                                                      *
 ************************************************************************/
   void wrchar(char ascii)          //
   { dc = 1;                        // set lcd 'data' mode            |02
     asm("addlw -32            ");  // ascii 32..127 minus offset     |02
     asm("banksel wrchar@ascii ");  // bank 0 ?                       |00
     asm("movwf wrchar@ascii,F ");  // font array index, 0..95        |00
     asm("lsrf  wrchar@ascii,W ");  // int(ascii *= 2.5) -> 0..237    |00
     asm("addwf wrchar@ascii,W ");  //  "                             |00
     asm("addwf wrchar@ascii,W ");  //  "                             |00
     asm("banksel EEADRL       ");  // bank 3                         |03
     asm("movwf EEADRL         ");  // flash address lo               |03
     asm("movlw Font5x7/256    ");  //                                |03
     asm("movwf EEADRH         ");  // flash address hi               |03
/*                                                                      *
 *   Extract five bytes of pattern data from three memory words. An     *
 *   even character uses word 0 hi + lo, 1 hi + lo, and 2 hi while      *
 *   odd characters use word 0 lo, 1 hi + lo, and 2 hi + lo.  A 6th     *
 *   blank (zero) byte is sent for inter-character spacing.             *
 *                                                                      */
     asm("call  _rdflash       ");  // read 1st word (2 bytes)        |03
     asm("banksel wrchar@ascii ");  // bank 0                         |00
     asm("btfss wrchar@ascii,0 ");  // odd char? yes, skip, else      |00
     asm("call  _putwreg       ");  // send hi byte (even character)  |00
     asm("banksel EEDATL       ");  // bank 3                         |03
     asm("movf  EEDATL,W       ");  //                                |03
     asm("call  _putwreg       ");  // send lo byte                   |00
     asm("call  _rdflash       ");  // read 2nd word (2 bytes)        |03
     asm("call  _putwreg       ");  // send hi byte                   |00
     asm("banksel EEDATL       ");  // bank 3                         |03
     asm("movf  EEDATL,W       ");  //                                |03
     asm("call  _putwreg       ");  // send lo byte                   |00
     asm("call  _rdflash       ");  // read 3rd word (2 bytes)        |03
     asm("call  _putwreg       ");  // send hi byte                   |00
     asm("banksel EEDATL       ");  // bank 3                         |03
     asm("movf  EEDATL,W       ");  //                                |03
     asm("banksel wrchar@ascii ");  // bank 0                         |00
     asm("btfsc wrchar@ascii,0 ");  // even char? yes, skip, else     |00
     asm("call  _putwreg       ");  // send lo byte (odd characters)  |00
     asm("movlw 0              ");  //                                |00
     asm("call  _putwreg       ");  // send blank 6th column          |00
   }

/************************************************************************
 *                                                                      *
 ************************************************************************/
   void putstr(const char *str)     // put 'ROM' strings
   { while(*str)                    //
       wrchar(*str++);              //
   }                                //

/************************************************************************
 *   main setup                                                         *
 ************************************************************************/
   void main(void)
   { ANSELA = 0;                    // Analog off (digital I/O)
     ANSELC = 0;                    //  "
     TRISA = 0;                     //
     TRISC = 0;                     //
     OSCCON = 0b01110000;           // set INTOSC to 8-MHz
 /*                                                                     *
  *  initialize MSSP module SPI mode 0 (CKE=1/CKP=0) & 500-kHz clock    *
  *                                                                     */
     SSP1STAT = 0x40;               // CKE = 1
     SSP1CON1 = 0x21;               // SPI Master, Fosc/16, CKP = 0
 /*                                                                     *
  *  initialize Nokia 5110 LCD display                                  *
  *                                                                     */
     __delay_ms(30);                //
     rst = 0; rst = 1;              // 5110 'reset' pulse
     putcmd(0x20+0x01);             // function set: ext instructions
     putcmd(0x80+0x30);             // set Vop (contrast), 0..127
     putcmd(0x04+0x02);             // set temperature coefficient, 0..3
     putcmd(0x10+0x03);             // Set bias system, 0..7
     putcmd(0x20+0x00);             // function set: std instructions
     putcmd(0x08+0x04);             // display control: normal mode
 /*                                                                     *
  *  test the lcd print functions                                       *
  *                                                                     */
     putcmd(0x80+0x20);             // set DDRAM X address, 0..83
     putcmd(0x40+0x02);             // set DDRAM Y address, 0..5
     wrchar('R');                   //
     putstr("eady");                //

/************************************************************************
 *   main loop                                                          *
 ************************************************************************/
     while(1)
     {                              //
     }                              //
   }                                //

/************************************************************************
 *   Packed 96 character 5x7 Font, 2.5-words-per-character, 240 words   *
 ************************************************************************/
   #asm
   PSECT myFonts, class=CODE, abs, ovrld, space=0, delta=2
     ORG 700h
   Font5x7:
     dw 0x0000, 0x0000, 0x0000, 0x005F, 0x0000     ;  32 ' '  '!'
     dw 0x0007, 0x0007, 0x0014, 0x3F94, 0x3F94     ;  34 '"'  '#'
     dw 0x122A, 0x3FAA, 0x0923, 0x0988, 0x3262     ;  36 '$'  '%'
     dw 0x1B49, 0x2AA2, 0x2800, 0x0283, 0x0000     ;  38 '&'  '''
     dw 0x001C, 0x1141, 0x0000, 0x20A2, 0x0E00     ;  40 '('  ')'
     dw 0x0A08, 0x1F08, 0x0A08, 0x043E, 0x0408     ;  42 '*'  '+'
     dw 0x0050, 0x1800, 0x0008, 0x0408, 0x0408     ;  44 ','  '-'
     dw 0x0060, 0x3000, 0x0020, 0x0808, 0x0202     ;  46 '.'  '/'
     dw 0x1F51, 0x24C5, 0x1F00, 0x217F, 0x2000     ;  48 '0'  '1'
     dw 0x2161, 0x28C9, 0x2321, 0x20C5, 0x25B1     ;  50 '2'  '3'
     dw 0x0C14, 0x097F, 0x0827, 0x22C5, 0x22B9     ;  52 '4'  '5'
     dw 0x1E4A, 0x24C9, 0x1801, 0x3889, 0x0283     ;  54 '6'  '7'
     dw 0x1B49, 0x24C9, 0x1B06, 0x24C9, 0x149E     ;  56 '8'  '9'
     dw 0x0036, 0x1B00, 0x0000, 0x2B36, 0x0000     ;  58 ':'  ';'
     dw 0x0414, 0x1141, 0x0014, 0x0A14, 0x0A14     ;  60 '<'  '='
     dw 0x0041, 0x1114, 0x0402, 0x00D1, 0x0486     ;  62 '>'  '?'
     dw 0x1949, 0x3CC1, 0x1F7E, 0x0891, 0x08FE     ;  64 '@'  'A'
     dw 0x3FC9, 0x24C9, 0x1B3E, 0x20C1, 0x20A2     ;  66 'B'  'C'
     dw 0x3FC1, 0x20A2, 0x0E7F, 0x24C9, 0x24C1     ;  68 'D'  'E'
     dw 0x3F89, 0x0489, 0x00BE, 0x20C9, 0x24FA     ;  70 'F'  'G'
     dw 0x3F88, 0x0408, 0x3F80, 0x20FF, 0x2080     ;  72 'H'  'I'
     dw 0x1040, 0x20BF, 0x00FF, 0x0414, 0x1141     ;  74 'J'  'K'
     dw 0x3FC0, 0x2040, 0x207F, 0x010C, 0x017F     ;  76 'L'  'M'
     dw 0x3F84, 0x0410, 0x3FBE, 0x20C1, 0x20BE     ;  78 'N'  'O'
     dw 0x3F89, 0x0489, 0x033E, 0x20D1, 0x10DE     ;  80 'P'  'Q'
     dw 0x3F89, 0x0CA9, 0x2346, 0x24C9, 0x24B1     ;  82 'R'  'S'
     dw 0x0081, 0x3F81, 0x00BF, 0x2040, 0x203F     ;  84 'T'  'U'
     dw 0x0FA0, 0x2020, 0x0FBF, 0x2038, 0x203F     ;  86 'V'  'W'
     dw 0x3194, 0x0414, 0x3187, 0x0470, 0x0407     ;  88 'X'  'Y'
     dw 0x30D1, 0x24C5, 0x2180, 0x3FC1, 0x2080     ;  90 'Z'  '['
     dw 0x0104, 0x0410, 0x1000, 0x20C1, 0x3F80     ;  92 '\'  ']'
     dw 0x0202, 0x0082, 0x0240, 0x2040, 0x2040     ;  94 '^'  '_'
     dw 0x0001, 0x0104, 0x0020, 0x2A54, 0x2A78     ;  96 '`'  'a'
     dw 0x3FC8, 0x2244, 0x1C38, 0x2244, 0x2220     ;  98 'b'  'c'
     dw 0x1C44, 0x2248, 0x3FB8, 0x2A54, 0x2A18     ; 100 'd'  'e'
     dw 0x047E, 0x0481, 0x010C, 0x2952, 0x293E     ; 102 'f'  'g'
     dw 0x3F88, 0x0204, 0x3C00, 0x227D, 0x2000     ; 104 'h'  'i'
     dw 0x1040, 0x223D, 0x007F, 0x0828, 0x2200     ; 106 'j'  'k'
     dw 0x0041, 0x3FC0, 0x007C, 0x0218, 0x0278     ; 108 'l'  'm'
     dw 0x3E08, 0x0204, 0x3C38, 0x2244, 0x2238     ; 110 'n'  'o'
     dw 0x3E14, 0x0A14, 0x0408, 0x0A14, 0x0C7C     ; 112 'p'  'q'
     dw 0x3E08, 0x0204, 0x0448, 0x2A54, 0x2A20     ; 114 'r'  's'
     dw 0x023F, 0x2240, 0x103C, 0x2040, 0x107C     ; 116 't'  'u'
     dw 0x0E20, 0x2020, 0x0E3C, 0x2030, 0x203C     ; 118 'v'  'w'
     dw 0x2228, 0x0828, 0x220C, 0x2850, 0x283C     ; 120 'x'  'y'
     dw 0x2264, 0x2A4C, 0x2200, 0x0436, 0x2080     ; 122 'z'  '{'
     dw 0x0000, 0x3F80, 0x0000, 0x20B6, 0x0400     ; 124 '|'  '}'
     dw 0x0808, 0x0410, 0x0478, 0x2341, 0x2378     ; 126 '~'  ''

#endasm
/************************************************************************/
This is the 5x7 font I'm using;

Font Viewer 5x7.png
 

Ian Rogers

Joined Dec 12, 2012
662
I have re-read this several times... You may be looking in the wrong place.... These are different pointers.. You have a ROM pointer and a RAM pointer, so one cannot destroy the other ( In theory ) It looks to me like there is no const pointer!! I run this on the simulator and I get garbage.

I have tried "rom const" but get errors...I also tried a unique label ( putstr may be defined ) but still no avail!!
 

Thread Starter

MMcLaren

Joined Feb 14, 2010
842
Here's the putstr() function code. XC8 assigned the 'str' pointer to RAM locations 70h and 71h.
Code:
   484  069C                     _putstr:  
   485  069C                     l569:  
   486                           ;incstack = 0
   487                           ; Regs used in _putstr: [wreg-fsr0h+status,2+status,0+pclath+cstack]
   488                          
   489  069C  0870                  movf    putstr@str,w              '        movf    str+0,W
   490  069D  0084                  movwf    4                        '        movwf   FSR0L
   491  069E  0871                  movf    putstr@str+1,w            '        movf    str+1,W
   492  069F  0085                  movwf    5                        '        movwf   FSR0H
   493  06A0  0012                  moviw fsr0++                      '        moviw   fsr0++
   494  06A1  1903                  btfsc    3,2                      '        skpnz
   495  06A2  0008                  return                            '        return
   496  06A3  0870                  movf    putstr@str,w              '        movf    str+0,W
   497  06A4  0084                  movwf    4                        '        movwf   FSR0L
   498  06A5  0871                  movf    putstr@str+1,w            '        movf    str+1,W
   499  06A6  0085                  movwf    5                        '        movwf   FSR0H
   500  06A7  0800                  movf    0,w                       '        movf    INDF0,W
   501  06A8  26AE                  fcall    _wrchar                  '        fcall   wrchar
   502  06A9  3001                  movlw    1                        '        movlw   1
   503  06AA  07F0                  addwf    putstr@str,f             '        addwf   str+0,F
   504  06AB  3000                  movlw    0                        '        movlw   0
   505  06AC  3DF1                  addwfc    putstr@str+1,f          '        addwfc  str+1,F
   506  06AD  2E9C                  goto    l569                      '
   507  06AE                     __end_of_putstr:
Here's the beginning section of the wrchar() function. XC8 assigned the 'ascii' parameter to RAM location 70h.
Code:
   544  06AE                     _wrchar:   
   545                           
   546                           ;incstack = 0
   547                           ; Regs used in _wrchar: [wreg]
   548  06AE  0022                  movlb    2    ; select bank2
   549  06AF  148E                  bsf    14,1    ;volatile
   550  06B0  3EE0                  addlw    -32    ;# 
   551  06B1  0020                  banksel    wrchar@ascii    ;# 
   552  06B2  00F0                  movwf    wrchar@ascii    ;# 
   553  06B3  3670                  lsrf    wrchar@ascii,w    ;# 
   554  06B4  0770                  addwf    wrchar@ascii,w    ;# 
   555  06B5  0770                  addwf    wrchar@ascii,w    ;#
Since the putstr() function calls wrchar(), the putstr@str pointer gets corrupted. Why isn't XC8 using unique RAM locations for these parameter variables?

TIA. Cheerful regards, Mike
 

Ian Rogers

Joined Dec 12, 2012
662
One thing that will fix it... The variable ASCII is already in the wreg, so you could just work on the that..

When your code compiles there are two warnings ( well at least that matters ) ... wrchar@ascii not used and putcmd@cmd is not used..
But as you are using wrchar@ascii, it points me to a compiler and linker out of sync... The 'R' and the 'e' do print....so as a workaround you can save the pointer and retrieve it after before the increment.. I know this isn't what you want, but the XC8 documentation said you have it correct..
 

Ian Rogers

Joined Dec 12, 2012
662
This worked..

C:
void putstr( const char *str)  // put 'ROM' strings
  {
   const char *tmp;
   while(*str) {
      tmp = str;  //
      wrchar(*str);
      str = tmp;
      str++;
     }    //
}
 

Thread Starter

MMcLaren

Joined Feb 14, 2010
842
Thanks, Ian.

Thank you. I have a couple work-arounds, too, but I'd still like to discover the cause of this behavior. I've been reading for hours and still haven't figured it out.

This program is based on a "working" version that I wrote in BoostC but I'd like to move away from BoostC in favor of XC8.

Take care... Cheerful regards, Mike
 

Ian Rogers

Joined Dec 12, 2012
662
The reason it's happening is because those two variables are being optimised out... The FSR will still contain 0x70 from the last operation.

What beats me is even if I make the variables volatile ( should fix it) the compiler doesn't whinge any more but still it doesn't create a static pointer for putstr... I can't get my head around it either... This is a question for the XC8 forum on MicroChip.... Have you posted it there?
 

Ian Rogers

Joined Dec 12, 2012
662
I have analysed the data stack... It's only 70 bytes!! It would appear that the stack is corrupting the data as the stack doesn't increase when wrchar is called from putstr thus the existing data is overwritten.. I can't find out how to "up" the size of the stack..
 
Top