mirror of
https://git.code.sf.net/p/newrpl/sources
synced 2024-11-16 19:51:25 +01:00
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)
This commit is contained in:
parent
8a1657f442
commit
341e4f329e
6 changed files with 55 additions and 62 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) while(*TICKCNT>=start); // Wait for the counter to wrap
|
||||
|
||||
while(*TICKCNT<end); // And wait for the timer count to reach the end
|
||||
}
|
||||
|
||||
// Do a single delay 100 usec
|
||||
// Do a single delay 10 msec
|
||||
void __tmr_delay10ms()
|
||||
{
|
||||
*TCNTB4= (__LLTIMER_FREQ * 10) / 1000;
|
||||
*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 * 10) / 1000;
|
||||
|
||||
while((*TCNTO4&0xffff)!=0); // And wait for the timer to count to zero
|
||||
if(end<start) while(*TICKCNT>=start); // Wait for the counter to wrap
|
||||
|
||||
while(*TICKCNT<end); // And wait for the timer count to reach the end
|
||||
}
|
||||
|
||||
// Do a single delay 100 usec
|
||||
void __tmr_delay20ms()
|
||||
{
|
||||
*TCNTB4= (__LLTIMER_FREQ * 20) / 1000;
|
||||
*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 * 20) / 1000;
|
||||
|
||||
while((*TCNTO4&0xffff)!=0); // And wait for the timer to count to zero
|
||||
if(end<start) while(*TICKCNT>=start); // Wait for the counter to wrap
|
||||
|
||||
while(*TICKCNT<end); // And wait for the timer count to reach the end
|
||||
}
|
||||
|
||||
// Prepare for an open loop timeout
|
||||
void __tmr_setuptimeoutms(int delayms,unsigned int *start,unsigned int *end)
|
||||
{
|
||||
*start = *TICKCNT;
|
||||
*end = *TICKCNT + (__LLTIMER_FREQ * delayms) / 1000;
|
||||
}
|
||||
|
||||
// Check if clock timed out or not
|
||||
int __tmr_timedout(unsigned int start,unsigned int end)
|
||||
{
|
||||
if(end<start) if(*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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue