# Pic12f629 problems with memory map and sleep

Status
Not open for further replies.

#### bouvett

##### New Member
hi...

I am trying to program the pic12f629, but unfortunately i have still not understood some basic definitions making it.. these are:

i have just encountered a problem in the interrupt section of the datasheet...
if one looks at the memory map of this micro he can notice that the general purpose registers can be accessed also from bank1...
so can we define say location 20h and A0h as say reg1 by

reg1 equ 20h
reg1 equ A0h i think this would produce an error, but if i understood correctly in the datasheet there is written that this is possible
quote" 9.5 Context Saving During Interrupts

The user register, W_TEMP, must be defined
in both banks and must be defined at the same offset
from the bank base address (i.e., W_TEMP is defined
at 0x20 in Bank 0 and it must also be defined at 0xA0
in Bank 1) "

?????

also, there is written that "The user register, STATUS_TEMP, must be defined in Bank 0."
why is this so? why only in bank 0? in the memory map there is written that status register is in both bank 0 and bank 1!.. so what does this mean? is status in bank1 a reflection of the status register in bank 0 or what(other examples are the FSR PCL and PCLATH, i really wonder why they are in both banks )??

sry for my grade of confusion by the way...

finally,
i need to make myself sure about two other things with regards to the sleep function:

1.in section 9.7 the datasheet says that theoscillator driver is turned off... now, timer0 is surely turned off during sleep, but with regards to timer1, if say an hs oscillator is used, does this mean that the timer1 won't continue to increment(since the HS oscillator driver is switched off) will it only continue to operate if the internal oscillator is used as a main oscillator??

2. in the same section there is a note saying :

Note: If the global interrupts are disabled (GIE is
cleared), but any interrupt source has both
its interrupt enable bit and the corresponding
interrupt flag bits set, the device will
immediately wake-up from SLEEP. The
SLEEP instruction is completely executed

therefore if the micro would in such a case wake up but not start the ISR ?

thanks a lot... i am really grateful

#### blueroomelectronics

##### Well-Known Member
Use the include file, don't point to SFRs directly. You must save and restore at least W and STATUS when using interrupts on a 14bit core PIC.

#### kpatz

##### New Member
The PIC12F629 has 2 banks, with some SFRs in one and some in the other. The GPRs are the same in both banks (on the 629, but not on all PICs), so when you use the GPRs on the 629 you don't have to worry about switching banks.

Like blueroomelectronics said, use the include file constants to reference the SFRs and the bits within. Also, use the banksel directive to switch banks as needed (say, to access TRISIO and then GPIO).

reg1 equ 20h
reg1 equ A0h
This would be an error, but when referencing any register, you would use 00-7Fh, and the PIC would access the bank as set by bit RP0 in the STATUS register. This is because there's only 7 bits in the instruction to hold the register address, so to access more than 128 bytes/registers, they need to be banked.

