1 /*-------------------------------------------------------------------------
3 device.c - Accomodates subtle variations in PIC16 devices
5 Written By - Scott Dattalo scott@dattalo.com
6 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
25 VR - Began writing code to make PIC16 C source files independent from
26 the header file (created by the inc2h.pl)
28 - adding maximum RAM memory into PIC_Device structure
34 #include "common.h" // Include everything in the SDCC src directory
42 #if defined(__BORLANDC__) || defined(_MSC_VER)
43 #define STRCASECMP stricmp
45 #define STRCASECMP strcasecmp
48 static PIC_device Pics[] = {
50 {"p18f242", "18f242", "pic18f242", "f242"}, // aliases
51 (memRange *)NULL, // ram memory map
52 (memRange *)NULL, // sfr memory map
60 {"p18f252", "18f252", "pic18f252", "f252"}, // aliases
61 (memRange *)NULL, // ram memory map
62 (memRange *)NULL, // sfr memory map
70 {"p18f442", "18f442", "pic18f442", "f442"}, // aliases
71 (memRange *)NULL, // ram memory map
72 (memRange *)NULL, // sfr memory map
80 {"p18f452", "18f452", "pic18f452", "f452"}, // aliases
81 (memRange *)NULL, // ram memory map
82 (memRange *)NULL, // sfr memory map
90 {"p18f248", "18f248", "pic18f248", "f248"}, // aliases
91 (memRange *)NULL, // ram memory map
92 (memRange *)NULL, // sfr memory map
100 {"p18f258", "18f258", "pic18f258", "f258"}, // aliases
101 (memRange *)NULL, // ram memory map
102 (memRange *)NULL, // sfr memory map
110 {"p18f448", "18f448", "pic18f448", "f448"}, // aliases
111 (memRange *)NULL, // ram memory map
112 (memRange *)NULL, // sfr memory map
120 {"p18f458", "18f458", "pic18f458", "f458"}, // aliases
121 (memRange *)NULL, // ram memory map
122 (memRange *)NULL, // sfr memory map
130 {"p18f6520", "18f6520", "pic18f6520", "f6520"}, // aliases
131 (memRange *)NULL, // ram memory map
132 (memRange *)NULL, // sfr memory map
140 {"p18f6620", "18f6620", "pic18f6620", "f6620"}, // aliases
141 (memRange *)NULL, // ram memory map
142 (memRange *)NULL, // sfr memory map
149 {"p18f6680", "18f6680", "pic18f6680", "f6680"}, // aliases
150 (memRange *)NULL, // ram memory map
151 (memRange *)NULL, // sfr memory map
158 {"p18f6720", "18f6720", "pic18f6720", "f6720"}, // aliases
159 (memRange *)NULL, // ram memory map
160 (memRange *)NULL, // sfr memory map
167 {"p18f8520", "18f8520", "pic18f8520", "f8520"}, // aliases
168 (memRange *)NULL, // ram memory map
169 (memRange *)NULL, // sfr memory map
176 {"p18f8620", "18f8620", "pic18f8620", "f8620"}, // aliases
177 (memRange *)NULL, // ram memory map
178 (memRange *)NULL, // sfr memory map
185 {"p18f8680", "18f8680", "pic18f8680", "f8680"}, // aliases
186 (memRange *)NULL, // ram memory map
187 (memRange *)NULL, // sfr memory map
194 {"p18f8720", "18f8720", "pic18f8720", "f8720"}, // aliases
195 (memRange *)NULL, // ram memory map
196 (memRange *)NULL, // sfr memory map
205 static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
207 #define DEFAULT_PIC "452"
209 static PIC_device *pic=NULL;
211 AssignedMemory *pic16_finalMapping=NULL;
212 int pic16_finalMappingSize=0;
214 #define DEFAULT_CONFIG_BYTE 0xff
216 #define CONFIG1H_WORD_ADDRESS 0x300001
217 #define DEFAULT_CONFIG1H_WORD DEFAULT_CONFIG_BYTE
219 #define CONFIG2L_WORD_ADDRESS 0x300002
220 #define DEFAULT_CONFIG2L_WORD DEFAULT_CONFIG_BYTE
222 #define CONFIG2H_WORD_ADDRESS 0x300003
223 #define DEFAULT_CONFIG2H_WORD DEFAULT_CONFIG_BYTE
225 #define CONFIG3H_WORD_ADDRESS 0x300005
226 #define DEFAULT_CONFIG3H_WORD DEFAULT_CONFIG_BYTE
228 #define CONFIG4L_WORD_ADDRESS 0x300006
229 #define DEFAULT_CONFIG4L_WORD DEFAULT_CONFIG_BYTE
231 #define CONFIG5L_WORD_ADDRESS 0x300008
232 #define DEFAULT_CONFIG5L_WORD DEFAULT_CONFIG_BYTE
234 #define CONFIG5H_WORD_ADDRESS 0x300009
235 #define DEFAULT_CONFIG5H_WORD DEFAULT_CONFIG_BYTE
237 #define CONFIG6L_WORD_ADDRESS 0x30000a
238 #define DEFAULT_CONFIG6L_WORD DEFAULT_CONFIG_BYTE
240 #define CONFIG6H_WORD_ADDRESS 0x30000b
241 #define DEFAULT_CONFIG6H_WORD DEFAULT_CONFIG_BYTE
243 #define CONFIG7L_WORD_ADDRESS 0x30000c
244 #define DEFAULT_CONFIG7L_WORD DEFAULT_CONFIG_BYTE
246 #define CONFIG7H_WORD_ADDRESS 0x30000d
247 #define DEFAULT_CONFIG7H_WORD DEFAULT_CONFIG_BYTE
249 static unsigned int config1h_word = DEFAULT_CONFIG1H_WORD;
250 static unsigned int config2l_word = DEFAULT_CONFIG2L_WORD;
251 static unsigned int config2h_word = DEFAULT_CONFIG2H_WORD;
252 static unsigned int config3h_word = DEFAULT_CONFIG3H_WORD;
253 static unsigned int config4l_word = DEFAULT_CONFIG4L_WORD;
254 static unsigned int config5l_word = DEFAULT_CONFIG5L_WORD;
255 static unsigned int config5h_word = DEFAULT_CONFIG5H_WORD;
256 static unsigned int config6l_word = DEFAULT_CONFIG6L_WORD;
257 static unsigned int config6h_word = DEFAULT_CONFIG6H_WORD;
258 static unsigned int config7l_word = DEFAULT_CONFIG7L_WORD;
259 static unsigned int config7h_word = DEFAULT_CONFIG7H_WORD;
261 void pic16_addMemRange(memRange *r, int type)
264 int alias = r->alias;
266 if (pic->maxRAMaddress < 0) {
267 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
271 // fprintf(stderr, "%s: adding memory range from 0x%x to 0x%x type= %d\n",
272 // __FUNCTION__, r->start_address, r->end_address, type);
275 for (i=r->start_address; i<= r->end_address; i++) {
276 if ((i|alias) <= pic->maxRAMaddress) {
277 pic16_finalMapping[i | alias].isValid = 1;
278 pic16_finalMapping[i | alias].alias = r->alias;
279 pic16_finalMapping[i | alias].bank = r->bank;
282 pic16_finalMapping[i | alias].isSFR = 1;
284 pic16_finalMapping[i | alias].isSFR = 0;
287 fprintf(stderr, "WARNING: %s:%s memory at 0x%x is beyond max ram = 0x%x\n",
288 __FILE__,__FUNCTION__,(i|alias), pic->maxRAMaddress);
292 /* Decrement alias */
294 alias -= ((alias & (alias - 1)) ^ alias);
299 } while (alias >= 0);
302 void pic16_setMaxRAM(int size)
305 pic->maxRAMaddress = size;
307 if (pic->maxRAMaddress < 0) {
308 fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
313 pic16_finalMapping = Safe_calloc(1+pic->maxRAMaddress,
314 sizeof(AssignedMemory));
316 /* Now initialize the pic16_finalMapping array */
318 for(i=0; i<=pic->maxRAMaddress; i++) {
319 pic16_finalMapping[i].reg = NULL;
320 pic16_finalMapping[i].isValid = 0;
324 /*-----------------------------------------------------------------*
325 *-----------------------------------------------------------------*/
327 int pic16_isREGinBank(regs *reg, int bank)
333 if(pic16_finalMapping[reg->address].bank == bank)
339 /*-----------------------------------------------------------------*
340 *-----------------------------------------------------------------*/
341 int pic16_REGallBanks(regs *reg)
347 if (reg->address > pic->maxRAMaddress)
354 /*-----------------------------------------------------------------*
355 *-----------------------------------------------------------------*/
358 * pic16_dump_map -- debug stuff
361 void pic16_dump_map(void)
365 for(i=0; i<=pic->maxRAMaddress; i++) {
366 //fprintf(stdout , "addr 0x%02x is %s\n", i, ((pic16_finalMapping[i].isValid) ? "valid":"invalid"));
368 if(pic16_finalMapping[i].isValid) {
369 fprintf(stderr,"addr: 0x%02x",i);
370 if(pic16_finalMapping[i].isSFR)
371 fprintf(stderr," isSFR");
372 if(pic16_finalMapping[i].reg)
373 fprintf( stderr, " reg %s", pic16_finalMapping[i].reg->name);
374 fprintf(stderr, "\n");
380 void pic16_dump_cblock(FILE *of)
386 //pic16_dump_map(); /* display the register map */
388 if (pic->maxRAMaddress < 0) {
389 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
395 if(pic16_finalMapping[addr].reg && !pic16_finalMapping[addr].reg->isEmitted
396 && pic16_finalMapping[addr].reg->wasUsed) {
403 /* clear the lower 7-bits of the start address of the first
404 * variable declared in this bank. The upper bits for the mid
405 * range pics are the bank select bits.
408 bank_base = start & 0xfff8;
410 /* The bank number printed in the cblock comment tacitly
411 * assumes that the first register in the contiguous group
412 * of registers represents the bank for the whole group */
414 if ((pic16_finalMapping[start].bank == 0 && start <= 0x7f) ||
415 pic16_finalMapping[start].isSFR)
416 fprintf(of," cblock 0X%04X\t; Access Bank\n",start);
418 fprintf(of," cblock 0X%04X\t; Bank %d\n",start,pic16_finalMapping[start].bank);
420 for( ; start < addr; start++) {
421 if((pic16_finalMapping[start].reg) && !pic16_finalMapping[start].reg->isEmitted ) {
422 fprintf(of,"\t%s",pic16_finalMapping[start].reg->name);
424 /* If this register is aliased in multiple banks, then
425 * mangle the variable name with the alias address: */
426 if(pic16_finalMapping[start].alias & start)
427 fprintf(of,"_%x",bank_base);
429 if(pic16_finalMapping[start].instance)
430 fprintf(of,"_%d",pic16_finalMapping[start].instance);
435 //#warning why is the following line commented out?! (VR)
436 // pic16_finalMapping[start].reg->isEmitted = 1;
440 fprintf(of," endc\n");
449 } while(addr <= pic->maxRAMaddress);
454 /*-----------------------------------------------------------------*
455 * void pic16_list_valid_pics(int ncols, int list_alias)
457 * Print out a formatted list of valid PIC devices
459 * ncols - number of columns in the list.
461 * list_alias - if non-zero, print all of the supported aliases
462 * for a device (e.g. F84, 16F84, etc...)
463 *-----------------------------------------------------------------*/
464 void pic16_list_valid_pics(int ncols, int list_alias)
470 list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
472 /* decrement the column number if it's greater than zero */
473 ncols = (ncols > 1) ? ncols-1 : 4;
475 /* Find the device with the longest name */
476 for(i=0,longest=0; i<num_of_supported_PICS; i++) {
477 for(j=0; j<=list_alias; j++) {
478 k = strlen(Pics[i].name[j]);
486 for(i=0; i < num_of_supported_PICS; i++) {
490 fprintf(stderr,"%s", Pics[i].name[j]);
492 l = longest + 2 - strlen(Pics[i].name[j]);
503 } while(++j<list_alias);
511 /*-----------------------------------------------------------------*
513 *-----------------------------------------------------------------*/
514 PIC_device *pic16_find_device(char *name)
522 for(i = 0; i<num_of_supported_PICS; i++) {
524 for(j=0; j<PROCESSOR_NAMES; j++)
525 if(!STRCASECMP(Pics[i].name[j], name) )
533 /*-----------------------------------------------------------------*
535 *-----------------------------------------------------------------*/
536 void pic16_init_pic(char *pic_type)
538 pic = pic16_find_device(pic_type);
542 fprintf(stderr, "'%s' was not found.\n", pic_type);
544 fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
546 fprintf(stderr,"Valid devices are:\n");
548 pic16_list_valid_pics(4,0);
552 pic->maxRAMaddress = -1;
555 /*-----------------------------------------------------------------*
557 *-----------------------------------------------------------------*/
558 int pic16_picIsInitialized(void)
560 if(pic && pic->maxRAMaddress > 0)
567 /*-----------------------------------------------------------------*
568 * char *pic16_processor_base_name(void) - Include file is derived from this.
569 *-----------------------------------------------------------------*/
570 char *pic16_processor_base_name(void)
579 static int isSFR(int address)
582 if( (address > pic->maxRAMaddress) || !pic16_finalMapping[address].isSFR)
589 /*-----------------------------------------------------------------*
590 *-----------------------------------------------------------------*/
591 static int validAddress(int address, int reg_size)
595 if (pic->maxRAMaddress < 0) {
596 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
599 // fprintf(stderr, "validAddress: Checking 0x%04x (max=0x%04x) (reg_size = %d)\n",address, pic->maxRAMaddress, reg_size);
600 if(address > pic->maxRAMaddress)
603 for (i=0; i<reg_size; i++)
604 if(!pic16_finalMapping[address + i].isValid ||
605 pic16_finalMapping[address+i].reg ||
606 pic16_finalMapping[address+i].isSFR )
612 /*-----------------------------------------------------------------*
613 *-----------------------------------------------------------------*/
614 static void mapRegister(regs *reg)
620 if(!reg || !reg->size) {
621 fprintf(stderr,"WARNING: %s:%s:%d Bad register\n",__FILE__,__FUNCTION__,__LINE__);
625 if (pic->maxRAMaddress < 0) {
626 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
630 for(i=0; i<reg->size; i++) {
632 alias = pic16_finalMapping[reg->address].alias;
637 // fprintf(stdout,"mapping %s to address 0x%02x, reg size = %d\n",reg->name, (reg->address+alias+i),reg->size);
639 pic16_finalMapping[reg->address + alias + i].reg = reg;
640 pic16_finalMapping[reg->address + alias + i].instance = i;
642 /* Decrement alias */
644 alias -= ((alias & (alias - 1)) ^ alias);
651 // fprintf(stderr,"%s - %s addr = 0x%03x, size %d\n",__FUNCTION__,reg->name, reg->address,reg->size);
657 /*-----------------------------------------------------------------*
658 *-----------------------------------------------------------------*/
659 static int assignRegister(regs *reg, int start_address)
663 // fprintf(stderr,"%s - %s start_address = 0x%03x\t(max=0x%03x)\n",__FUNCTION__,reg->name, start_address, pic->maxRAMaddress);
666 if (validAddress(reg->address,reg->size)) {
667 // fprintf(stderr,"fixed %s - %s address = 0x%03x\n",__FUNCTION__,reg->name, reg->address);
672 if( isSFR(reg->address)) {
673 // fprintf(stderr,"sfr %s - %s address = 0x%03x\n",__FUNCTION__,reg->name, reg->address);
678 //fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
679 // reg->address, reg->name);
683 /* This register does not have a fixed address requirement
684 * so we'll search through all availble ram address and
685 * assign the first one */
687 for (i=start_address; i<=pic->maxRAMaddress; i++) {
689 if (validAddress(i,reg->size)) {
690 // fprintf(stderr, "found valid address = 0x%04x\n", i);
697 fprintf(stderr, "WARNING: No more RAM available for %s\n",reg->name);
704 /*-----------------------------------------------------------------*
705 *-----------------------------------------------------------------*/
706 void pic16_assignFixedRegisters(set *regset)
710 for (reg = setFirstItem(regset) ; reg ;
711 reg = setNextItem(regset)) {
714 assignRegister(reg,0);
719 /*-----------------------------------------------------------------*
720 *-----------------------------------------------------------------*/
721 void pic16_assignRelocatableRegisters(set *regset, int used)
727 for (reg = setFirstItem(regset) ; reg ;
728 reg = setNextItem(regset)) {
730 //fprintf(stdout,"assigning %s isFixed=%d, wasUsed=%d\n",reg->name,reg->isFixed,reg->wasUsed);
732 if((!reg->isFixed) && (used || reg->wasUsed))
733 address = assignRegister(reg,address);
740 /*-----------------------------------------------------------------*
741 * void pic16_assignConfigWordValue(int address, int value)
743 * All high performance RISC CPU PICs have seven config word starting
744 * at address 0x300000.
745 * This routine will assign a value to that address.
747 *-----------------------------------------------------------------*/
749 void pic16_assignConfigWordValue(int address, int value)
752 case CONFIG1H_WORD_ADDRESS:
753 config1h_word = value;
755 case CONFIG2L_WORD_ADDRESS:
756 config2l_word = value;
758 case CONFIG2H_WORD_ADDRESS:
759 config2h_word = value;
761 case CONFIG3H_WORD_ADDRESS:
762 config3h_word = value;
764 case CONFIG4L_WORD_ADDRESS:
765 config4l_word = value;
767 case CONFIG5L_WORD_ADDRESS:
768 config5l_word = value;
770 case CONFIG5H_WORD_ADDRESS:
771 config5h_word = value;
773 case CONFIG6L_WORD_ADDRESS:
774 config6l_word = value;
776 case CONFIG6H_WORD_ADDRESS:
777 config6h_word = value;
779 case CONFIG7L_WORD_ADDRESS:
780 config7l_word = value;
782 case CONFIG7H_WORD_ADDRESS:
783 config7h_word = value;
787 //fprintf(stderr,"setting config word to 0x%x\n",value);
790 /*-----------------------------------------------------------------*
791 * int pic16_getConfigWord(int address)
793 * Get the current value of the config word.
795 *-----------------------------------------------------------------*/
797 int pic16_getConfigWord(int address)
800 case CONFIG1H_WORD_ADDRESS:
801 return config1h_word;
802 case CONFIG2L_WORD_ADDRESS:
803 return config2l_word;
804 case CONFIG2H_WORD_ADDRESS:
805 return config2h_word;
806 case CONFIG3H_WORD_ADDRESS:
807 return config3h_word;
808 case CONFIG4L_WORD_ADDRESS:
809 return config4l_word;
810 case CONFIG5L_WORD_ADDRESS:
811 return config5l_word;
812 case CONFIG5H_WORD_ADDRESS:
813 return config5h_word;
814 case CONFIG6L_WORD_ADDRESS:
815 return config6l_word;
816 case CONFIG6H_WORD_ADDRESS:
817 return config6h_word;
818 case CONFIG7L_WORD_ADDRESS:
819 return config7l_word;
820 case CONFIG7H_WORD_ADDRESS:
821 return config7h_word;