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 #include "common.h" // Include everything in the SDCC src directory
33 #if defined(__BORLANDC__) || defined(_MSC_VER)
34 #define STRCASECMP stricmp
36 #define STRCASECMP strcasecmp
39 static PIC_device Pics[] = {
41 {"p18f242", "18f242", "pic18f242", "f242"},
49 {"p18f252", "18f252", "pic18f252", "f252"},
57 {"p18f442", "18f442", "pic18f442", "f442"},
65 {"p18f452", "18f452", "pic18f452", "f452"},
74 static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
76 #define DEFAULT_PIC "f452"
78 static PIC_device *pic=NULL;
80 AssignedMemory *pic16_finalMapping=NULL;
81 int pic16_finalMappingSize=0;
83 #define DEFAULT_CONFIG_BYTE 0xff
85 #define CONFIG1H_WORD_ADDRESS 0x300001
86 #define DEFAULT_CONFIG1H_WORD DEFAULT_CONFIG_BYTE
88 #define CONFIG2L_WORD_ADDRESS 0x300002
89 #define DEFAULT_CONFIG2L_WORD DEFAULT_CONFIG_BYTE
91 #define CONFIG2H_WORD_ADDRESS 0x300003
92 #define DEFAULT_CONFIG2H_WORD DEFAULT_CONFIG_BYTE
94 #define CONFIG3H_WORD_ADDRESS 0x300005
95 #define DEFAULT_CONFIG3H_WORD DEFAULT_CONFIG_BYTE
97 #define CONFIG4L_WORD_ADDRESS 0x300006
98 #define DEFAULT_CONFIG4L_WORD DEFAULT_CONFIG_BYTE
100 #define CONFIG5L_WORD_ADDRESS 0x300008
101 #define DEFAULT_CONFIG5L_WORD DEFAULT_CONFIG_BYTE
103 #define CONFIG5H_WORD_ADDRESS 0x300009
104 #define DEFAULT_CONFIG5H_WORD DEFAULT_CONFIG_BYTE
106 #define CONFIG6L_WORD_ADDRESS 0x30000a
107 #define DEFAULT_CONFIG6L_WORD DEFAULT_CONFIG_BYTE
109 #define CONFIG6H_WORD_ADDRESS 0x30000b
110 #define DEFAULT_CONFIG6H_WORD DEFAULT_CONFIG_BYTE
112 #define CONFIG7L_WORD_ADDRESS 0x30000c
113 #define DEFAULT_CONFIG7L_WORD DEFAULT_CONFIG_BYTE
115 #define CONFIG7H_WORD_ADDRESS 0x30000d
116 #define DEFAULT_CONFIG7H_WORD DEFAULT_CONFIG_BYTE
118 static unsigned int config1h_word = DEFAULT_CONFIG1H_WORD;
119 static unsigned int config2l_word = DEFAULT_CONFIG2L_WORD;
120 static unsigned int config2h_word = DEFAULT_CONFIG2H_WORD;
121 static unsigned int config3h_word = DEFAULT_CONFIG3H_WORD;
122 static unsigned int config4l_word = DEFAULT_CONFIG4L_WORD;
123 static unsigned int config5l_word = DEFAULT_CONFIG5L_WORD;
124 static unsigned int config5h_word = DEFAULT_CONFIG5H_WORD;
125 static unsigned int config6l_word = DEFAULT_CONFIG6L_WORD;
126 static unsigned int config6h_word = DEFAULT_CONFIG6H_WORD;
127 static unsigned int config7l_word = DEFAULT_CONFIG7L_WORD;
128 static unsigned int config7h_word = DEFAULT_CONFIG7H_WORD;
130 void pic16_addMemRange(memRange *r, int type)
133 int alias = r->alias;
135 if (pic->maxRAMaddress < 0) {
136 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
141 for (i=r->start_address; i<= r->end_address; i++) {
142 if ((i|alias) <= pic->maxRAMaddress) {
143 pic16_finalMapping[i | alias].isValid = 1;
144 pic16_finalMapping[i | alias].alias = r->alias;
145 pic16_finalMapping[i | alias].bank = r->bank;
148 pic16_finalMapping[i | alias].isSFR = 1;
150 pic16_finalMapping[i | alias].isSFR = 0;
153 fprintf(stderr, "WARNING: %s:%s memory at 0x%x is beyond max ram = 0x%x\n",
154 __FILE__,__FUNCTION__,(i|alias), pic->maxRAMaddress);
158 /* Decrement alias */
160 alias -= ((alias & (alias - 1)) ^ alias);
165 } while (alias >= 0);
168 void pic16_setMaxRAM(int size)
171 pic->maxRAMaddress = size;
173 if (pic->maxRAMaddress < 0) {
174 fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
179 pic16_finalMapping = Safe_calloc(1+pic->maxRAMaddress,
180 sizeof(AssignedMemory));
182 /* Now initialize the pic16_finalMapping array */
184 for(i=0; i<=pic->maxRAMaddress; i++) {
185 pic16_finalMapping[i].reg = NULL;
186 pic16_finalMapping[i].isValid = 0;
190 /*-----------------------------------------------------------------*
191 *-----------------------------------------------------------------*/
193 int pic16_isREGinBank(regs *reg, int bank)
199 if(pic16_finalMapping[reg->address].bank == bank)
205 /*-----------------------------------------------------------------*
206 *-----------------------------------------------------------------*/
207 int pic16_REGallBanks(regs *reg)
213 if (reg->address > pic->maxRAMaddress)
220 /*-----------------------------------------------------------------*
221 *-----------------------------------------------------------------*/
224 * pic16_dump_map -- debug stuff
227 void pic16_dump_map(void)
231 for(i=0; i<=pic->maxRAMaddress; i++) {
232 //fprintf(stdout , "addr 0x%02x is %s\n", i, ((pic16_finalMapping[i].isValid) ? "valid":"invalid"));
234 if(pic16_finalMapping[i].isValid) {
235 fprintf(stderr,"addr: 0x%02x",i);
236 if(pic16_finalMapping[i].isSFR)
237 fprintf(stderr," isSFR");
238 if(pic16_finalMapping[i].reg)
239 fprintf( stderr, " reg %s", pic16_finalMapping[i].reg->name);
240 fprintf(stderr, "\n");
246 void pic16_dump_cblock(FILE *of)
252 //pic16_dump_map(); /* display the register map */
254 if (pic->maxRAMaddress < 0) {
255 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
261 if(pic16_finalMapping[addr].reg && !pic16_finalMapping[addr].reg->isEmitted) {
268 /* clear the lower 7-bits of the start address of the first
269 * variable declared in this bank. The upper bits for the mid
270 * range pics are the bank select bits.
273 bank_base = start & 0xfff8;
275 /* The bank number printed in the cblock comment tacitly
276 * assumes that the first register in the contiguous group
277 * of registers represents the bank for the whole group */
279 if ((pic16_finalMapping[start].bank == 0 && start <= 0x7f) ||
280 pic16_finalMapping[start].isSFR)
281 fprintf(of," cblock 0X%04X\t; Access Bank\n",start);
283 fprintf(of," cblock 0X%04X\t; Bank %d\n",start,pic16_finalMapping[start].bank);
285 for( ; start < addr; start++) {
286 if((pic16_finalMapping[start].reg) && !pic16_finalMapping[start].reg->isEmitted ) {
287 fprintf(of,"\t%s",pic16_finalMapping[start].reg->name);
289 /* If this register is aliased in multiple banks, then
290 * mangle the variable name with the alias address: */
291 if(pic16_finalMapping[start].alias & start)
292 fprintf(of,"_%x",bank_base);
294 if(pic16_finalMapping[start].instance)
295 fprintf(of,"_%d",pic16_finalMapping[start].instance);
300 //#warning why is the following line commented out?! (VR)
301 // pic16_finalMapping[start].reg->isEmitted = 1;
305 fprintf(of," endc\n");
314 } while(addr <= pic->maxRAMaddress);
319 /*-----------------------------------------------------------------*
320 * void pic16_list_valid_pics(int ncols, int list_alias)
322 * Print out a formatted list of valid PIC devices
324 * ncols - number of columns in the list.
326 * list_alias - if non-zero, print all of the supported aliases
327 * for a device (e.g. F84, 16F84, etc...)
328 *-----------------------------------------------------------------*/
329 void pic16_list_valid_pics(int ncols, int list_alias)
335 list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
337 /* decrement the column number if it's greater than zero */
338 ncols = (ncols > 1) ? ncols-1 : 4;
340 /* Find the device with the longest name */
341 for(i=0,longest=0; i<num_of_supported_PICS; i++) {
342 for(j=0; j<=list_alias; j++) {
343 k = strlen(Pics[i].name[j]);
351 for(i=0; i < num_of_supported_PICS; i++) {
355 fprintf(stderr,"%s", Pics[i].name[j]);
357 l = longest + 2 - strlen(Pics[i].name[j]);
368 } while(++j<list_alias);
376 /*-----------------------------------------------------------------*
378 *-----------------------------------------------------------------*/
379 PIC_device *pic16_find_device(char *name)
387 for(i = 0; i<num_of_supported_PICS; i++) {
389 for(j=0; j<PROCESSOR_NAMES; j++)
390 if(!STRCASECMP(Pics[i].name[j], name) )
398 /*-----------------------------------------------------------------*
400 *-----------------------------------------------------------------*/
401 void pic16_init_pic(char *pic_type)
403 pic = pic16_find_device(pic_type);
407 fprintf(stderr, "'%s' was not found.\n", pic_type);
409 fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
411 fprintf(stderr,"Valid devices are:\n");
413 pic16_list_valid_pics(4,0);
417 pic->maxRAMaddress = -1;
420 /*-----------------------------------------------------------------*
422 *-----------------------------------------------------------------*/
423 int pic16_picIsInitialized(void)
425 if(pic && pic->maxRAMaddress > 0)
432 /*-----------------------------------------------------------------*
433 * char *pic16_processor_base_name(void) - Include file is derived from this.
434 *-----------------------------------------------------------------*/
435 char *pic16_processor_base_name(void)
444 static int isSFR(int address)
447 if( (address > pic->maxRAMaddress) || !pic16_finalMapping[address].isSFR)
454 /*-----------------------------------------------------------------*
455 *-----------------------------------------------------------------*/
456 static int validAddress(int address, int reg_size)
460 if (pic->maxRAMaddress < 0) {
461 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
464 // fprintf(stderr, "validAddress: Checking 0x%04x (max=0x%04x) (reg_size = %d)\n",address, pic->maxRAMaddress, reg_size);
465 if(address > pic->maxRAMaddress)
468 for (i=0; i<reg_size; i++)
469 if(!pic16_finalMapping[address + i].isValid ||
470 pic16_finalMapping[address+i].reg ||
471 pic16_finalMapping[address+i].isSFR )
477 /*-----------------------------------------------------------------*
478 *-----------------------------------------------------------------*/
479 static void mapRegister(regs *reg)
485 if(!reg || !reg->size) {
486 fprintf(stderr,"WARNING: %s:%s:%d Bad register\n",__FILE__,__FUNCTION__,__LINE__);
490 if (pic->maxRAMaddress < 0) {
491 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
495 for(i=0; i<reg->size; i++) {
497 alias = pic16_finalMapping[reg->address].alias;
502 // fprintf(stdout,"mapping %s to address 0x%02x, reg size = %d\n",reg->name, (reg->address+alias+i),reg->size);
504 pic16_finalMapping[reg->address + alias + i].reg = reg;
505 pic16_finalMapping[reg->address + alias + i].instance = i;
507 /* Decrement alias */
509 alias -= ((alias & (alias - 1)) ^ alias);
516 // fprintf(stderr,"%s - %s addr = 0x%03x, size %d\n",__FUNCTION__,reg->name, reg->address,reg->size);
522 /*-----------------------------------------------------------------*
523 *-----------------------------------------------------------------*/
524 static int assignRegister(regs *reg, int start_address)
528 //fprintf(stderr,"%s - %s start_address = 0x%03x\n",__FUNCTION__,reg->name, start_address);
531 if (validAddress(reg->address,reg->size)) {
532 //fprintf(stderr,"%s - %s address = 0x%03x\n",__FUNCTION__,reg->name, reg->address);
537 if( isSFR(reg->address)) {
542 //fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
543 // reg->address, reg->name);
547 /* This register does not have a fixed address requirement
548 * so we'll search through all availble ram address and
549 * assign the first one */
551 for (i=start_address; i<=pic->maxRAMaddress; i++) {
553 if (validAddress(i,reg->size)) {
554 // fprintf(stderr, "found valid address = 0x%04x\n", i);
561 fprintf(stderr, "WARNING: No more RAM available for %s\n",reg->name);
568 /*-----------------------------------------------------------------*
569 *-----------------------------------------------------------------*/
570 void pic16_assignFixedRegisters(set *regset)
574 for (reg = setFirstItem(regset) ; reg ;
575 reg = setNextItem(regset)) {
578 assignRegister(reg,0);
583 /*-----------------------------------------------------------------*
584 *-----------------------------------------------------------------*/
585 void pic16_assignRelocatableRegisters(set *regset, int used)
591 for (reg = setFirstItem(regset) ; reg ;
592 reg = setNextItem(regset)) {
594 //fprintf(stdout,"assigning %s isFixed=%d, wasUsed=%d\n",reg->name,reg->isFixed,reg->wasUsed);
596 if((!reg->isFixed) && (used || reg->wasUsed))
597 address = assignRegister(reg,address);
604 /*-----------------------------------------------------------------*
605 * void pic16_assignConfigWordValue(int address, int value)
607 * All high performance RISC CPU PICs have seven config word starting
608 * at address 0x300000.
609 * This routine will assign a value to that address.
611 *-----------------------------------------------------------------*/
613 void pic16_assignConfigWordValue(int address, int value)
616 case CONFIG1H_WORD_ADDRESS:
617 config1h_word = value;
619 case CONFIG2L_WORD_ADDRESS:
620 config2l_word = value;
622 case CONFIG2H_WORD_ADDRESS:
623 config2h_word = value;
625 case CONFIG3H_WORD_ADDRESS:
626 config3h_word = value;
628 case CONFIG4L_WORD_ADDRESS:
629 config4l_word = value;
631 case CONFIG5L_WORD_ADDRESS:
632 config5l_word = value;
634 case CONFIG5H_WORD_ADDRESS:
635 config5h_word = value;
637 case CONFIG6L_WORD_ADDRESS:
638 config6l_word = value;
640 case CONFIG6H_WORD_ADDRESS:
641 config6h_word = value;
643 case CONFIG7L_WORD_ADDRESS:
644 config7l_word = value;
646 case CONFIG7H_WORD_ADDRESS:
647 config7h_word = value;
651 //fprintf(stderr,"setting config word to 0x%x\n",value);
654 /*-----------------------------------------------------------------*
655 * int pic16_getConfigWord(int address)
657 * Get the current value of the config word.
659 *-----------------------------------------------------------------*/
661 int pic16_getConfigWord(int address)
664 case CONFIG1H_WORD_ADDRESS:
665 return config1h_word;
666 case CONFIG2L_WORD_ADDRESS:
667 return config2l_word;
668 case CONFIG2H_WORD_ADDRESS:
669 return config2h_word;
670 case CONFIG3H_WORD_ADDRESS:
671 return config3h_word;
672 case CONFIG4L_WORD_ADDRESS:
673 return config4l_word;
674 case CONFIG5L_WORD_ADDRESS:
675 return config5l_word;
676 case CONFIG5H_WORD_ADDRESS:
677 return config5h_word;
678 case CONFIG6L_WORD_ADDRESS:
679 return config6l_word;
680 case CONFIG6H_WORD_ADDRESS:
681 return config6h_word;
682 case CONFIG7L_WORD_ADDRESS:
683 return config7l_word;
684 case CONFIG7H_WORD_ADDRESS:
685 return config7h_word;