CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

PCM 3.205, 16F877A and bank 1

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Royce



Joined: 16 Jul 2004
Posts: 4

View user's profile Send private message

PCM 3.205, 16F877A and bank 1
PostPosted: Fri Jul 16, 2004 3:57 pm     Reply with quote

I'm pretty new to this compiler so I'm sure I'm missing something.

For some reason my compiler does not want to allocate anything in bank 1. It puts my two 96 bytes arrays in banks 2 & 3 happily and it fills bank 0 up with miscellaneous variables. But the symbol table shows nothing at all in bank 1 and I have a number of variables that need to go there.

Is this a bug or is there something special about bank 1?

Do I have to #byte all those variables in?

Thanks much,
Royce
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 16, 2004 4:24 pm     Reply with quote

In the 16F877A data sheet, look at Figure 2-3 which shows the
"Register File Map".
http://ww1.microchip.com/downloads/en/DeviceDoc/39582b.pdf
Notice how in banks 2 and 3, you can get a contiguous 96-byte block
without encroaching on the special 16-byte common area.
In bank 1, the most you can get is 80 bytes while preserving the
common ram area.

The compiler likes to put certain commonly used variables in that
special 16-byte area, because then it can access them without having
to set the bank select bits.

This is the reason why the compiler allocated memory in the manner
that you saw.
Royce



Joined: 16 Jul 2004
Posts: 4

View user's profile Send private message

PostPosted: Fri Jul 16, 2004 5:30 pm     Reply with quote

Its all small variables that it can't seem to find a home for. All my big arrays got spots.

Something else must be going on. After looking more carefully at the symbol file I found that there are in fact still free spots left in bank 0.

I moved some local variables that were not getting spots out of main() and into globals and magically they were given spots. Now, the setNodeDirection function parameters are not getting spots and there is still enough room left in bank 0 to hold them. What is really wierd is that none of the other function parameters even show up in the symbol file. Confused

If you don't mind would you look at this code and see if you can see what I'm doing wrong?

Thanks much,
Royce

Code:

#include <16F877A.h>


//too big to fit in memory, cache in ram and save out to flash?
//use actual RAM chip? (we will have to have the bus structure anyway for all the inputs.)
//cacheing wil require that you relocate the pointers
//prolly better to have only a single struct in local RAM at once

//alernate: delete dead nodes!!!
//need malloc for this struct
//bitpacked allocation tracker. block are all same size.
//can hold 24 entries



typedef int nodep;     //bit 7 indicates node is in nodes2
typedef unsigned traversep;    //bits 5 6 indicate traversal direction
typedef short bit;

struct bits_layout
{
   short      b0;
   short      b1;
   short      b2;
   short      b3;
   short      b4;
   short      b5;
   short      b6;
   short      b7;
};

union bitbyte_layout
{
   unsigned   data;
   struct bits_layout bits;
};

typedef union bitbyte_layout bitbyte;

struct snode
{
    unsigned         xy;              //bitpacked estimated grid coordinates
    nodep       directions[3];   //explored flag packed into bit 6
};

typedef struct snode node;

#define INCOMING        0
#define LEFT            1
#define STRAIGHT        2
#define RIGHT           3



traversep   traverse[48]; //bit pack direction at 5,6
unsigned traverse_top;
node    nodes1[24];
node    nodes2[24];
unsigned used_nodes1[3];
unsigned used_nodes2[3];


//I moved these from main() and they got spots????
    traversep prev_traverse;
    nodep orgnode, prev_node, tnode;
   unsigned tdir;
    bit backtracking;
    int newdirection;
   

