Nothing more than a memory - Page 1
Forum section: electronics / general

author: PerranOak
author_rank: Frequent Contributor
timestamp: July 03, 2018, 01:02:43 pm
content: I'm trying to get to grips with the memory in my PIC16F1827.The datasheet says there are three types: programme, data, EEPROM.Is have been taught to begin progs like this:#include p16f1827.var_1 equ 0x20var_2 equ 0x21org 0x0000goto startorg 0x0004goto intrptorg 0x0005main prog ...So, this is programme memory and the datasheet goes on to specify that this is then split into "Page 0" and "Page 1".What is the significance of detailing this break at 07FFh / 0800h - is there any?It then goes on to data memory: core registers, SFRs, General purpose RAM (GPRAM) and common RAM.When it says that the core registers, SFRs and common RAM occupy "every data memory bank" does this mean that whatever is written in one register in one bank is "copied" to the same register in all banks?Am I right though that GPRAM is not the same and that each bank can hold different values in the equivalent positions?Is the "equ" in my example above somehow writing directly to the first and second positions in the GPRAM? I've never been told what this is but just to do it!The datasheet text says there is 80 bytes of GPRAM and 16 bytes of common RAM. However, in the memory map it shows 96 bytes in bank 0. Is this because this is where you write into common RAM that is then accessible in all banks? Can you write to this area when another bank is selected or do you have to be in bank 0 to write?EEPROM is said to be from 0h to 0ffh.You can ignore the fact that data memory and programme memory also being at 0h because the context of the commands being use will prevent any conflicts - is this correct?That's a lot, I'm sorry but if you could help please … thank you.

author: Berni
author_rank: Super Contributor
timestamp: July 03, 2018, 01:11:54 pm
content: My first advice is just use a high level language, the assembler on the PIC16F family is horrible.But if you still want to do it the thing is that instructions on the 16F can't address much memory. As a result most chips have pages that have to be switched between by flipping some special bits in a SFR. Trough some adressing forms you can get to memory regardless of the page setting. Other addressing modes or chunks of RAM are only addressable when the corresponding page is selected.The pages contain both RAM and SFRs, but they are mixed without any consistant structure and there are no long runs of contiguous memory. Some SFRs appear on multiple pages, some don't.Reading from flash memory needs a special instruction and reading from eeprom needs a different special instruction.All in all its horrible.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 03, 2018, 01:42:36 pm
content: Quote from: PerranOak on July 03, 2018, 01:02:43 pmYes. The place where GOTO goes depends on the PCLATH register, so your GOTO in the interrupt may go to either page, depending on what PCLATH was when the interrupt has happened. So, you need to set PCLATH before goto.Code:org 0x0000goto startorg 0x0004pagesel intrptgoto intrptorg 0x0006main prog ...Or better yet (eliminating unnecessary jump and decreasing interrupt latency):Code:org 0x0000goto startorg 0x0004; your ISR goes hereretfiestartmain prog ...Quote from: PerranOak on July 03, 2018, 01:02:43 pmThe bank is selected by BSR register. The address within the bank comes from the command.If the address in the command is 0x00 to 0x0f, BSR is ignored and command accesses coomon FSRs (such as WREG, PCLLATH etc.).If the address is 0x01 to 0x1f, the command accesses different SFRs depending on BSR.If the address is 0x20 to 0x6f, the command accesses regular RAM. BSR selects the bank. Each bank has 80 bytes of RAM (if populated).If the address is 0x70 to 0x7f, BSR is ignored and command accesses "common RAM" - 16 bytes of it.Quote from: PerranOak on July 03, 2018, 01:02:43 pmNo. The "equ" merely says that the "var_1" symbol should be replaced by 0x20 thereafter.

author: PerranOak
author_rank: Frequent Contributor
timestamp: July 04, 2018, 09:07:47 am
content: Thanks Berni but I really want to get to grips with assembly and the PICs inner workings.Thanks NorthGuy. With the equ and var_1 situation, where is the data for this variable actually stored?

author: mikerj
author_rank: Super Contributor
timestamp: July 04, 2018, 10:41:42 am
content: Quote from: Berni on July 03, 2018, 01:11:54 pmVery horrible, an AVR is a much nicer thing to program at this level.

