Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] PIC18F4550 unable to do per-byte addressing (mikroC PRO)

Status
Not open for further replies.

K33rg4t3

Full Member level 3
Joined
Aug 2, 2015
Messages
165
Helped
7
Reputation
14
Reaction score
7
Trophy points
1,298
Activity points
2,607
Hey
I have a strange issue.
Take a look:

Code:
typedef struct 
{
       char data[4];
} TEST;

void doTest(char *data)
{
        char txt[64];
        TEST *p;

        UART1_Write(data); // writes ABC

      p = (TEST*)data;
      sprintf(txt,"%c %c",p->data[0], p->data[1]);
      UART1_Write(txt); // writes A C !!
     
}

Why am I having such strange issues with struct member access? I don't know what's wrong...
BTW: sizeof(TEST) = 4 ...
 

Why you use stack to allocate 64 bytes of char? This is an 8bit processor with limited capabilities.
sprintf is also a heavy function that need enough stack. It may corrupt it, so txt will contain garbage.

Put complete code (how is the doTest called?)
 

It is very bad practice for such type conversion.
p.data = data; - this way is correct
Also, be carefull with sizeof() macros. Never use it in routine where target array not declared.
 

The code is very long and includes USB stuff and such, but what I am basically trying to do is:
Code:
typedef struct 
{
         char engineRight;
         char engineLeft;
         char rotorA;
         char rotorB;
} MyState;

void OnNewState(char *data)
{
      char r, l, a, b;
      // the data contents are OK here, I have tested it with UART
      UART_Write(data);

      // here is bug...
      MyState *p = data;
      r = p->engineRight;
      l = p->engineLeft;
      a = p->rotorA;
      b = p->rotorB;
      // and now you see, using p->engineLeft is returning bad value for me...

       // rest of the code is not important
      //SetEngineLeft(r);
}
I've used structs in desktrop C for very long time and didn't had such issues....
 

Did it work in desktop PC without using
Code:
#pragma pack(1)
????
hmmm strange....


I cannot help you without the call of the function and the data allocation and filling before the call.
 

There's no way how the elements of a character array would be word aligned. In so far #pragma pack(1) shouln't be necessary with any compiler. MikroC doesn't provide it anyway.

Looks simply like a MikroC bug.
 

@FvM I am talking about struct:
Code:
typedef struct 
{
         char engineRight;
         char engineLeft;
         char rotorA;
         char rotorB;
} MyState;
in a desktop PC.
I doubt that it works without pragma pack.

Thread initiator, tries to pass a character array in a 4 bytes structure.
I am not convinced that the character array data are sequencial printable chars (eg. could be NUL char that the uart write function simply ignores).
Yes MicroC sucks but it would be trivial to have a look at this char array that is passed to the function before I put a blame on microC.
 

Not used this myself, but using Google, I see the "UARTx_write" function is used to send a single byte to the UART (https://www.mikroe.com/download/eng/documents/compilers/mikroc/pro/pic/help/uart_library.htm).
Therefore I would call into question the way it is being used in the code from the OP.
Further, if it actually supposed to write a character string (which the referenced document calls '"UARTx_write_text") then it would need a null terminator which is may or may not have when passed the struct.
How is the 'doTest' function begin called?
Susan
 

Sorry guys, but the previous snippets were pseudocode.

I have made a real test case now, please take a look and refer only to this:
Code:
typedef struct {
        char a;
        char b;
        char c;
        char d;
} TestStruct;

typedef struct {
        char arr[4];
} TestStruct2;
void main(void){
     TestStruct *ptr;
     TestStruct2 *ptr2;
     char buffer[64] = { 'A', 'B', 'C', 'D', 0 };
     char txt[64];
     

     ADCON1 |= 0x0F;                         // Configure all ports with analog function as digital
     CMCON  |= 7;                                  // Disable comparators

     // 25 is TX, 26 is RX
     UART1_Init(300);

     while(1)
     {
           Delay_ms(1000);
           sprintf(txt,"Sizeof struct is %i\n\r",sizeof(TestStruct));
           UART1_Write_Text(txt);
           Delay_ms(1000);
           ptr = (TestStruct*)buffer;
           sprintf(txt,"Members: a %c, b %c, c %c, d %c\n\r",ptr->a,ptr->b,ptr->c,ptr->d);
           UART1_Write_Text(txt);
           Delay_ms(1000);
           ptr2 = (TestStruct2*)buffer;
           sprintf(txt,"Array in struct: [0] %c, [1] %c, [2] %c, [3] %c\n\r",ptr2->arr[0],ptr2->arr[1],ptr2->arr[2],ptr2->arr[3]);
           UART1_Write_Text(txt);
           Delay_ms(1000);
           sprintf(txt,"Raw: %s\n\r",buffer);
           UART1_Write_Text(txt);
     }
     
}
Screenshot from my IDEs (Pickit2 programmer, mikroC IDE, and RealTerminal for debugging):
ides.png
Config bits (but I think they are unrelated to the problem):
configbits.png
IDE version:
ideversion.png

The output:
Code:
Raw: ABCD                                 
Sizeof struct is 4                             
Members: a A, b C, c , d         
Array in struct: [0] A, [1] C, [2] , [3] 


Please help, as you see, in both cases (struct with separate four "char" members and struct with char arr[4] member) the second member is 'C', but it should be 'B'...)
 
Last edited:

I have some news for you that you (amond others) may not like.
I simplified and decresed size of code and MicroC works correctly:
Code:
typedef struct {
        char a;
        char b;
        char c;
        char d;
} TestStruct;

typedef struct {
        char arr[4];
} TestStruct2;


void dbg(char index,char a,char b,char c,char d){
//        UART_Write(a);
  //      UART_Write(b);
    //    UART_Write(c);
      //  UART_Write(d);
        //UART_Write('\n');
        _asm nop;
}

void main(void){
     TestStruct *ptr;
     TestStruct2 *ptr2;
     char buffer[5] = { 'A', 'B', 'C', 'D', 0 };

     ADCON1 |= 0x0F;                         // Configure all ports with analog function as digital
     CMCON  |= 7;                                  // Disable comparators

     // 25 is TX, 26 is RX
     //UART1_Init(300);

     while(1)
     {
           Delay_ms(1000);
           dbg(1,'s','z',' ',sizeof(TestStruct)+'0');
           Delay_ms(1000);
           ptr = (TestStruct*)buffer;
           dbg(2,ptr->a,ptr->b,ptr->c,ptr->d);
           Delay_ms(1000);
           ptr2 = (TestStruct2*)buffer;
           dbg(3,ptr2->arr[0],ptr2->arr[1],ptr2->arr[2],ptr2->arr[3]);
           Delay_ms(1000);
           dbg(4,buffer[0],buffer[1],buffer[2],buffer[3]);
     }
}

Results:
x4.JPG

Both redefinitions to structs defined works well.

So what is the problem?
One of the bellow (I can narrow down, but I'd rather not):
a) you use too much stack!!! I am not sure if microC can handle it.
b) sprintf takes a lot of stack too. Remove it and will help a lot.
c) you have not bought microC. The cracked version ON PURPOSE swaps assembly code pieces to produce strange results.
 
