|
|
View previous topic :: View next topic |
Author |
Message |
Royce
Joined: 16 Jul 2004 Posts: 4
|
PCM 3.205, 16F877A and bank 1 |
Posted: Fri Jul 16, 2004 3:57 pm |
|
|
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
|
|
Posted: Fri Jul 16, 2004 4:24 pm |
|
|
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
|
|
Posted: Fri Jul 16, 2004 5:30 pm |
|
|
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.
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
|
|
Posted: Fri Jul 16, 2004 5:43 pm |
|
|
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
|
|
Posted: Fri Jul 16, 2004 6:07 pm |
|
|
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
|
|
Posted: Fri Jul 16, 2004 6:29 pm |
|
|
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
|
|
Posted: Fri Jul 16, 2004 6:34 pm |
|
|
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
|
|
Posted: Fri Jul 16, 2004 7:21 pm |
|
|
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
|
|
Posted: Mon Oct 04, 2004 8:45 am |
|
|
Don't you have to switch between banks when you use the #locate in different banks ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 04, 2004 1:34 pm |
|
|
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 |
Posted: Mon Oct 04, 2004 7:43 pm |
|
|
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 ?
last words, don't push it to the limit
Best wishes |
|
|
|
|
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
|