1

I am new to C programming and microcontrollers. I am using a PIC18F24K20 microcontroller with C18. I have it set up to receive information from a computer input using USART transmit and receive functions. My goal is to compare the received word against known words, and transmit something back to the computer based on what word was received. Below is the relevant code.

#include "p18f24k20.h"
#include "delays.h"
#include "string.h"
#include "stdlib.h"


void CommTransmit ( rom char * );

void main (void)
{
    char buf[11], data, T;
    int i;

    i = 0;
    memset(buf, 0, sizeof buf);

    while(1)
    {
        if (PIR1bits.RCIF)
        {
            data = USART_receive();
            if (data != 47)             // 47 is /, indicates end of string
            {
                buf[i] = data;
                i++;
            }
            else
            {
                // T = strcmppgm2ram(buf,(const far rom char*)"test");
                CommTransmit(buf);
                USART_transmit('t');
                buf[0] = 0'
            }
        }
    }
}


void CommTransmit ( rom char *CommVariable )
{
    char test;

    test = strcmppgm2ram(CommVariable, (const far rom char*)"test");
    if (test == 0)
    {
        USART_transmit('g');
    }
}

The code is currently set up to test to try to determine what is wrong. If I run it as is, the computer will receive a 't', as if the microcontroller ran through the CommTransmit function. However, it never transmits the 'g'. Even if I put a USART_transmit('g') call in the CommTransmit function, outside of and after the if statement, it never gets called (like it gets stuck in the strcmppgm2ram function?) but yet it still transmits the 't'.

It is also strange because if I put a break at the CommTransmit function and run through line by line, it seems to work properly. However, if I watch the CommVariable inside MPLAB IDE, it is never what it supposed to be (though the 'buf' variable prior to being called into the function is correct). From what I can tell, the value of CommVariable when I watch it depends on the size of the array.

From reading, I think it may caused by how the microcontroller stores the variable (program vs data memory?) but I'm not sure. Any help is greatly appreciated!

edit: I should also add that if I uncomment the T = strcmppgm2ram line in the else statement before the CommTransmit line, it works properly (T = 0 when the two strings are the same). I believe the array changes when I pass it through the function, which causes the strcmppgm2ram function to not work properly.

10
  • Hi. I haven't programmed on C18 (but have on other embedded systems); but I'm suspicious of (const far rom char*)"test". If the string literal is not in the right area of memory then this cast won't move it, it'll just send a bogus pointer. What happens without the cast? Commented Apr 10, 2014 at 13:53
  • BTW check that i < 11 in the data != 47 case Commented Apr 10, 2014 at 13:54
  • 1
    Given the seemingly random behavior, it sounds like you have some memory-related bug somewhere. Some pointer or array bug corrupting memory, perhaps in strcmppgm2ram(). Is that a user-defined function or some library one? Also since this is a PIC, stack overflow is always a likely candidate. Commented Apr 10, 2014 at 13:55
  • @lundin strcmppgm2ram() is a library function. Here is what the string.h file says about it: signed char strcmppgm2ram (auto const char s1, auto const MEM_MODEL rom char *s2); /* name strcmpram2pgm * The {\bf strcmpram2pgm} function performs a {\bf strcmp} where {\bf s1} * points to program memory and {\bf s2} point to data memory. * param s1 pointer to string in program memory * param s2 pointer to string in data memory */ Commented Apr 10, 2014 at 14:35
  • 1
    The parameter of the CommTransmit funtion is suspicious. Why is it rom? You are passing it a variable on the stack. (In general, I prefer to declare buffers outside of main to avoid using the stack at all.) Commented Apr 10, 2014 at 16:36

1 Answer 1

1

Looking at signature for strcmppgm2ram

signed char strcmppgm2ram(const char * str1, const rom char * str2 );

I don't understand why do you have rom char * for CommVariable. From chapter 2.4.3 ram/rom Qualifiers of MPLAB® C18 C Compiler User’s Guide

Because the PICmicro microcontrollers use separate program memory and data memory address busses in their design, MPLAB C18 requires extensions to distinguish between data located in program memory and data located in data memory. /---/ Pointers can point to either data memory (ram pointers) or program memory (rom pointers). Pointers are assumed to be ram pointers unless declared as rom.

And in 2.7.3 String Constants:

An important consequence of the separate address spaces for MPLAB C18 is that pointers to data in program memory and pointers to data in data memory are not compatible. /---/ because they refer to different address spaces. /---/ MPLAB C18 automatically places all string constants in program memory. This type of a string constant is “array of char located in program memory”, (const rom char []).

And also it's not clear the purpose of type casting to const far rom char* for the second argument. That may cause stack corruption because far pointer has bigger size (24 bits). So, it looks like it should be rewritten as:

void CommTransmit (const char *CommVariable )
{
    if (!strcmppgm2ram(CommVariable, "test")) {
         USART_transmit('g');
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.