nodep allocnode(int X, int Y)
{
    //try nodes1 then nodes2
    int idx, bitidx, tbit;
    for (idx = 0; idx < 3; idx++)
    {
        for(bitidx = 0; bitidx < 8; bitidx++)
        {
         tbit = (1 << bitidx);
            if (!(used_nodes1[idx] & tbit))
                return (8*idx + bitidx);
        }
    }
   
    for (idx = 0; idx < 3; idx++)
    {
        for(bitidx = 0; bitidx < 8; bitidx++)
        {
         tbit = (1 << bitidx);
            if (!(used_nodes2[idx] & tbit))
                return (8*idx + bitidx) + 128;
        }
    }
   
    return 255; //error out of memory
   
}
void freenode(nodep pNode)
{
   unsigned tval, tval2;
    if (!bit_test(pNode,7))
    {
      tval = (pNode & 8);
      tval = 2 ^ tval;
      tval = ~tval;
      tval2 = pNode >> 3;
        used_nodes1[tval2] &= tval;
    }
    else
    {
        pNode &= 127;
        tval = (pNode & 8);
      tval = 2 ^ tval;
      tval = ~tval;
      tval2 = pNode >> 3;
        used_nodes2[tval2] &= tval;
    }
}

int  getX(nodep pNode)
{
    if (!bit_test(pNode,7))
    {
        return nodes1[pNode].xy & 0b00001111;
    }
    else
    {
        pNode &= 127;
        return nodes2[pNode].xy & 0b00001111;
       
    }
}

int  getY(nodep pNode)
{
    if (!bit_test(pNode,7))
    {
        return (nodes1[pNode].xy & 0b11110000) >> 4;
    }
    else
    {
        pNode &= 127;
        return (nodes2[pNode].xy & 0b11110000) >> 4;
    }
}



void setX(nodep pNode, int new_x)
{
    new_x &= 0b00001111;
    if (!bit_test(pNode,7))
    {
        nodes1[pNode].xy |= new_x;
    }
    else
    {
        pNode &= 127;
        nodes2[pNode].xy |= new_x;
    }   
}

void setY(nodep pNode, int new_y)
{
    new_y = new_y << 4;
    if (!bit_test(pNode,7))
    {
        nodes1[pNode].xy |= new_y;
    }
    else
    {
        pNode &= 127;
        nodes2[pNode].xy |= new_y;
    }   
}



nodep getNodeDirection(nodep pNode, int direction)
{
    if (!bit_test(pNode,7))
    {
        return nodes1[pNode].directions[direction];
    }
    else
    {
        pNode &= 127;
        return nodes2[pNode].directions[direction];
    }   
}

//why are these parameters not getting spots?
//why do paramters from the other functions not even show up in the symbol file???
void setNodeDirection(nodep pNode, int direction, nodep pBranchNode)
{
    if (!bit_test(pNode,7))
    {
        nodes1[pNode].directions[direction] = pBranchNode;
    }
    else
    {
        pNode &= 127;
        nodes2[pNode].directions[direction] = pBranchNode;
    }   

}
bit getNodeExplored(nodep pNode, int direction)
{
    if (!bit_test(pNode,7))
    {
        return bit_test(nodes1[pNode].directions[direction],6);
    }
    else
    {
        pNode &= 127;
        return bit_test(nodes2[pNode].directions[direction],6);
    }   
}

void setNodeExplored(nodep pNode, int direction, bit flag)
{
    if (!bit_test(pNode,7))
    {
        if (flag) bit_set(nodes1[pNode].directions[direction],6);
      else bit_clear(nodes1[pNode].directions[direction],6);
    }
    else
    {
        pNode &= 127;
      if (flag) bit_set(nodes2[pNode].directions[direction],6);
      else bit_clear(nodes2[pNode].directions[direction],6);
    }   
}


//a return traversal needs to know which pointer it is coming back from so the
//robot can manuver


void pushTraverse(nodep from_node, int direction)
{
    traverse[traverse_top] = from_node;
    direction &= 0b00000011;
    traverse[traverse_top] |= (direction << 5);
    traverse_top++;
}

traversep popTraverse()
{
    traverse_top--;
    return traverse[traverse_top];
}

traversep getTopTraverse()
{
    return traverse[traverse_top - 1];
}

unsigned getTraverseDirection(traversep trav)
{
    return (trav & 0b01100000) >> 5;
}

nodep getTraverseNode(traversep trav)
{
    return trav & 0b10011111;
}