author: glarsson
author_rank: Frequent Contributor
timestamp: July 04, 2018, 11:01:23 am
content: Quote from: PerranOak on July 04, 2018, 09:07:47 amIt is stored in RAM owned by the assembler. It is not a variable, just a name that can be used instead of the number. It just makes the source code neater and easier to understand and maintain.

author: jpanhalt
author_rank: Super Contributor
timestamp: July 04, 2018, 12:02:14 pm
content: @PerranOakSince you seem to be starting with that chip, there is a third "type" of RAM memory labeled, "Linear Data Memory." It accesses GPM but without paging using the FSR registers (FSR0 and/or FSR1). It has the advantage of not requiring paging. In brief, it can access all 384 bytes of GPM in a linear manner. See these sections of the datasheet: 2.3, 3.2.3.1, and most important, 3.5.2. FSR itself can access those areas, but if you set bit<5> of FSRnH (i.e., FSR = 0x2nnn), it is done as if the register is much larger (i.e, 384 bytes). That can be convenient if you need a large buffer. Much like the INDFn registers, it is not a physical register, but you can track is in a watch window. It will look something like this:As some user have stated, it is just another door to the GPM and Common Ram locations. Of course, Common Ram (limited to 16 bytes) does not require paging either.John

author: NorthGuy
author_rank: Super Contributor
timestamp: July 04, 2018, 03:03:06 pm
content: Quote from: PerranOak on July 04, 2018, 09:07:47 amThis is not actually a variable. EQU doesn't reserve a space. It simply associates a name with a number.After your EQU you can do:Code:movf var_1,wIt's the same as:Code:movf 0x20,wIt is up to you to make sure that the correct bank is selected and that other parts of the program don't use the same space.The closest C equivalent would beCode:#define var_1 0x20but notCode:char var_1 @0x20;

author: PerranOak
author_rank: Frequent Contributor
timestamp: July 06, 2018, 04:53:57 pm
content: Cheers all.I'm still not straight re the programme memory and RAM.Programme memory is where the programme code that you write is actually stored, yes? If so, in datasheet s.11.3 it talks about writing directly to "Flash Programme Memory" - is this the same thing? If it is the same thing, how is it possible/desirable to write data directly to where the programme is stored - will this not corrupt the programme? Is this different from s.3.1.1.2 "Indirect Read with FSR"?Ah. thanks, there is also what is in s.3.5.2 "Linear memory" thought it is not really there it is the same as GPRAM. Is GPRAM an area that if you use direct addressing with FSRs then is may overwrite where the assembler stores variables?Also, in the EEPROM write it talks about using the EEADRL, etc. registers. Theses need the value passed to them from variables but are variables in bank0 while these registers are in bank0>Phew!Thank you.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 06, 2018, 05:13:12 pm
content: Quote from: PerranOak on July 06, 2018, 04:53:57 pmIt certainly will corrupt the program if it's there. You can use some areas for program and others for data. Or you can create a bootloader which automatically program the new version of your firmware.Quote from: PerranOak on July 06, 2018, 04:53:57 pmFSR can address memory through banks.In addition to this, all the regular memory areas from all banks (80 bytes from a bank) are mapped consecutively to the addresses starting from 0x2000. E.g, first bank (0x20-0x6f) is mapped to (0x2000-0x204f), second bank (0xa0-0xef) is mapped to (0x2050-0x209f) etc. The 0x2000 area is only accessible through FSRs. This lets you have consecutive arrays which are longer than 80 bytes which would otherwise be impossible.Quote from: PerranOak on July 06, 2018, 04:53:57 pmEEPROM is a separate space, different from either program or date space. You only access it through special registers. Other PICs may have EEPROM mapped to the program memory space, but I don't think yours is one of them.

author: PerranOak
author_rank: Frequent Contributor
timestamp: July 09, 2018, 12:07:23 pm
content: Thank you very much.How do you know where your programme is in memory so that you can avoid it when using the programme memory for data?Also, when a programme uses variables are these just stored dynamically and not in any specific memory location?

