The Program Memory Organization
The Program Memory is the place where the user can write the assembly code of his program. Therefore, this is usually the bigest in size memory of the PIC. The PIC 16F88 device, has 4K of Program Memory. Strangely, it can allocate up to 8K of memory, but only the first 4K are physical memory. If the user calls a memory position higher than 4K, it will loop back to the beginning of the program memory (0x00).
The Reset Vector
There are two positions in the Program Memory that you need to know. The first one is the reset vector. The reset vector is the position where the program counter will go to after a reset (or a power on). This position is as expected at position 0x00, at the very beginning of the program memory.
The Interrupt Vector
The other very important position to know is the Interrupt Vector. This is the position where the program counter will go to when an interrupt occurs. The interrupts will be covered extensively later on. But in order to get an idea of what interrupts are, i shall give you an example. Suppose that the program counter is the paper carrier of a vintage type writer. While you type letters, the whole carrier shifts to left, one position every time. The letters are supposed to be your assembly code. Each letter corresponds to one instruction. The carrier will not shift left infinitely. There is a specific point where it has reached it's most left position and needs to be sent back. This position is the hypothetical interrupt and the interrupt vector is the most-right position of the carrier. So, as you type letters (instructions), when the interrupt occurs, no matter what instruction follows or is already executed, the carrier (program counter) shall return to the interrupt vector!
In real life, an interrupt example is the RB0/INT. If this interrupt is enabled, then every time the RB0 pin is HIGH, the program counter goes to the interrupt vector. This interrupt vector is located at the position 0x04, shortly after the reset vector.
org 0x00 ;Here is the Reset Vector. Here the program starts GOTO Start org 0x04 ;Here is the Interrupt Vector . . . Start . . .
The above example demonstrates how to start a program. Right on the reset vector, we usually put a GOTO instruction to a position after the Interrupt Vector. That is because we may want to use the Interrupt Vector, and therefore we need to keep it clear of code. You will notice the keyword ORG. This keyword tells to our assembler the position that the following instructions should be placed. So, the first one tells to MASM to put the GOTO Start instruction right on the 0x00 position. The second one, the ORG 0x04, is the position of the interrupt vector. It does not moatter if you do not feel comfortable with the interrupts. You are just on the beginning and this is normal. The interrupts will be discussed in details during the intermediate lessons.
The Program Counter (PC), the PCL and PCLATH registers
The Program Counter is a 13-bit wide register that keeps the position of the program while in execution. The PC will have the value 0x00 (reset Vector) after a reset or a power on of the PIC. Then, after an execution of an instruction, the PC will increase it's position by 1. The instruction that is located to this position will be the next to be executed. Because of it's 13-bit width, the PC can get values up to 8K, but as said before, only the first 4K are physical memory.
The program Counter is composed by two registers. The first one is the PCL. This is a readable and writable register that carries the first 8 bits of the Program Counter. This register can be directly accessed and is located in the third position of all four banks (0x02, 0x82, 0x102 and 0x182). The other 5 bits are NOT readable. the can be indirectly written though through the PCLATH register.
The knowledge provided above shall be useful to you when you start making computed GOTOs. A computed GOTO is a programming technique, that someone can implement data tables. For example, if you add 0x01 to the PCL, then the first element of the table is accessed, if you add 0x02, the second element is accessed and so on. The limitation is that only 256 elements can be accessed each time, as the PCL is an 8-bit register. For longer tables, you need to access the PCLATH.
Program Memory Paging
This is a very important topic and needs of your full attention. I have spent hours and hours of sense-less debugging because i was not aware of the Program Memory Paging that the PIC uses.
Let's take thing from the beginning. The problem occurs when the user does a GOTO or a CALL. These instruction can carry up to 11-bit memory position. But our memory width is 13-bits. In other words, a CALL or GOTO instruction can send the PC from position 0 to position 2047 (2K). But our PIC has 4K (4095) of physical memory! How can a GOTO or a CALL access the whole memory and not just the first 2K of it?
The job is done manually. And this is the point that needs your attention. Microchip calls this "Program Memory Paging". This is nothing else than manually setting the 2 MSB of the PCLATH register that the 11-bit GOTO and CALL instructions cannot reach. An elegant name for the "manually setting the PCLATH bits".
The PCLATH is a 5-bit width register. It carries the bits 8 through 12 of the Program Counter. But the CALL and GOTO instructions can carry up to 11-bits of memory location. So, the 2 MSB of the Program Counter that happens to be also the 2 MSB of the PCLATH (bits 4 and 3) needs to be changed manually. There are 4 obvious pages in the program memory:
And why is this so important for you? Suppose that you are writing a program that it is smaller than 2 Kbytes. Your whole program is located within the first page (page 0) and only. So, any GOTO and CALL will be FROM page 0 TO page 0. Everything will work fine. Now suppose that your program is longer than 2K. And suppose that in page 0 there is a GOTO (or CALL) to a program location that belongs to page 1. What will happen? The GOTO instruction will have an affect to the first 11 bits of the program counter. So, if the source (the GOTO position) is the position 0x100 in the program memory, and the target of the GOTO is the program memory 0x900, look what happens:
0x100 = 00 00100000000 b
The Program Counter at the target of the GOTO should be:
0x900 = 01 00100000000 b
I have kept the highest 2-bits of the PC separated in purpose for you to see the difference.
The GOTO instruction is just 11-bits width, so the GOTO to location 0x900, will actually affect ONLY the 11 first bits of the Program Counter. And actually, it shall be sent to '00100000000' instead of '01 00100000000'. The 2 MSB of the Program Counter shall be kept untouched! The final position of the GOTO 0x900, instead of the 0x900 will be the 0x100 again!
And what can be done for this? There are basically two ways to avoid such errors. The first one is the most obvious. You can manually set the PCLATH 2 MSB bits. So, the correct way of the above GOTO command should be as follows:
org 0x100 ;You are in position 0x100 (Page 0) bcf PCLATH,4 ;PCLATH bit 4 is 0 bsf PCLATH,3 ;PCLATH bit 4 is 1, The page 1 is selected for the next GOTO GOTO TargetPosition ;This GOTO is done in Page 1 as selected above . . . org 0x900 ;You are in position 0x900 (page 1) TargetPosition . .
Another way of selecting pages, that i prefer the most, is to use the MASM 'pagesel' keyword. By using this keyword, the appropriate page selection is done automatically, according to the position of the label that follows this keyword. The above example could be written as follows:
org 0x100 ;You are in position 0x100 (Page 0) pagesel TargetPosition ;The appropriate page (page 1) is selected! GOTO TargetPosition ;This GOTO is done in Page 1 as selected above . . . org 0x900 ;You are in position 0x900 (page 1) TargetPosition . .
The page selection NEEDS TO BE DONE each and every tome you want to change the PC with a GOTO or a CALL instruction, and the target position is in a different page tfrom the page that the GOTO or CALL was located. When i make such GOTOs or CALL, i usually call them FAR GOTO and FAR CALL, to indicate that the target is in different page.
Confirm your knowledge
There is an online test to check your knowledge on this page. You may reveal the test with the following button:
No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise without the prior written permission of the author.
Read the Disclaimer
All trademarks used are properties of their respective owners.
Copyright © 2007-2009 Lazaridis Giorgos.
All rights reserved.