void turnTo(int newdirection)
{

}
bit nodeDetect()
{
   return 1;
}
bit allsensors()
{
   return 0;
}
unsigned getNewDirection(nodep n)
{
   return STRAIGHT;
}
unsigned gridX()
{
   return 0;
}
unsigned gridY()
{
   return 0;
}


//maze solver
void main(void)
{

    //we start out on a straigh away
    orgnode = allocnode(0, 0);
    pushTraverse(orgnode, STRAIGHT);
    prev_node = orgnode;
   
    //TODO: start rolling straight
   
    do
    {
        if (allsensors()) break;
       
        if (nodeDetect()) //detects dead ends too
        {
            if (backtracking)
            {
                //mark this node direction as explored
                //remove the dead end traversal from the stack.
                prev_traverse = popTraverse();
            tnode = getTraverseNode(prev_traverse);
            tdir = getTraverseDirection(prev_traverse);
                setNodeDirection(tnode, tdir, prev_node);
                setNodeExplored(tnode,tdir,1);
                prev_node = getTraverseNode(prev_traverse);
               
                newdirection = getNewDirection(prev_node);
                if (newdirection)
                    backtracking = false;
               
                   
                newdirection -= getTraverseDirection(prev_traverse);
                newdirection &= 3;   
                turnTo(newdirection);
            }
            else
            {
                //we have arrived at a new node
                //document it and explore from this point
                prev_node = allocnode(gridX(), gridY());
                newdirection = getNewDirection(prev_node);
                if (newdirection)
                {
                    pushTraverse(prev_node, newdirection);
                    turnTo(newdirection);
                }
                else
                {
                    //The new node is a dead end
                    backtracking = true;
                    turnTo(INCOMING);
                   
                }
            }
        }
        else
        {   
            //track straight line
        }
    }while(1);
   
    //do solution dance
   
}

/*

intersection model

            left
              ^
              |
incoming ->---|-----> straight
              |
              |
            right

normally the robot is coming into the intersection from the incoming direction
when the robot is backtracking it will may be coming from any direction excpet incoming and going to any
direction. THe manuver routine will need to know what direction the robot is going and what direction the
robot wants to go.

incoming = 0
left     = 1
straight = 2
right    = 3


pcode
    create orgnode node
    push straight traversal from orgnode
    follow line to next node

    do
        if all sensors detect then exit loop
        if node detected
            if backtracking
                if valid and unexplored random direction
                    manuver for new direction (based on top traverse in backtrack mode)
                    pop top traverse
                    clear backtrack mode
                else
                    manuver for incoming direction (based on top traverse in backtrack mode)
                    pop top traverse
                endif
            else
                populate current node directions
                reset explored flags
                estimate grid coords based on distance
                link node to last traversal direction
                if valid and unexplored random direction
                    push directed traversal from current node
                    manuver for new direction
                else
                    unxepected condition!!
                endif
            endif
           
        else
            if found dead end
                reverse direction
                set backtrack flag
                mark top traverse's node's direction as explored
            else
                keep going
            endif
        end if
    loop

    write travers stack to flash
    do solution dance
*/


PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 16, 2004 5:43 pm     Reply with quote

You didn't post any of your CCS pre-processor statements.
Have you enabled use of ram at address 0x100 and above,
by using the #device *=16 statement ? Example:

#include <16F877A.h>
#device *=16

That #device statement should go on the next line after your
#include statement. Don't put it anywhere else.
Royce



Joined: 16 Jul 2004
Posts: 4

View user's profile Send private message

PostPosted: Fri Jul 16, 2004 6:07 pm     Reply with quote

I had actually edited my 16F877A.h file to read

#device PIC16F877A *=16

on line 2.

I didn't realize that you could split the device statement up like that. I changed the .h file back to the way it was and added the line you show but there was no change in symptoms. I think that my was inelegant but still technically correct.

Regards,
Royce
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 16, 2004 6:29 pm     Reply with quote

