ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
19 апреля
225851 Топик полностью
fk0, легенда (06.12.2010 16:27, просмотров: 300) ответил Vit на Трабла с запуском PIC24FJ64GB002 - под PICkit3 запускается, без - нет. Схема сброса - RC 10 кОм 0.1 uF (не помню точно - может быть 0.01), подключено через 470 Ом к MCLR, сброс от PICkit3 подключен через BAT54 (анодом к MCLR). Питаю
Немного отвлечённо, но общие соображения: 1) нельзя из C переключить OSCCON (ибо код получается разный с/без оптимизации и нет гарантии работы). 2) надо *всегда* программировать все FSR, особенно касающиеся конфигурации ног, с нуля как положено (в т.ч. и АЦП и т.п.) Я это делаю так всё: /* FUSE bits */ #ifdef __DEBUG #define CONFIG1 (GCP_OFF & BKBUG_OFF) #else #define CONFIG1 (GCP_ON & BKBUG_ON) #endif _CONFIG1(JTAGEN_OFF & CONFIG1 & GWRP_OFF & ICS_PGx2 & FWDTEN_ON & WINDIS_OFF & FWPSA_PR128 & WDTPS_PS32768); _CONFIG2(IESO_ON & FNOSC_FRC & FCKSM_CSECME & OSCIOFNC_OFF & IOL1WAY_ON & POSCMOD_XT); /* unlock OSCCONL, INTERRUPTS MUST BE DISABLED! * W1, W2, W3 will not be preserved! */ #define OSCCONL_UNLOCK() \ asm("mov #OSCCONL, W1"); \ asm("mov.b #0x46, W2"); \ asm("mov.b #0x57, W3"); \ asm("mov.b W2, [W1]"); \ asm("mov.b W3, [W1]"); /* unlock OSCONH, write desired clocking mode, then * unlock OSCCONL and switch frequency to desired mode, * INTERRUPTS MUST BE DISABLED! */ static void osccon_switch_clock(unsigned char mode) { /* unlock OSCCONH */ asm("mov #OSCCONH, W1"); asm("mov.b #0x78, W2"); asm("mov.b #0x9a, W3"); asm("mov.b W2, [W1]"); asm("mov.b W3, [W1]"); /* set new mode */ OSCCONH=mode; /* switch clock to new mode */ OSCCONL_UNLOCK(); OSCCONbits.OSWEN=1; } /* switch CPU clock to desired mode, no wait completion */ static void cpu_clock_switch(char mode) { int cpu_ipl; SET_AND_SAVE_CPU_IPL(cpu_ipl, 7); /* if PLL used -- at first switch to FRC without PLL! */ switch ((OSCCON>>12) & 7) { case 0: /* FRC */ case 2: /* Primary without PLL */ case 4: /* SOSC */ case 5: /* LPRC */ case 7: /* FRCDIV */ break; default: /* turn off PLL */ osccon_switch_clock(0); /* select FRC */ /* wait until switch complete */ while (OSCCONbits.OSWEN); } /* switch to desired mode (without PLL! see above) */ osccon_switch_clock(mode); RESTORE_CPU_IPL(cpu_ipl); } /* wait few milliseconds until quartz oscillator and PLL will be ready, * when check OSWEN and return non-zero error code if OSWEN is set */ static int check_xt_osc(void) { unsigned n; /* at highest speed we have ~16000 cycles per millisecond */ n=32767; do { asm("nop"); } while (--n); if (! OSCCONbits.OSWEN) return 0; if (! OSCCONbits.LOCK) return 2; // TODO define error codes else return 1; } /* set default/safe GPIO ports states */ static void gpio_set_safe(void) { /* disable pull-ups and pull-downs on ALL pins */ CNPU1=CNPU2=CNPU3=CNPU4=CNPU5=CNPU6=0; CNPD1=CNPD2=CNPD3=CNPD4=CNPD5=CNPD6=0; /* configure unused ADC pins as digital -- enabled AN1,3,4,9,10 */ AD1PCFGL=0xffff & ~(1<<1) & ~(1<<3) & ~(1<<4) & ~(1<<9) & ~(1<<10); AD1PCFGH=0xffff; /* PORTA */ LATA = 0; TRISA = 1<<15 | 1<<14; CNPU3bits.CN43PUE=1, CNPU3bits.CN44PUE=1; /* PORTB */ LATB = 1<<5 | 1<<8; TRISB = BIN(00100110)<<8 | BIN(11011010); CNPU2bits.CN31PUE=1; CNPU2bits.CN24PUE=1, CNPU2bits.CN25PUE=1; /* PGEC/PGED pull-up */ /* PORTC */ LATC = 0; TRISC = 1<<15 | 1<<14 | 1<<12 | 1<<1; /* PORTD */ LATD = 1<<15 | 1<<13; /* LATD8==0 !!! */ TRISD = 1<<14 | 1<<12 | 1<<10 | 1<<5 | 1<<2 | 1<<0; CNPU4bits.CN49PUE=1, CNPU4bits.CN57PUE=1, CNPU2bits.CN20PUE=1; /* PORTE */ LATE = 0; TRISE = 1<<9 | 1<<6 | 1<<5 | 1<<4 | 1<<3 | 1<<2; CNPU5bits.CN67PUE=1; /* PORTF */ LATF = 1<<7 | 1<<6; /* LATF0=0 ! */ TRISF = 1<<8 | 1<<2; /* PORTG */ LATG = 0; TRISG = 1<<7; } /* tune remappable peripheral */ static void remap_peripheral(void) { int cpu_ipl; SET_AND_SAVE_CPU_IPL(cpu_ipl, 7); /* disable interrupts */ /* unlock IOLOCK bit */ OSCCONL_UNLOCK(); OSCCONbits.IOLOCK=0; /* UART1 -- debug interface */ RPINR18bits.U1RXR = 34; /* RPI34 */ RPOR9bits.RP18R = 3; /* U1TX */ /* UART2 -- modem */ RPINR19bits.U2RXR = 43; RPOR2bits.RP5R = 5; /* U2TX */ /* UART3 -- GPS */ RPINR17bits.U3RXR = 26; RPOR10bits.RP21R = 28; /* U3TX */ /* SPI */ RPOR11bits.RP22R = 8; /* SCK1OUT */ RPOR12bits.RP25R = 7; /* SDO1 */ RPINR20bits.SDI1R = 42; /* OC1, OC2 -- LEDs */ /* unused now */ /* OC3, OC4 -- sound */ RPOR12bits.RP24R = 20; /* OC3 */ RPOR9bits.RP19R = 21; /* OC4 */ /* disable future remapping */ OSCCONL_UNLOCK(); OSCCONbits.IOLOCK=1; RESTORE_CPU_IPL(cpu_ipl); } /* this function called before C runtime initialization * to configure hardware as soon as possible. * XXX: variables will not be initilized whem this function called! */ void __attribute__((user_init)) hardware_init(void) { SET_CPU_IPL(7); /* disable interrupts except level 7 */ asm("CLRWDT"); remap_peripheral(); /* XXX NOTE: именно здесь, в этой функции отключаются * и включаются АЦП, настроиваются ноги на ввод-вывод -- * функция вызывается практически сразу после старта * микроконтроллера (до инициализации C-рантайма, * до медленного запуска PLL и т.п.) */ gpio_set_safe(); [...] /* primary oscillator with PLL -- запускается основной * генератор и не дожидаясь ничего происходит возврат * в C-стартап для инициализации C-рантайма */ cpu_clock_switch(0x03); } int main() { int i; asm("CLRWDT"); signal(SIGABRT, aborted); /* В main первым делом проверяется, что генератор и PLL * работает как положено, иначе предпринимаются меры * по аварийной индикации... */ i=check_xt_osc(); if (i) _Exit(ERR_OSC_FAIL); [...] } Запуск функции hardware_init() обеспечивается модифицированным C-стартапом (там была опция --data-init, но она вызывала функцию после инициализации C-рантайма, а не до -- что неадекватно, потому, что на внутреннем генераторе оно запускается долго и за это время все релюшки поклацают и т.п., а они в hardware_init() выключаются): ;; C Run-time startup module for dsPIC30 C compiler. ;; (c) Copyright 2002,2004,2007 Microchip Technology, All rights reserved ;; 1. initialize stack and stack limit register ;; 2. initialize PSV window if __const_length > 0 ;; 3. call the .user_init section, if it exists XXX fk0: call user_init first! ;; 4. process the data initialization template ;; 5. call the user's _main entry point ;; Assigned to section .init, which may be allocated ;; at a specific address in linker scripts. ;; If a local copy of this file is customized, be sure ;; to choose a file name other than crt0.s or crt1.s. .section .init,code .global __resetPRI .ifdef __C30ELF .type __resetPRI,@function .endif __resetPRI: .weak __reset .ifdef __C30ELF .type __reset,@function .endif __reset: ;; Initialize stack, PSV, and data ;; registers used: w0 ;; Inputs (defined by user or linker): ;; __SP_init ;; __SPLIM_init ;; Outputs: ;; (does not return - resets the processor) ;; Calls: ;; __psv_init ;; __data_init ;; _main .weak __user_init, __has_user_init mov #__SP_init,w15 ; initialize w15 mov #__SPLIM_init,w0 ; mov w0,_SPLIM ; initialize SPLIM nop ; wait 1 cycle rcall __psv_init ; initialize PSV mov #__has_user_init,w0 cp0 w0 ; user init functions? bra eq,1f ; br if not call __user_init ; else call them 1: rcall __data_init ; initialize data call _main ; call user's main() .pword 0xDA4000 ; halt the simulator reset ; reset the processor .global __psv_init __psv_init: ;; Initialize PSV window if _constlen > 0 ;; Registers used: w0 ;; Inputs (defined by linker): ;; __const_length ;; __const_psvpage ;; Outputs: ;; (none) ;; .equiv PSV, 0x0002 bclr _CORCON,#PSV ; disable PSV (default) mov #__const_length,w0 ; cp0 w0 ; test length of constants bra z,1f ; br if zero mov #__const_psvpage,w0 ; mov w0,_PSVPAG ; PSVPAG = psvpage(constants) bset _CORCON,#PSV ; enable PSV 1: return ; and exit .global __data_init __data_init: ;; Process data init template ;; The template is null-terminated, with records ;; in the following format: ;; struct data_record { ;; char *dst; /* destination address */ ;; int len; /* length in bytes */ ;; int format; /* format code */ ;; char dat[0]; /* variable length data */ ;; }; ;; ;; Registers used: w0 w1 w2 w3 w4 w5 ;; ;; Inputs (defined by linker): ;; __dinit_tbloffset ;; __dinit_tblpage ;; ;; Outputs: ;; (none) ;; ;; Calls: ;; __memcpypd3 ;; .equiv FMT_CLEAR,0 ; format codes .equiv FMT_COPY2,1 ; .equiv FMT_COPY3,2 ; mov #__dinit_tbloffset,w0 ; w0,w1 = template mov #__dinit_tblpage,w1 ; bra 4f ; br to continue 1: add w0,#2,w0 ; template+=2 addc w1,#0,w1 ; mov w1,_TBLPAG ; TBLPAG = tblpage(template) tblrdl.w [w0],w3 ; w3 = len add w0,#2,w0 ; template+=2 addc w1,#0,w1 ; mov w1,_TBLPAG ; TBLPAG = tblpage(template) tblrdl.w [w0],w5 ; w5 = format add w0,#2,w0 ; template+=2 addc w1,#0,w1 ; clr w4 ; upper = FALSE (default) cp w5,#FMT_CLEAR ; test format bra nz,2f ; br if not FMT_CLEAR ;; FMT_CLEAR - clear destination memory 9: clr.b [w2++] ; clear memory dec w3,w3 ; done? bra gtu,9b ; loop if not bra 4f ; br to continue ;; FMT_COPY2, FMT_COPY3 - copy bytes 2: cp w5,#FMT_COPY2 ; test format bra z,3f ; br if FMT_COPY2 setm w4 ; upper = TRUE 3: rcall __memcpypd3 ; copy 2 or 3 bytes 4: mov w1,_TBLPAG ; TBLPAG = tblpage(template) tblrdl.w [w0],w2 ; w2 = next dst cp0 w2 ; bra nz,1b ; loop on non-zero dst retlw #0,w0 ; exit (clears ARGC also) __memcpypd3: ;; ;; Copy data from program memory to data memory ;; ;; Registers used: w0 w1 w2 w3 w4 w5 ;; ;; Inputs: ;; w0,w1 = source address (24 bits) ;; w2 = destination address (16 bits) ;; w3 = number of bytes (even or odd) ;; w4 = upper byte flag (0 = false) ;; ;; Outputs: ;; w0,w1 = next source address (24 bits) ;; 1: mov w1,_TBLPAG ; TBLPAG = tblpage(src) mov w0,w5 ; w5 = tbloffset(src) add w0,#2,w0 ; src+=2 addc w1,#0,w1 ; tblrdl.b [w5++],[w2++] ; dst++ = lo byte dec w3,w3 ; num-- bra z,2f ; br if done tblrdl.b [w5--],[w2++] ; dst++ = hi byte dec w3,w3 ; num-- bra z,2f ; br if done cp0 w4 ; test upper flag bra z,1b ; br if false tblrdh.b [w5],[w2++] ; dst++ = upper byte dec w3,w3 ; num-- bra nz,1b ; br if not done 2: return ; exit .end
[ZX]