author: NorthGuy
author_rank: Super Contributor
timestamp: July 09, 2018, 01:21:54 pm
content: Quote from: PerranOak on July 09, 2018, 12:07:23 pmYou decide where you put the program and where you put the data.Quote from: PerranOak on July 09, 2018, 12:07:23 pmIt is up to you to decide where your variables are. When you decide this, you use commands to access your variables at the known addresses.The Mucrochip's asm has a relocatable mode where you write code, then the linker allocates your variables for you.Better yet, if you use C, it'll allocate all the variables for you, will take care of banking/paging etc. If you don't feel you can benefit from doing these things manually, it's a good idea to use C.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 09, 2018, 05:13:53 pm
content: Ahh, the fond memories of bank selection in older PICs...Either use C which will take care of bank selection... or if you still want to use ASM, you will have to properly lay out your variables in memory and change banks when needed. Selecting the bank at every variable access would be very inefficient (and C compilers usually try to minimize bank selection).

author: PerranOak
author_rank: Frequent Contributor
timestamp: July 09, 2018, 08:32:20 pm
content: Hmm. I think the programme memory allocation stuff is beyond me at the moment but I do want to continue with assembly for now.How do you organise variables in memory?

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: July 09, 2018, 09:29:20 pm
content: Quote from: PerranOak on July 09, 2018, 08:32:20 pmYou use C - the compiler does it for you.

author: PerranOak
author_rank: Frequent Contributor
timestamp: July 10, 2018, 02:57:15 pm
content: … but then I'll never understand it.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 11, 2018, 08:32:45 am
content: Quote from: PerranOak on July 09, 2018, 08:32:20 pmWhen I did PIC assembly, I just started at address 20 (in hex) and just gave each byte-sized variable the next address.If something needed more than 8 bits I defined the high and low bytes separately - e.g TEMPH and TEMPL.However, once you use the first bank of memory (224 bytes, IIRC) things rapidly get very complex, as you need to put a lot more structure is what is stored in which bank.The small PIC micros are a terrible target for C compilers. The banked data and code memories is just C friendly (not to mention the shallow call stack). The instruction set is so small and has a lot of features that C cannot access directly (like a carry flag, or bit test operators).They are nice for assember coding. The entire instruction set can be fully documented on one side of one page and counting clock cycles is easy.

author: jpanhalt
author_rank: Super Contributor
timestamp: July 11, 2018, 11:36:22 am
content: Quote from: PerranOak on July 09, 2018, 08:32:20 pmIt would be a little easier, if you told us which family of chips you plan to use. Although the method in Assembly is basically the same for most chips, there are differences. If you are using an enhanced mid-range chip, then there are more options as I and NorthGuy have pointed out.First, I try to minimize the number of variables I use. Most of my stuff has a 'temp' and a 'count' register; although, I may not use both in a final version of the code. You could call them whatever, e.g., temp0, temp1, ... Some people prefer acc or accum, etc.For such variables, I use Common RAM. It starts at 0x70 and goes to 0x7F. It is accessible from any bank, but of course can hold only 16 bytes.For variables that will only be accessed when in bank 0, I use the space beginning at 0x20 and going to 0x6F. It is called General Purpose RAM. Most important, it is banked. That is, each bank has its own section. Go to Table 3-3 (usually)called "Memory Map."If you need a really large area of contiguous RAM, then you can use what is called "Linear Memory" (also described by NorthGuy). That uses indirect accessing (i.e., FSRn and INDFn) and acts as if all of GP RAM was one space. Depending on the chip, that can give access to hundreds of contiguous bytes.In actual practice, I use mainly GP RAM at 0x20..0x6F (Bank 0) and Common RAM at 0x70..0x7F almost exclusively. If I need a large space for variables that change frequently, like for a buffer, I use Linear Memory. I tend to start that buffer at 0x80 (actually accessed indirectly at 0x2080) to preserve the lowest bank of GP RAM. Banking is really a non-issue for me.EDIT: BTW, if you like a lot of different register names ("aliases"). You use as many as you want. The same register location can have several aliases as can the individual bits in different registers. Just look at the .inc file for your chip and you will an extreme example of that.

