Hot!PIC16F1503 stopping on memcpy

Author
Geomancer
New Member
  • Total Posts : 8
  • Reward points : 0
  • Joined: 2018/01/16 01:08:45
  • Location: 0
  • Status: offline
2018/02/14 15:42:54 (permalink)
0

PIC16F1503 stopping on memcpy

Hello all,
 
Having a hard time figuring out why my PIC16F1503 is stalling (freezing, crashing?) on a memcpy statement. I don't have a debug header, so I'm forced to rely on basic debugging and the simulator. I narrowed it down to this statement by moving a LATA write around that turns on an LED until it no longer worked.
 
In the simulator I'm not seeing any issues, it runs fine and does exactly what I expect it to.
 
This happens within my Init function, which is the very first thing in main so there shouldn't be anything executing before this.
 
Wondering if any of you experts here could give me some ideas on what could be causing it to stop. I thought maybe an interrupt, but even with GIE disabled it fails to get past that statement.
 
Thank you!
 
#include <pic16f1503.h>
#include <xc.h>
#include <string.h>

extern volatile char lcd_buffer[21];

void Init(void){
    // Set Processor Frequency
    // OSCCON - Oscillator Control Register

    OSCCON = 0b01101000;
 
    // Set Data Port Input/Output
    ANSELA = 0x00; // Turn off Analog Input functionality
    LATA = 0x00; // Set default Port A output values
    TRISA = 0x23; // Set bits 2 and 4 as output
    
    ANSELC = 0x00; // Turn off Analog Input functionality
    TRISC = 0xFF; // Set all of Port C as input
    
    // Configure I2C Registers
    
    // SSP1STAT - SSP Status Register
    SSP1CON1 = 0x28;
    
    // SSP1CON2 - SSP Control Register 2
    SSP1CON3 = 60;
    
    // SSP1ADD - MSSP Address and Baud Rate Register
    SSP1ADD = 0x09;
    
    // Enable MSSP (I2C) Interrupts
    PIE1bits.SSP1IE = 1;
    
    // Enable Global Interrupts
    INTCONbits.GIE = 1;
    INTCONbits.PEIE = 1;
    
    // Initialize the LCD
    const uint8_t lcd_init1[] = {0x00,0x38,0x39,0x14,0x78,0x5E,0x6D};
    memcpy(lcd_buffer,lcd_init1,7);

    // More code follows, but this is where the LATA command fails to execute

}

#1