You may have to do as Neutone suggests, and help the compiler
to allocate ram properly by using the #locate directive for your
large arrays. This appears to work. (ie., it now compiles without
an "out of ram" error). Example:

node nodes1[24];
#locate nodes1 = 0x110
node nodes2[24];
#locate nodes2 = 0x190
Darren Rook



Joined: 06 Sep 2003
Posts: 287
Location: Milwaukee, WI

View user's profile Send private message Send e-mail

PostPosted: Fri Jul 16, 2004 6:34 pm     Reply with quote

Maybe I didn't understand your problem, but why do you care where stuff is in RAM? That is why you buy a compiler, to handle placing things in RAM and for you to not worry about it.
Royce



Joined: 16 Jul 2004
Posts: 4

View user's profile Send private message

PostPosted: Fri Jul 16, 2004 7:21 pm     Reply with quote

Darren: the compiler was failing to compile this code. Its not that I care where the variables are, but they do have to be somewhere. Before I made the change that PCM Programmer made the compiler simply wasn't allocateing the space. Plus it was putting a bunch of variables ontop of one another at location zero.. which is a bad place for them to be.

PCM Programmer: Thanks a bunch for the work around! My symbol table looks sane now. I guess I'm kind of dissapointed that the compiler could not figure it out by itself. And it strikes me a strange that telling the compiler to put those arrays in the same place it was automatically selecting without the #locates would somehow allow it to find homes for all the other variables.

Would you not count that a compiler bug? Should I turn in a bug report?

All in all though this still looks to be a good upgrade from CC5X. Those expressions were killing me,

Thanks again,
Royce
Alex
Guest







PostPosted: Mon Oct 04, 2004 8:45 am     Reply with quote

Don't you have to switch between banks when you use the #locate in different banks ?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Oct 04, 2004 1:34 pm     Reply with quote

Quote:
Don't you have to switch between banks when you use the
#locate in different banks ?

No. The compiler knows which banks the variables are in, because
the upper bits of the address are specified in the address that you
use with the #locate statement.

One of the features of the CCS compiler is that you don't have to
manually put in bank switching code. It knows what bank everything
is in, and automatically puts in code to switch to the correct bank
before accessing a variable.

------------
Edited to add:
I just noticed you asked this question (and got an answer) in another
thread, here:
http://www.ccsinfo.com/forum/viewtopic.php?t=20605
You should only ask a question in one thread. Don't tack the same
question onto several threads.
C-H Wu
Guest







don't push it to the limit
PostPosted: Mon Oct 04, 2004 7:43 pm     Reply with quote

Royce wrote:
Darren: the compiler was failing to compile this code. Its not that I care where the variables are, but they do have to be somewhere. Before I made the change that PCM Programmer made the compiler simply wasn't allocateing the space. Plus it was putting a bunch of variables ontop of one another at location zero.. which is a bad place for them to be.

PCM Programmer: Thanks a bunch for the work around! My symbol table looks sane now. I guess I'm kind of dissapointed that the compiler could not figure it out by itself. And it strikes me a strange that telling the compiler to put those arrays in the same place it was automatically selecting without the #locates would somehow allow it to find homes for all the other variables.

Would you not count that a compiler bug? Should I turn in a bug report?

All in all though this still looks to be a good upgrade from CC5X. Those expressions were killing me,

Thanks again,
Royce


I compiled your code, happy with nodes1[20], cried out with nodes1[24].

You should file a bug report, although I would call it a compiler 'defect' instead of 'bug'.

The problem is CCS always put 'local' variables at the 'end' of available RAM.

In your case, you need two 96-byte array, which have to filled up bank 2 and 3, then, there is no more RAM after bank 3, as a result, CCS cried out.

The easiest way to get around, is to reduce you array size. say, instead of 96-bytes array, 80-bytes array will be much more easier for CCS to handle, since all 4 banks has at least 80 byte space.

node nodes1[20]; // instead of 24, thus, 80 bytes instead of 96
node nodes2[20];

can you live with 20 ? Confused

last words, don't push it to the limit Cool

Best wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group