author: StillTrying
author_rank: Super Contributor
timestamp: July 11, 2018, 11:55:16 am
content: Quote from: PerranOak on July 09, 2018, 08:32:20 pmHave a look at the Assembler's View > Program Memory or View > Disassembly Listing.Worry about calls and gotos above 07ffh and PCLATH when you get to them.Quotecblock and endc are useful, they save having to use all the "equ"s. You can just list your ram variables between them.Code:cblock 0x20tempL, tempHbin:4 ; = 4 bytes, named "bin" to "bin+3"endccblock 0x70ram bytes common to all banksendc

author: PerranOak
author_rank: Frequent Contributor
timestamp: July 11, 2018, 12:49:55 pm
content: Thanks all.At the moment all I do is use memory at 20h and this larger structure is what I can't quite get.I am using the PIC16F1827. So, the common RAM is that last 16 bytes after general purpose RAM which is where the 20h area (that I use now) is located. The advantage of the common RAM is that you don't have to usebanksel?The linear memory INCLUDES the general purpose and common RAM does it? I hadn't picked that up as each section shows a different memory map.I can't see cblock or endc in the datasheet … oh wait, yes I se it's in the MPASM manual, cheers.

author: jpanhalt
author_rank: Super Contributor
timestamp: July 11, 2018, 04:01:16 pm
content: I have experience with the 16F1827.Linear Memory does not include Common Ram. You can say where to start it, which is why I start after 0x6F. If you look at the registers, you will see Linear RAM mapped to the various physical GP RAM registers, but from the user's perspective it is a contiguous block of 350+ bytes accessed indirectly. I start at 0x80 so as to avoid "looking like" it starts in Common Ram. That way, I know where to look for the registers.Like all threads, this one seems to have wandered. What is your current question?

author: PerranOak
author_rank: Frequent Contributor
timestamp: July 12, 2018, 12:55:02 pm
content: Thank you.It's really just to get to grips with all the different kinds of memory. The "memory maps" confuse me as there are different ones for different purposes and they all seem to start at 00h without there being one master map that shows where they all reside relative to each other. This is how I got confused with linear memory and GP RAM.So, the map I think understand is the one in banks with all the registers and the 80bytes of GP RAM and 16bytes of common RAM at the bottom.I think that the GP RAM is what I am using when I use theequcommand to "name" memory locations. I've not used the common RAM yet but I think this is similar to GP RAM but does not requirebanksel. I think that these are incorporated into what is called "traditional data memory", shown as from 0000h to 0FFFh, in one memory map?I now think that linear data memory, shown as from 2000h to 29AFh, is further memory separate from those above and can be addressed indirectly with the use of certain registers but not used by theequcommand. I am also getting the feeling that people see theequcommand as something used for storing constants rather than variables. Maybe linear data memory is for constants?I think the program memory is somewhere else entirely and can be used for data but I'm not really understanding how to that ensure this doesn't overwrite my programmes - I'll park this one for now. I'm not sure if "program flash memory" is the same as this?Sorry to waffle on.

author: Buriedcode
author_rank: Super Contributor
timestamp: July 13, 2018, 06:59:27 pm
content: The directive "equ" quite literally equates - it just allows one to assign a name to a value. This can be for variables - which are just address locations, or constants, which are just literal values. Which one depends on how you used that value.If you have:Code:pooname1 equ 0x20 ; replaces all instances of "pooname1" with 0x20pooname2 equ 35 ; replaces all instances of "pooname2" with 35, or 0x23Either can be a variable, but if we assume pooname1 is a variable, you can use it withCode:movf pooname1,w ; moves the contents of 0x20 memory location to the working regmovwf pooname1 ; moves the contents of the working reg to location 0x20but if its a constant, it can still be used:Code:movlw pooname1 ; move the literal value of pooname1 (0x20 in hex, or 32 in decimal) into the working regmovlw pooname2 ; move the literal value of pooname1 (0x23 in hex, or 35 in decimal) into the working regI believe "#define" is used in assembly in the same way it is for C. Similar to equ but.. it can be anything including a macro. I *think* equ is limited to just values. Eg:Code:#define LED1_ON bsf PORTB,0x03 ; Set bit 3 of portb where an LED is connectedLED1_ON;This can be a bit of a gotcha because if you make a mistake and use movlw instead of movf x,w - then you end up putting the address location into the W reg every time, regardless of what value is stored in that location. I could be wrong here, it's been a couple of decades since I did assembly - very few instances where it is required. I implore you to just switch directly to C - it makes life much easier and allows you to focus on practical things rather than spending much of your time moving stuff in and out of the W reg. And it really isn't that less efficient - a decent compiler like MikroC or even XC8 (if you set it up right) won't hog much program space.