8 Replies Related Threads

    jack@kksound
    code tags!
    • Total Posts : 2450
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: PIC16F1503 stopping on memcpy 2018/02/14 16:09:03 (permalink)
    0
    OK you have a declaration for lcd_buffer:
    extern volatile char lcd_buffer[21];

    but where is the definition of this variable?
    Basically, declarations (anytime you use extern it is a declaration) DO NOT allocate memory only the definition does that. Somewhere you need:
    volatile char lcd_buffer[21];

     
    #2
    jtemples
    Super Member
    • Total Posts : 10691
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: PIC16F1503 stopping on memcpy 2018/02/14 16:09:25 (permalink)
    0
    Where is lcd_buffer defined?  I wouldn't expect your code to link in its current state.
    #3
    Geomancer
    New Member
    • Total Posts : 8
    • Reward points : 0
    • Joined: 2018/01/16 01:08:45
    • Location: 0
    • Status: offline
    Re: PIC16F1503 stopping on memcpy 2018/02/14 16:13:08 (permalink)
    0
    The init function is in it's own c file.
     
    lcd_buffer is defined in main, along with some other global variables used by the ISR.
     
    Here is the main file.
     
     
    // Include PIC16F1503 CONFIG register settings
    // These control clock selection, watchdog disable, etc
    #include "pic16f1503config.h"

    // Compiler include file
    #include <xc.h>

    // C Standard Includes
    #include <stdint.h>
    #include <string.h>

    // Project Specific Includes
    #include "Init.h"
    #include "lcd_funcs.h"
    #include "AlarmClock.h"


    // Global Variables
    volatile l_state lcd_state;
    volatile uint8_t msg_length;
    volatile unsigned char *lcd_msg;
    uint8_t i2c_addr;
    volatile char lcd_buffer[21];

    void main(void) {
        // Initialization of MCU & peripherals
        Init();
        
        while(1){
            // The main loop of the program runs forever
            lcd_buffer[0]=0x40;
            const char testmsg[] = "This is a test";
            memcpy(lcd_buffer+1,testmsg,14);
            send2lcd(lcd_buffer,15,lcd_w);
            while(1){
                // Basically stop for test
            }
        }
        return;
    }

    void interrupt pic16_int (void) {
        if(SSP1IF == 1){
            // If MSSP module generated the interrupt, clear the flag and process
            LATA = 0x10;
            SSP1IF = 0;
            switch(lcd_state) {
                case lcd_idle:
                    // Do Nothing
                    break;
                case lcd_start:
                    // Start Condition Completed, send address
                    SSP1BUF = i2c_addr;
                    // Then go to next state
                    if(i2c_addr & 0x01){
                        // LSB '1' = TX
                        lcd_state = lcd_rx;
                    } else {
                        // LSB '0' = RX
                        lcd_state = lcd_tx;
                    }
                    break;
                case lcd_tx:
                    // Loading buffer starts transmission
                    SSP1BUF = *lcd_msg;
                    lcd_msg++;
                    msg_length--;
                    if(msg_length == 0){
                        lcd_state = lcd_stop;
                    }
                    break;
                case lcd_rx:
                    // Grab received byte
                    break;
                case lcd_stop:
                    // Set Stop Bit
                    SSP1CON2bits.PEN = 1;
                    lcd_state = lcd_finish;
                    break;
                case lcd_finish:
                    // I2C Transaction is completed, go to idle
                    lcd_state = lcd_idle;
            }
        }
        return;
    }

    #4
    jack@kksound
    code tags!
    • Total Posts : 2450
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: PIC16F1503 stopping on memcpy 2018/02/14 16:21:08 (permalink)
    0
    just FYI you do not need this:
    #include <pic16f1503.h>
    #5
    jtemples
    Super Member
    • Total Posts : 10691
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: PIC16F1503 stopping on memcpy 2018/02/14 16:36:10 (permalink)
    0
    I wouldn't expect "const" to affect the generated code in that context, but try it without "const".
    #6
    Geomancer
    New Member
    • Total Posts : 8
    • Reward points : 0
    • Joined: 2018/01/16 01:08:45
    • Location: 0
    • Status: offline
    Re: PIC16F1503 stopping on memcpy 2018/02/14 17:12:17 (permalink)
    0
    const is what tells the compiler to put it into program memory vs RAM. Since the PIC16F1503 only has 128 bytes of RAM I'd like to avoid using it when possible.
     
    Regardless, I tried removing it but still gets stuck on that memcpy line.
    #7
    qɥb
    Monolothic Member
    • Total Posts : 2138
    • Reward points : 0
    • Joined: 2017/09/09 05:07:30
    • Location: Jupiter
    • Status: online
    Re: PIC16F1503 stopping on memcpy 2018/02/14 17:14:05 (permalink)
    0
    I'm surprised XC8 allowed you to define the variable there.
    It is a "C89" compiler, where variable definitions can only occur at the start of a block, before any executable code.
    Have you looked at the LST file output to see what assembler has been generated there?
     
     

    PicForum "it just works"
    #8
    Geomancer
    New Member
    • Total Posts : 8
    • Reward points : 0
    • Joined: 2018/01/16 01:08:45
    • Location: 0
    • Status: offline
    Re: PIC16F1503 stopping on memcpy 2018/02/14 17:43:36 (permalink)
    0
    I don't see anything immediately, but I'm not all that familiar with the PIC instruction set (I came from HC08's).
     
       831 ;Init.c: 76: const uint8_t lcd_init1[] = {0x00,0x38,0x39,0x14,0x78,0x5E,0x6D};
       832 ;Init.c: 77: __builtin_memcpy(lcd_buffer,lcd_init1,7);
       833 006B 3020 movlw low (_lcd_buffer| 0)
       834 006C 0086 movwf 6
       835 006D 0187 clrf 7
       836 006E 3015 movlw low (Init@lcd_init1| (0+32768))
       837 006F 0084 movwf 4
       838 0070 3081 movlw high (Init@lcd_init1| (0+32768))
       839 0071 0085 movwf 5
       840 0072 3007 movlw 7
       841 0073 00F6 movwf ??_Init
       842 0074 0876 movf ??_Init,w
       843 0075 1903 skipnz
       844 0076 287B goto l635
       845 0077 u10m0:
       846 0077 0012 moviw fsr0++
       847 0078 001E movwi fsr1++
       848 0079 0BF6 decfsz ??_Init,f
       849 007A 2877 goto u10m0
       850 007B l635:
       851
       852 ;Init.c: 78: send2lcd(lcd_buffer,7,0x78);

     
    And the constant is here:
       507 psect stringtext2
       508 0115 __pstringtext2:
       509 0115 Init@lcd_init1:
       510 0115 3400 retlw 0
       511 0116 3438 retlw 56
       512 0117 3439 retlw 57
       513 0118 3414 retlw 20
       514 0119 3478 retlw 120
       515 011A 345E retlw 94
       516 011B 346D retlw 109
       517 011C __end_ofInit@lcd_init1:

    #9
    Jump to:
    © 2018 APG vNext Commercial Version 4.5