From 341e4f329e783689486b6bdd5ad5ae8d1045c377 Mon Sep 17 00:00:00 2001 From: claudiol Date: Thu, 27 May 2021 18:10:16 -0400 Subject: [PATCH] Used RTC tick counter for low level delays. Added timeout on NAND operations. Removed tmrsetup() calls from all drivers (no setup needed, added to boot_prime.c) --- firmware/include/target_prime1.h | 6 +- firmware/sys/target_prime1/boot_prime1.c | 7 +- firmware/sys/target_prime1/lcd.c | 2 - firmware/sys/target_prime1/nand.c | 14 +++- firmware/sys/target_prime1/timer.c | 85 ++++++++++-------------- firmware/sys/target_prime1/usbdriver.c | 3 - 6 files changed, 55 insertions(+), 62 deletions(-) diff --git a/firmware/include/target_prime1.h b/firmware/include/target_prime1.h index 26126ed..385aaf6 100644 --- a/firmware/include/target_prime1.h +++ b/firmware/include/target_prime1.h @@ -877,13 +877,17 @@ extern void ts_init(); #define PIXELS_PER_WORD 8 // LOW LEVEL TIMER FUNCTIONS FOR HARDWARE SETUP -void __tmr_setupdelay(); + // Do a single delay 100 usec void __tmr_delay100us(); // Do a single delay 10 msec void __tmr_delay10ms(); // Do a single delay 20 msec void __tmr_delay20ms(); +// Prepare for an open loop timeout +void __tmr_setuptimeoutms(int delayms,unsigned int *start,unsigned int *end); +// Check if clock timed out or not +int __tmr_timedout(unsigned int start,unsigned int end); // OTHER ADDITIONAL HARDWARE FUNCTIONS diff --git a/firmware/sys/target_prime1/boot_prime1.c b/firmware/sys/target_prime1/boot_prime1.c index c44c040..819fa12 100644 --- a/firmware/sys/target_prime1/boot_prime1.c +++ b/firmware/sys/target_prime1/boot_prime1.c @@ -225,9 +225,6 @@ void setup_hardware() lcd_off(); - // Playing it safe for testing - - NANDWriteProtect(); - *PWRCFG |= 0x20000; // Enable Wait for Interrupt mode // Disable SoC blocks that we don't use @@ -236,6 +233,10 @@ void setup_hardware() *PCLKCON &= ~0x8034e; // Disable PCLK going to SPI_HS0, AC97, I2S0, and PCM audio interfaces *SCLKCON &= ~0xa05242; // Disable special clocks to HSMMC0, I2S0, PCM0, SPI, USB Host + *RTCCON = 0x10; // RTC clock set to defaults, plus tick counter at 1/32768 second + *TICNT0 = 0x80; // Enable tick interrupt, counter to zero (make TICKCNT tick at 32.768 kHz) + *TICNT1 = 0; // Counter to zero + *TICNT2 = 0; // Counter to zero } diff --git a/firmware/sys/target_prime1/lcd.c b/firmware/sys/target_prime1/lcd.c index 65f6347..22bbd2d 100644 --- a/firmware/sys/target_prime1/lcd.c +++ b/firmware/sys/target_prime1/lcd.c @@ -339,8 +339,6 @@ int lcd_setmode(int mode, unsigned int *physbuf) void lcd_poweron() { - __tmr_setupdelay(); // SETUP TIMERS TO GET ACCURATE DELAYS - // Setup GPIO *GPCCON = (*GPCCON&0xfc00) | 0xaaaa02aa; // ALL GPC PINS SET FOR LCD FUNCTION diff --git a/firmware/sys/target_prime1/nand.c b/firmware/sys/target_prime1/nand.c index 897998a..1887223 100644 --- a/firmware/sys/target_prime1/nand.c +++ b/firmware/sys/target_prime1/nand.c @@ -104,7 +104,12 @@ static inline void NANDEnableChipSelect(void) static inline void NANDWaitReady(void) { - while ((*NFSTAT & NFSTAT_RnB_TransDetect) == 0); + unsigned int start,end; + // Flash datasheet lists Block Erase as the longest operation with a max. 10 ms + // So in 12 ms it MUST have finished or there was an error. + __tmr_setuptimeoutms(12,&start,&end); + + while ((*NFSTAT & NFSTAT_RnB_TransDetect) == 0) if(__tmr_timedout(start,end)) return; } static inline void NANDClearReady(void) @@ -511,12 +516,17 @@ int NANDBlockErase(uint32_t nand_address) *NFCMMD = NAND_CMD_BLOCK_ERASE2nd; + red_led_on(); + NANDWaitReady(); + blue_led_on(); + // NOTE BL2 does not check NFSTAT_IllegalAccess here if (NANDCheckWrite() == 0) { retval = 0; } + green_led_on(); NANDDisableChipSelect(); @@ -592,7 +602,7 @@ int NANDWrite(uint32_t virtual_address, uint8_t const *source_address, unsigned uint32_t nand_write_address = NANDTranslateVirtualAddress(block_start); - if (offset != 0 || num_bytes < NAND_BLOCK_SIZE) { + if ( (offset != 0) || (num_bytes < NAND_BLOCK_SIZE)) { if (NANDReadBlock(nand_write_address, nand_buffer) == 0) { return 0; } diff --git a/firmware/sys/target_prime1/timer.c b/firmware/sys/target_prime1/timer.c index 8ccaa31..7cdb83e 100644 --- a/firmware/sys/target_prime1/timer.c +++ b/firmware/sys/target_prime1/timer.c @@ -455,74 +455,57 @@ void tmr_eventkill(HEVENT event) // INDEPENDENT TIMING FUNCTIONS THAT DON'T DEPEND ON INTERRUPTS OR THE TIMER MODULE TO BE INITIALIZED TO WORK // USED MAINLY FOR HARDWARE SETUP THAT NEEDS ACCURATE TIMING -// Setup TIMER 4 for delays in LCD chip communications -#define __LLTIMER_FREQ 100000 // 100 kHz tick - - - - -void __tmr_setupdelay() -{ - unsigned int pclk = __cpu_getPCLK(); - - unsigned int divider, prescaler; - - prescaler = (pclk << 3) / __LLTIMER_FREQ; - divider = 1; - - while(prescaler > (1 << (11 + divider))) { - divider++; - } - - prescaler += (1 << (2 + divider)); - prescaler >>= divider + 3; - -//if(divider>4) PCLK TOO HIGH TO ACHIEVE TIMER FREQUENCY, USE HIGHER MULTIPLE - if(divider > 4) - divider = 4; - -// SET PRESCALER VALUES FOR TIMERS 2,3 AND 4 - *TCFG0 = (*TCFG0 & (~0xFF00)) | ((prescaler - 1)<<8); - *TCFG1 = - (*TCFG1 & (~0xf0000)) | ((divider - 1) << 16); - -// SET COUNT VALUES TO MAXIMUM - *TCNTB4 = 0xffff; - -// Make sure no interrupts are fired by timer4 - *INTMSK1 |= 0x4000; -} +// Use RTC tick counter for delays in LCD chip communications +#define __LLTIMER_FREQ 32768 // 32.768 kHz tick // Do a single delay 100 usec void __tmr_delay100us() { - *TCNTB4= (__LLTIMER_FREQ * 100) / 1000000; - *TCON= (*TCON&~0x700000) | 0x200000; // Update the count - *TCON= (*TCON&~0x700000) | 0x100000; // Start the timer, single shot + unsigned int start,end; + start = *TICKCNT; + end = *TICKCNT + (__LLTIMER_FREQ * 100) / 1000000; - while((*TCNTO4&0xffff)!=0); // And wait for the timer to count to zero + if(end=start); // Wait for the counter to wrap + + while(*TICKCNT=start); // Wait for the counter to wrap + + while(*TICKCNT=start); // Wait for the counter to wrap + + while(*TICKCNT=start) return 0; // Wait for the counter to wrap - + if(*TICKCNT>=end) return 1; // And wait for the timer count to reach the end + return 0; +} diff --git a/firmware/sys/target_prime1/usbdriver.c b/firmware/sys/target_prime1/usbdriver.c index 3b83e76..d48b622 100644 --- a/firmware/sys/target_prime1/usbdriver.c +++ b/firmware/sys/target_prime1/usbdriver.c @@ -378,9 +378,6 @@ static void usb_reset_full(void) void usb_hwsetup() { - __tmr_setupdelay(); // SETUP SOME TIMERS TO GET ACCURATE DELAYS - - // POWER OFF FIRST TO CAUSE A FULL RESET OF THE USB BLOCK *UCLKCON &= ~0x80000000; // SIGNAL THE HOST A DEVICE HAS BEEN DISCONNECTED