author: jpanhalt
author_rank: Super Contributor
timestamp: July 13, 2018, 09:40:52 pm
content: An easy way to remember it is that an equate must be a value(number). A #define is just a text substitution. It can be anything, including a value, but if you use a symbol as a value, then you must define that value.QuoteFor example, this assembles fine with one error (noted):abc equ 0x33def equ time ;error: "symbol (time) not previously defined"#define ghi hours#define jkl 0x13But, if you then try this:movf ghi,w you get an error: "symbol not previously defined (hours)," but if you trymovf jkl,w there is no error because jkl is define as a value

author: PerranOak
author_rank: Frequent Contributor
timestamp: July 14, 2018, 11:29:54 am
content: That is fantastic thank you both very much.Is it better to put variables into linear memory?Is flash program memory the same as program memory? Presumably this area is not used for variables or constants?

author: jpanhalt
author_rank: Super Contributor
timestamp: July 14, 2018, 12:03:23 pm
content: Quote from: PerranOak on July 14, 2018, 11:29:54 amBetter? In what way? As we have stated many times, Linear Memory IS GP RAM. It's the same silicon, but mapped differently and accessed differently. It's only advantage is that the entire GP RAM is mapped to contiguous space. It is imaginary addresses, just like INDFn. Since none of us have a clue what you need to do, we cannot answer that question in the abstract. I am assuming you are new at this, and until you are comfortable using "pointers" (aka FSRn/INDFn registers), I will suggest not trying to use it. Just use GP RAM or Common RAM as that you already know how to access. By imaginary, you cannot watch it directly in a window. If you want to know what is at a particular location (i.e., where the FSRn is pointing) you need to do a movf INDFn or moviw instruction. For the moviw, read the datasheet.QuoteSame silicon, but again, accessed somewhat differently. You set bit 7 of the FSRn you are using which acts as a flag to tell the assembler to access the program memory as data. When (if) you use it, you will find that bit 7 is often set automatically; however, I suggest you do it in code at the start. I use it for tables (i.e., constants).I am assuming you are referring to use of program memory as described (i.e., all program memory in 16Fxxx chips is called "flash"). There is also memory specifically called flash program memory that operates much like EEPROM.

author: Buriedcode
author_rank: Super Contributor
timestamp: July 14, 2018, 02:35:48 pm
content: Quote from: PerranOak on July 14, 2018, 11:29:54 amWell variables can only go in SRAM and for the most part, just use the cblock macro (it will assign memory locations sequentially). I haven't used more modern 8-bitters with assembly so I am unsure of the memory structure of the RAM (banks). I would have thought if you have a large array that crosses a boundary - the compiler will point this out to you. A quick scan of the PIC16F1827 datasheet mentions the "linear data memory" you speak of, which appears to"allows buffers to be larger than 80 bytes because incrementing the FSR beyond one bank will go directly to the GPR memory of the next bank.".That just means when using the FSR (file select register) can be incremented/decremented through-out the entire RAM without worrying about switching banks.Side note: If you're unsure about using the FSR and INDF (indirect file register) then google indirect addressing - it is very handy for dealing with linear arrays and buffers. Briefly, you put the address of the location you want to read/write to in the FSR, and that makes the INDF register the register it points to. So for a linear array, you can simply increment/decrement the FSR to move up and down the array and read/write to the INDF register rather than deal with mnemonics. It appears that the FSR covers both data and program memory, which can be confusing.Quote from: PerranOak on July 14, 2018, 11:29:54 amYup. To both questions. These days as all program memory is flash, and they have provided the facility to self-write the flash, most PIC's can use a bootloader for programming.