Thank you for in-depth test, but you have omitted one thing.

I have also used debugger now, here is my code:

Code:
typedef struct {
        char a;
        char b;
        char c;
        char d;
} TestStruct;

typedef struct {
        char arr[4];
} TestStruct2;
void dbg(char a, char b, char c, char d)
{
 _asm nop;
}
void main(void){
     TestStruct *ptr;
     TestStruct2 *ptr2;
     char buffer[64] = { 'A', 'B', 'C', 'D', 0 };
     char txt[64];
     char a, b, c, d;

     ADCON1 |= 0x0F;                         // Configure all ports with analog function as digital
     CMCON  |= 7;                                  // Disable comparators

     // 25 is TX, 26 is RX
     UART1_Init(300);

     while(1)
     {
           ptr = (TestStruct*)buffer;
           // OK -  a, b, c, d are 'A', 'B', 'C' and 'D'
           a = ptr->a;
           b = ptr->b;
           c = ptr->c;
           d = ptr->d;
           // OK: variables in function are  'A', 'B', 'C' and 'D'
           dbg(a,b,c,d);
           // ERROR: txt contents are A,C, garbage...
           sprintf(txt,"%c%c%c%c\n\r",a,b,c,d);
     }
}
Results: only the sprintf output is broken, which is stored in txt variable value.
And you didn't test sprintf.
Can you also test sprintf function?

Here is the screenshot from debugger:
anothertest.png
 

Results: only the sprintf output is broken, which is stored in txt variable value.
Suggests that the problem hasn't anything to do with structures or arrays. It would be approriate to mention the mikroC version. Are you running the latest version?
 

microC with sprintf exceeds demo limit (2Kbytes) so I cannot test.

mplab 8.6x with mcc18 demo works fine:
x5.jpg

- - - Updated - - -


As I can see you still use 128 bytes of stack in txt and buffer arrays. Try to reduce it to absolutely necessary...and see what happens
 

Changed to 8 bytes, and the bug is still here.

I have really no idea what's wrong, maybe it's because I'm also including USB library?

- - - Updated - - -

Suggests that the problem hasn't anything to do with structures or arrays. It would be approriate to mention the mikroC version. Are you running the latest version?

please take a look at the IDEs screenshot, here is the version
 


Won't multiple sprintf() calls solve the problem?
Code:
sprintf(txt,"%c%",a);
sprintf(strend(txt),"%c",b);
sprintf(strend(txt),"%c",d);
sprintf(strend(txt),"%c\n\r",d);
 

Won't multiple sprintf() calls solve the problem?
Code:
sprintf(txt,"%c%",a);
sprintf(strend(txt),"%c",b);
sprintf(strend(txt),"%c",d);
sprintf(strend(txt),"%c\n\r",d);

It works:
Code:
typedef struct {
        char a;
        char b;
        char c;
        char d;
} TestStruct;

typedef struct {
        char arr[4];
} TestStruct2;
void dbg(char a, char b, char c, char d)
{
 _asm nop;
}
char * strend(char *p)
{
 while(*p)
 p++;
 return p;
}
void main(void){
     TestStruct *ptr;
     TestStruct2 *ptr2;
     char buffer[8] = { 'A', 'B', 'C', 'D', 0 };
     char txt[8];
     char a, b, c, d;

     ADCON1 |= 0x0F;                         // Configure all ports with analog function as digital
     CMCON  |= 7;                                  // Disable comparators

     // 25 is TX, 26 is RX
     UART1_Init(300);

     while(1)
     {
           ptr = (TestStruct*)buffer;
           // OK -  a, b, c, d are 'A', 'B', 'C' and 'D'
           a = ptr->a;
           b = ptr->b;
           c = ptr->c;
           d = ptr->d;
           // OK: variables in function are  'A', 'B', 'C' and 'D'
           dbg(a,b,c,d);
// FvM work around
         sprintf(txt,"%c%",a);
        sprintf(strend(txt),"%c",b);
        sprintf(strend(txt),"%c",c);
        sprintf(strend(txt),"%c\n\r",d);
     }
     
}
workarounddd.png

- - - Updated - - -

.. but I want a real solution to the problem, not a work-around
 

...but I want a real solution to the problem, not a work-around
No problem, get the bug fixed by mikroE or use a industry-standard PIC compiler, e.g. XC8.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top