So, for example (I'm using 05h to set an example, you should use the include constants to make the code more readable):
Code:
  bcf STATUS,RP0  ; Clear the bank bit
bsf 05h,0           ; Sets bit 0 of GPIO

bsf STATUS,RP0  ; Set the bank bit
bcf 05h,0           ; Clears bit 0 of TRISIO

You can see both GPIO and TRISIO are accessed at the same address (05h) but in different banks.
The user register, W_TEMP, must be defined in both banks and must be defined at the same offset from the bank base address (i.e., W_TEMP is defined at 0x20 in Bank 0 and it must also be defined at 0xA0 in Bank 1) "
When you enter your interrupt service routine, you don't know what bank you might be in at the time, and you need to save the W register before making any changes to the bank bits, therefore, you need to reserve that byte in both banks. But, on the 16F629 it doesn't matter, since the general purpose registers are the same in both banks.
also, there is written that "The user register, STATUS_TEMP, must be defined in Bank 0." why is this so? why only in bank 0?
Because, once you've saved W off (in either bank), you then move STATUS to W (in essence saving it), and then you can change the bank bit in the STATUS register, eliminating the need to reserve space in both GPR banks. Once the bank is set, you store W to STATUS_TEMP which saves the original copy of the STATUS register. Here's the sample code from the datasheet:
Code:
MOVWF W_TEMP ;copy W to temp register,
could be in either bank
SWAPF STATUS,W ;swap status to be saved into W
BCF STATUS,RP0 ;change to bank 0 regardless of
current bank
MOVWF STATUS_TEMP ;save status to bank 0 register
:
:(ISR)
:
SWAPF STATUS_TEMP,W;swap STATUS_TEMP register into
W, sets bank to original state
MOVWF STATUS ;move W into STATUS register
SWAPF W_TEMP,F ;swap W_TEMP
SWAPF W_TEMP,W ;swap W_TEMP into W
in the memory map there is written that status register is in both bank 0 and bank 1!.. so what does this mean? is status in bank1 a reflection of the status register in bank 0 or what(other examples are the FSR PCL and PCLATH, i really wonder why they are in both banks )??
Certain commonly-used registers such as STATUS, FSR, PCL, and a few others are mirrored in both banks to make them accessible without having to switch banks.

Last edited:

#### kpatz

##### New Member
inally,
i need to make myself sure about two other things with regards to the sleep function:

1.in section 9.7 the datasheet says that theoscillator driver is turned off... now, timer0 is surely turned off during sleep, but with regards to timer1, if say an hs oscillator is used, does this mean that the timer1 won't continue to increment(since the HS oscillator driver is switched off) will it only continue to operate if the internal oscillator is used as a main oscillator??
The only way timer1 will continue to increment during sleep is if you use the Timer1 crystal oscillator. See page 33 of the datasheet.
Note: If the global interrupts are disabled (GIE is
cleared), but any interrupt source has both
its interrupt enable bit and the corresponding
interrupt flag bits set, the device will
immediately wake-up from SLEEP. The
SLEEP instruction is completely executed
therefore if the micro would in such a case wake up but not start the ISR ?
The interrupt enable bit for the timer will cause the PIC to wake-up from sleep when the timer rolls over and its interrupt flag gets set (make sure to clear the interrupt flag before going to sleep, or the PIC will awaken immediately). If the global interrupt enable flag is set, the ISR will execute after the PIC wakes up and executes the instruction following the SLEEP (it's suggested to put a NOP there). If the GIE flag is clear, the PIC will wake-up but it won't execute the ISR; it will just resume execution at the instruction following the SLEEP. If the TMR1E timer interrupt flag isn't set, the timer won't wake-up or interrupt the PIC.

Think of the flow as follows:

Code:
  While sleeping
{
If timer1 overflows { set TMR1IF }
If TMR1F is set and TMR1E is set
{
Wake-up
Execute instruction following SLEEP
If GIE is set { goto ISR }
}
}

Last edited:

#### bouvett

##### New Member
The PIC12F629 has 2 banks, with some SFRs in one and some in the other. The GPRs are the same in both banks (on the 629, but not on all PICs), so when you use the GPRs on the 629 you don't have to worry about switching banks.

Like blueroomelectronics said, use the include file constants to reference the SFRs and the bits within. Also, use the banksel directive to switch banks as needed (say, to access TRISIO and then GPIO).

This would be an error, but when referencing any register, you would use 00-7Fh, and the PIC would access the bank as set by bit RP0 in the STATUS register. This is because there's only 7 bits in the instruction to hold the register address, so to access more than 128 bytes/registers, they need to be banked.

So, for example (I'm using 05h to set an example, you should use the include constants to make the code more readable):
Code:
  bcf STATUS,RP0  ; Clear the bank bit
bsf 05h,0           ; Sets bit 0 of GPIO

bsf STATUS,RP0  ; Set the bank bit
bcf 05h,0           ; Clears bit 0 of TRISIO

You can see both GPIO and TRISIO are accessed at the same address (05h) but in different banks.When you enter your interrupt service routine, you don't know what bank you might be in at the time, and you need to save the W register before making any changes to the bank bits, therefore, you need to reserve that byte in both banks. But, on the 16F629 it doesn't matter, since the general purpose registers are the same in both banks.Because, once you've saved W off (in either bank), you then move STATUS to W (in essence saving it), and then you can change the bank bit in the STATUS register, eliminating the need to reserve space in both GPR banks. Once the bank is set, you store W to STATUS_TEMP which saves the original copy of the STATUS register. Here's the sample code from the datasheet:
Code:
MOVWF W_TEMP ;copy W to temp register,
could be in either bank
SWAPF STATUS,W ;swap status to be saved into W
BCF STATUS,RP0 ;change to bank 0 regardless of
current bank
MOVWF STATUS_TEMP ;save status to bank 0 register
:
:(ISR)
:
SWAPF STATUS_TEMP,W;swap STATUS_TEMP register into
W, sets bank to original state
MOVWF STATUS ;move W into STATUS register
SWAPF W_TEMP,F ;swap W_TEMP
SWAPF W_TEMP,W ;swap W_TEMP into W
Certain commonly-used registers such as STATUS, FSR, PCL, and a few others are mirrored in both banks to make them accessible without having to switch banks.

i really can't understand this problem of the W_temp register... if it is an error to name to locatons wth the same name using

reg1 equ 20h
reg1 equ A0h (i agree that it should be an error)

therefore why did the datasheet say that we should name it the same??
the isr should use movwf reg1 as soon as it enters the ISR right, whether it is in bank1 or bank0... now if it had to be an error to name two locations with the same name (again let me say that it seems obvious although it seems to be suggested in the datasheet), and thus we have to name the two locations with a different name though they are basically the same(since the ones in bank1 access bank0), you have noted that we cannot(for the w register) vary the bank first before saving the w reg, therfoe how is it possble to save the w reg... you cannot simply say movf w_temp_bank1 since you might be in bank0 and thus it is not found...

i believe you and understand if you say my post is very confusing... in fact even i myself is very confused on this subject... can anyone please post some examples ..

thanks a lot
regards

#### kpatz

##### New Member
You only have to name the register once. So, for example, in your code, you would put:
Code:
reg1 equ 20h

Now, whenever you reference that register in an instruction, it will access the register at 20h. But, if the bank bits (RP0) are set to bank 1, you would still say 20h in your code, but the uC will actually access the register at A0h.

Think of the register file as RAM, where each location/register has an address, starting at 00h and going up to however far it goes (let's say FFh for simplicity). This is 256 locations, requiring an 8 bit address to get at all the registers. However, the PIC16 opcodes only allow 7 bits for direct addressing, so when you say:
Code:
movwf  20h
only the lowest 7 bits are assembled into the opcode. In other words, if you say:
Code:
movwf A0h
the topmost bit of the address would be omitted, and the resulting opcode winds up pointing to 20H.

So... to get at registers above 7FH you need to use the bank bits. The RP0 bit becomes the most significant bit of the address, so, with RP0 = 0, you can access registers from 00h-7Fh. With RP0 = 1, you then access registers from 80h-FFh.

The reason the datasheet says to make "w_temp" both 20h and A0h merely means you need to RESERVE both 20h and A0h for w_temp (in other words, don't use 20h or A0h for other purposes). If you use an equ directive to give it a name, you just make it 20h. The reason for reserve it in both banks is because you won't know what bank you're going to be in at the time the interrupt occurs. You may be in bank 0 during one interrupt, and bank 1 during the next. If you reserved 20h for w_temp and then used A0h for something else, and an interrupt occurs while RP0 = 1, the code that saves W into w_temp will overwrite your data in A0h.

Last edited:

#### bouvett

##### New Member
hey
you just said " If you reserved 20h for w_temp and then used A0h for something else, and an interrupt occurs while RP0 = 1, the code that saves W into w_temp will overwrite your data in A0h."

from the memory map there is written that A0h is actually 20h, i.e if you write to A0h you are writing in 20h actually.. therefore you cannot use A0 for something and 20h for something else right? in fact in the memory map it says

general purpose: 20h-5fh
A0h-DFh accesses 20h -5fh

they must be the same... you cannot use one location for something and its reflection for something else ...

thanks
regards

#### bouvett

##### New Member
example 9.2

MOVWF W_TEMP ;copy W to temp register,
could be in either bank
SWAPF STATUS,W ;swap status to be saved into W
BCF STATUS,RP0 ;change to bank 0 regardless of
current bank
MOVWF STATUS_TEMP ;save status to bank 0 register
:
ISR)
:
SWAPF STATUS_TEMP,W;swap STATUS_TEMP register into
W, sets bank to original state
MOVWF STATUS ;move W into STATUS register
SWAPF W_TEMP,F ;swap W_TEMP
SWAPF W_TEMP,W ;swap W_TEMP into W

this is very confusing also actually (for me)
why does it use the swapf instruction instead of just moving it? someone somewhere has suggested that the status register can be changed if the status register is simply moved to w and then to its temp file....
i would really like to have an example how this is possible cause i cannot find one myself

not mentioning that it seems contradictory(again for me) since to move w in w_temp he just used the movwf, whilst when it came to moving the w_temp back to w(after moving the status register) he used the swapf instruction twice...

can anyone please help me understand cause i am really getting frustrated with the lack of explanation (not necessarily a whole assay, just some extra words) in the datasheet.

thanks
regards

THANKS FOR ANYONE'S HELP BUT I MANAGED TO SOLVE THIS OUT, I TRIED SOME CODE AND I CONFIRMED TAHT WITH THE USE OF THE SWAPF INSTRUCTION ONE CAN MOVE A REGISTER HAVING A VALUE OF 0 INTO W WITHOUT ALTERING TEH STATUS BIT (ZERO_BIT).. THE SAME DOES NOT APPLY IF MOVF IS USED...

THANKS REGARDS, BTW ANY HELP IN THE POST PREVIOUSLY POSETED WILL BE VERY MUCH APPRECIATED
REGARDS

Last edited:

#### kpatz

##### New Member
from the memory map there is written that A0h is actually 20h, i.e if you write to A0h you are writing in 20h actually.. therefore you cannot use A0 for something and 20h for something else right? in fact in the memory map it says

general purpose: 20h-5fh
A0h-DFh accesses 20h -5fh

they must be the same... you cannot use one location for something and its reflection for something else ...

thanks
regards
Yes, you are correct, for the PIC12F629. But some higher-end PICs have more memory and the banks will contain different data, so something to keep in mind if you start developing things with other PICs.

why does it use the swapf instruction instead of just moving it? someone somewhere has suggested that the status register can be changed if the status register is simply moved to w and then to its temp file.... i would really like to have an example how this is possible cause i cannot find one myself.
When you use movf, the Z bit in the status register will be changed. Therefore, if you're trying to save the status register, you don't want to use instructions that change bits in the status register. Swapf is a good one to use since it doesn't change the status bits.
not mentioning that it seems contradictory(again for me) since to move w in w_temp he just used the movwf, whilst when it came to moving the w_temp back to w(after moving the status register) he used the swapf instruction twice...
That's because movwf doesn't change status flags, but movf (movfw) does. Therefore, if you want to move things around without changing status bits, you need to use the two swapfs (which has the same effect as movfw without changing status bits).

P.S. looks like you have it figured out.

#### bouvett

##### New Member
IT SEEMS FROM
https://www.electro-tech-online.com/custompdfs/2009/08/PIC_Mid_A_6.pdf
FIRST FEW PAGES

that you can simply ,if you use the shared data, set the w_temp register and status_temp register in which ever location you want and form which ever bank you want since being shared you are still writing at the same location.. and when you want to context save, you just write w_temp or status_temp, you don't have to bother about getting to bank 0 for the status register as mentioned in the datasheet. this is since we are using shared data, and thus variables in bank 0 can be accessed using the same name, through both banks using the same name in either case...

right?

thanks regards

#### blueroomelectronics

##### Well-Known Member
Many 14bit core PICs have shared (all bank) memory at the 0x70 to 0x7F range. This is easy to demonstrate with the MPLAB simulator. It was a perfect place for W_TEMP & S_TEMP variables.

#### bouvett

##### New Member
Many 14bit core PICs have shared (all bank) memory at the 0x70 to 0x7F range. This is easy to demonstrate with the MPLAB simulator. It was a perfect place for W_TEMP & S_TEMP variables.

yes i agree but what about what i asked am i right?

thanks a lot
regards

#### kpatz

##### New Member
that you can simply ,if you use the shared data, set the w_temp register and status_temp register in which ever location you want and form which ever bank you want since being shared you are still writing at the same location.. and when you want to context save, you just write w_temp or status_temp, you don't have to bother about getting to bank 0 for the status register as mentioned in the datasheet. this is since we are using shared data, and thus variables in bank 0 can be accessed using the same name, through both banks using the same name in either case...

right?

thanks regards
You are correct. In the case of the 12f629, all of the general purpose registers (the places you save your own data to, at 20h and higher) are shared across all banks, so you don't need to worry about switching banks for accessing your own variables. You only need to worry about switching banks for accessing certain SFRs (such as TRISA and PORTA which are in different banks).

Some day you may take on projects using the mid-range or higher-end PICs (PIC16 series) for example, and some of these do have banked GPRs, so you'll have to take that into account. But for the PIC you're using now, don't sweat it.

I'm using a PIC16F818 in one of my projects, and on this PIC the GPRs from 20h-40h are banked, while 40h and higher are shared, so I just put all my variables at 40h and higher, and then I don't have to worry about switching banks for GPRs.

Last edited:

#### bouvett

##### New Member
the same applied for the temporary file of STATUS right? since in the data sheet it specified that it must be in bank0 only.... i wonder whys he said that...

#### blueroomelectronics

##### Well-Known Member
STATUS is the same in all banks on all PICs. If you're saving it for an interrupt then save it in all bank (shared) RAM.

Remember the original PIC was designed in 1976 and transistor count was very expensive (compared to today) So tricks were used (such as bank switching) to keep the count low. The old C128 used this trick with its RAM to address more memory.

Advanced PICs like the 18F don't have the bank switching woes the midrange PICs have, the 18F also addressed lots of quirks that a 30yr old design couldn't (such as RMW).

Status
Not open for further replies.

Replies
2
Views
1K
Replies
3
Views
3K
Replies
13
Views
1K
Replies
5
Views
1K
Replies
0
Views
3K