author: jpanhalt
author_rank: Super Contributor
timestamp: July 14, 2018, 03:07:27 pm
content: Quote from: Buriedcode on July 14, 2018, 02:35:48 pmIt is actually a little more complicated than that, but the changes involve newer chips. Of course, the program is flash, and that very same memory can be used for data and accessed indirectly with FSRn. However, that memory cannot be written during run time. It is from that perspective that I initially answered PerranOak.However, I edited my comment on the chance that PerranOak had read the datasheet for newer PIC's (i.e, the 16F1827 he is using) and was wondering about another type of flash memory called HEF.(See my last sentence in previous post.)When the enhanced mid-range chips were introduced, e.g., 16F1516/7/8/9 family, Microchip introduced what it called at the time, High Endurance Flash memory (HEF flash). That was memory in the program space that could be reprogrammed at run time just like EEPROM. It seems the "HEF" term has been dropped, and the newest chips in the enhanced mid-range evolution include what is now called "Non Volatile Memory" (NVM, see 16F18856 for example).I have the eval board for that chip, but have not used it yet. Three things jump out based on a very brief review of its memory:1) It appears Microchip has dropped HEF as an identifier and effectively combined EEPROM with it to give NVM. They both (if that is still appropriate) use the same SFR registers to save and read the memory.2) Write cycles have been increased greatly.3) Access also can be by FSRn. I have not studied the datasheet carefully enough to know whether FSRn can be used to write, but my guess it that it cannot do that. Nevertheless, being able to read with FSRn will save bank switching.

author: PerranOak
author_rank: Frequent Contributor
timestamp: July 16, 2018, 02:27:28 pm
content: Thank you again both.Yes, I do seem to be struggling to get this into my brain! But I do have it nowlinear memory IS GP RAM!QuoteThis is what I was getting at. So, "flash program memory" and "program memory" are different: the former is like EEPROM and the latter is where the programme is stored?It's true that I haven't used indirect addressing yet but I wanted to be sure that I would not over-write my programme when I did.QuoteSo, it's the "program memory" that can't be accessed during run time but the "flash program memory" can be, like EEPROM? I can't quite see the use of memory that can't be accessed during run time.Is the "flash program memory" non-volatile?My project is a thermometer that samples every second or hour or whatever and then stores the data. I am using EEPROM which is non-volatile but can only store 256 data points. This is why I was looking at other methods but got caught-up in my linear memory/GP RAM confusion too.

author: JPortici
author_rank: Super Contributor
timestamp: July 16, 2018, 02:42:56 pm
content: Quote from: jpanhalt on July 14, 2018, 03:07:27 pmer.. no that's not correct.first, in these pics flash memory CAN certainly be programmed during runtime, otherwise bootloaders wouldn't be possible.In this aspect the difference between flash program memory and eeprom memory is that the core HALTS during flash memory erasing/programming, while it doesn't halt during eeprom erasing/programming.Actually, in devices with dual panel flash/memory partitioning the core halts if it's performing erase/write in the active partition, while is doesn't if erase/write happens in the inactive partition.The other two main differences between flash and eeprom are that flash is byte-erasable/writable, while flash is page-erasable and row-writable. you erase one whole page before being able to program one row (one row being N bytes, one page being M rows)And the other is that the endurance of flash is significantly lower than eeprom. we are talking of 100-10k erase/write cycles for flash compared to > 1M erase/write cycles for EEPROM.To mitigate this issue in lower cost devices with no eeprom (such as the PIC16F15xx series for example) the last page(s) of flash were so called "high endurance flash", which had an endurance in the order of 100k cycles, otherwise it is just flash, it's treated as such** in the pic18 K42 series and probably others you can configure the last x pages of flash to be a data storage area, nothing fancy if not that the device resets if it attempts to execute the memory in that area

author: jpanhalt
author_rank: Super Contributor
timestamp: July 16, 2018, 03:54:50 pm
content: Quote from: JPortici on July 16, 2018, 02:42:56 pmNo, it is row erasable, not page of "M" rows. I believe all chips are partial row writable, some can write a whole row. The 16F1827 can do either.Quote from: PIC161827 datasheetThe rows in that device are 32, 14-bit words long. Since that device has 32 write latches, it can write a whole row, not not all devices have that many data latches.I also ignored using a bootloader, as that would further cloud the issue.It appears the OP's questions have been answered.