FreeCalypso > hg > freecalypso-reveng
view frbl/reconst/boot.c @ 336:9805020b6834
frbl/README added
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 07 Mar 2020 06:54:17 +0000 |
parents | 4e1d7ce0ee71 |
children |
line wrap: on
line source
/****************************************************************************** * FLUID (Flash Loader Utility Independent of Device) * * (C) Delta Technologies 2001. * Cleanup, modifications and extensions by Mads Meisner-Jensen, mmj@ti.com. * * Target Bootloader * * $Id: boot.c 1.18 Mon, 28 Apr 2003 08:49:16 +0200 tsj $ * ******************************************************************************/ #include "chipset.cfg" #include "target.h" #define DEBUG_TRACE 0 // Protocol version of this bootloader // Version 0: Original, unmodified Delta Technology Bootloader. // Version 1: First Fluid Bootloader. 'B'audrate command and 'V'ersion // command. Backward compatibly with version 0. // Version 2: 'H'ardware chipset query command. Debug/Trace // functionality. Backward compatibly with version 0, 1. Fixed bug where // IND$CALL was used to start command interpreter instead of private jump() // function // Version 3: Generic 'Q'uery command. Discontinued 'H'ardware query command // from version 2. #define BOOTLOADER_VERSION '3' /****************************************************************************** * Bootstrap/Init ******************************************************************************/ // Initialize stackpointer according to chipset. Note that we ALWAYS do // this, no matter if we were laoded with JTAG or if we were compiled-in. #if (CHIPSET == 3) asm("STACK_INIT .equ 03000000h"); asm("STACK_ADD .equ 00020000h ; 128kB"); #elif (CHIPSET == 7 || CHIPSET == 8 || CHIPSET == 10 || CHIPSET == 11) asm("STACK_INIT .equ 00800000h"); asm("STACK_ADD .equ 00020000h ; 128kB"); #elif (CHIPSET == 12) asm("STACK_INIT .equ 08000000h"); asm("STACK_ADD .equ 00020000h ; 128kB"); #else #error Unknown target hardware selected #endif #ifdef FLUID_BOOT_STAND_ALONE asm(" .def _c_int00 "); asm("_c_int00:"); #endif asm(" .state32 "); asm(" mov sp,#STACK_INIT"); asm(" add sp,sp,#STACK_ADD"); asm(" adr lr,start_end + 1 ; module end address with lsb set"); asm(" bx lr ; branch to start"); asm(" nop"); asm("start_end:"); /****************************************************************************** * Main ******************************************************************************/ uint32 uart_base; void jump(uint32, uint32); static void putchar(uint8 ch); uint8 getchar(void); void uart_init(UBYTE dlh, UBYTE dll); void hardware_init(uint16 *code); void fluid_bootloader(void) { uint8 ch; uint16 *mem; union32_t addr; union16_t size; union16_t data; uint8 uart_dlh, uart_dll; uint16 chip_id_code; hardware_init(&chip_id_code); uart_base = UART_BASE_MODEM; uart_init(0, 0x07); // baudrate = 115200kbps uart_base = UART_BASE_IRDA; uart_init(0, 0x07); // baudrate = 115200kbps #ifdef TESTBOOT while (1) { uart_base = UART_BASE_MODEM; if ((REGISTER_8_READ(uart_base + UART_LSR) & STAT_RXRDY)) break; uart_base = UART_BASE_IRDA; if ((REGISTER_8_READ(uart_base + UART_LSR) & STAT_RXRDY)) break; } while (getchar() != 0xAA) ; while (getchar() != 0x01) ; while (getchar() != 0xDD) ; #endif while (1) { uart_base = UART_BASE_MODEM; putchar(PROTO_HELLO); if ((REGISTER_8_READ(uart_base + UART_LSR) & STAT_RXRDY)) break; uart_base = UART_BASE_IRDA; putchar(PROTO_HELLO); if ((REGISTER_8_READ(uart_base + UART_LSR) & STAT_RXRDY)) break; } while (1) { ch = getchar(); switch (ch) { case PROTO_VERSION: putchar(BOOTLOADER_VERSION); break; /* FreeCalypso reconstruction of TCS211 boot.obj */ case PROTO_HARDWARE: putchar('0'); break; /* end FC reconstruction */ case PROTO_QUERY: ch = getchar(); if (ch == PROTO_QUERY_CHIP) { data.i = chip_id_code; putchar(data.b[0]); putchar(data.b[1]); putchar(0); putchar(0); } else { putchar(PROTO_ERROR); } break; case PROTO_BAUDRATE: ch = getchar(); // Get DLH case 0: uart_init(ch, getchar()); break; case PROTO_DOWNLOAD: addr.b[0] = getchar(); addr.b[1] = getchar(); addr.b[2] = getchar(); addr.b[3] = getchar(); size.b[0] = getchar(); size.b[1] = getchar(); putchar(PROTO_READY); mem = (uint16 *) addr.i; while (size.i--) { // Data bytes arrive in reverse order due to little endian mode data.b[1] = getchar(); data.b[0] = getchar(); *mem++ = data.i; } #if DEBUG_TRACE // Insert convenient tracing here... #endif // Start the program we loaded. jump(uart_base, addr.i); break; default: putchar(PROTO_ERROR); } } } // Little assembly function that makes a jump to the address/argument, // similar to the compiler's IND$CALL. We do not use the compiler's IND$CALL // because when we compile for non-standalone, IND$CALL is already // defined. We expect that the base address of the UART is in R0, so it can // be properly passed on to the command interpreter. asm("$jump:"); asm(" bx r1"); static void putchar(uint8 ch) { PUTCHAR_FUNCTION_CODE(uart_base) } uint8 getchar(void) { GETCHAR_FUNCTION_CODE(uart_base) } /****************************************************************************** * Initialization ******************************************************************************/ #if (CHIPSET == 3) #define IQ_MASK (0xFFFFFA02) /* Mask Interrupt Register */ #elif (CHIPSET == 7 || CHIPSET == 8 || CHIPSET == 10 || CHIPSET == 11) \ || (CHIPSET == 12) #define IQ_MASK1 (0xFFFFFA08) /* Mask Interrupt Register 1 */ #define IQ_MASK2 (0xFFFFFA0A) /* Mask Interrupt Register 2 */ #else #error Unknown target hardware selected #endif /* FreeCalypso reconstruction: definition missing from TCS211 target.h */ #define CHIP_ID_CODE 0xFFFEF000 void hardware_init(uint16 *chip_id_code) { uint16 clk; char chip_set = 0; // We read the chipset version directly from the hardware because // otherwise the stand-alone bootloader (to be downloaded with JTAG) is // obviously not target independent! *chip_id_code = *((volatile uint16 *) CHIP_ID_CODE); // We should only intialize the hardware if we were downloaded with JTAG #ifdef FLUID_BOOT_STAND_ALONE // FIXME: we should perhaps have different init depending on chipset // detected? // Mask all interrupts #if (CHIPSET == 3) *((volatile uint16 *) IQ_MASK) = 0xFFFF; #elif (CHIPSET == 7 || CHIPSET == 8 || CHIPSET == 10 || CHIPSET == 11) *((volatile uint16 *) IQ_MASK1) = 0xFFFF; *((volatile uint16 *) IQ_MASK2) = 0x001F; #elif (CHIPSET == 12) *((volatile uint16 *) IQ_MASK1) = 0xFFFF; *((volatile uint16 *) IQ_MASK2) = 0xFFFF; //BJO Check IRQ_29_MSK - should it be 0 ? #endif // Disable watchdog timer *((volatile uint16 *) WATCHDOG_TIM_MODE) = 0xF5; *((volatile uint16 *) WATCHDOG_TIM_MODE) = 0xA0; #if (CHIPSET == 12) //BJO Check this (documented?) *((volatile uint16 *) WATCHDOG_TIM_MODE+80) = 0xF5; // Secure watchdog CALPLUS *((volatile uint16 *) WATCHDOG_TIM_MODE+80) = 0xA0; // Secure watchdog CALPLUS #endif #if (CHIPSET == 3) || (CHIPSET == 7 || CHIPSET == 8 || CHIPSET == 10 || CHIPSET == 11) // FIXME: Describe exactly how the CSs are initialized *((volatile uint16 *) CS0_MEM_REG) = 0x2A1; *((volatile uint16 *) CS1_MEM_REG) = 0x2A1; *((volatile uint16 *) CS2_MEM_REG) = 0x2A1; *((volatile uint16 *) CS3_MEM_REG) = 0x283; *((volatile uint16 *) CS4_MEM_REG) = 0x283; *((volatile uint16 *) CS6_MEM_REG) = 0x2C0; #elif (CHIPSET == 12) *((volatile uint16 *) CS0_MEM_REG) = 0x2A3; //*BJO Check these settings *((volatile uint16 *) CS1_MEM_REG) = 0x2A3; *((volatile uint16 *) CS2_MEM_REG) = 0x2A3; *((volatile uint16 *) CS3_MEM_REG) = 0x2A3; *((volatile uint16 *) CS4_MEM_REG) = 0x2A3; *((volatile uint16 *) CS5_MEM_REG) = 0x2A3; #endif #if (CHIPSET == 3) clk = *(volatile uint16 *) CLKM_CNTL_ARM_CLK; clk &= ~(0x0C | 0x30); clk |= (2 << 4); *(volatile uint16 *) CLKM_CNTL_ARM_CLK = clk; #elif (CHIPSET == 7 || CHIPSET == 8 || CHIPSET == 10 || CHIPSET == 11) // Reset DPLL register * (volatile uint16 *) MEM_DPLL_ADDR = DPLL_RESET_VALUE; // Wait that DPLL is in BYPASS mode while (((* (volatile uint16 *) MEM_DPLL_ADDR) & 1) != 1) ; // Reset CLKM register *(volatile uint16 *) MEM_CLKM_ADDR = CLKM_CNTL_ARM_CLK_RST; #elif (CHIPSET == 12) *((volatile uint8*)CTNL_CLK) = 0x91; // Make sure we are set to 26MHz mode (div 2) // CALPLUS *((volatile uint16 *) MEM_DPLL_ADDR) = 0x6012 | (8<<7) | (1<<5); // multiplyer=8, divider=2 (-1) 52MHz!!! // CALPLUS // Wait that DPLL is locked while (((* (volatile unsigned short *) MEM_DPLL_ADDR) & 1) != 1) ; // CALPLUS #endif #endif // ifdef FLUID_BOOT_STAND_ALONE } void uart_init(uint8 my_dlh, uint8 my_dll) { uint8 ch; /* * Transition from the DSP Rhea bus to the MCU Rhea bus. */ BIT_SET (UART_UIR, UART_MASK_IT); BIT_CLR (UART_UIR, UART_ACCESS); BIT_CLR (UART_UIR, UART_MASK_IT); /* * Set the UART in reset mode. */ REGISTER_8_WRITE(uart_base + UART_MDR1, CMD_UART_RESET); /* * FIFO configuration */ REGISTER_8_WRITE(uart_base + UART_LCR, CMD_EFR_EN); BIT_SET (uart_base + UART_EFR, ENHANCED_EN); REGISTER_8_WRITE(uart_base + UART_LCR, CMD_FCR_MCR_EN); REGISTER_8_WRITE(uart_base + UART_FCR, CMD_FIFO_EN); /* * Speed configuration */ REGISTER_8_WRITE(uart_base + UART_LCR, CMD_EFR_EN); REGISTER_8_WRITE(uart_base + UART_DLL, my_dll); REGISTER_8_WRITE(uart_base + UART_DLH, my_dlh); /* * Character format configuration */ REGISTER_8_WRITE(uart_base + UART_LCR, CMD_CHAR8_STOP1_NOPAR); /* * Modem configuration */ REGISTER_8_WRITE(uart_base + UART_MDR1, CMD_UART_MODE); /* * Flush Rx buffer */ while ((REGISTER_8_READ(uart_base + UART_LSR) & STAT_RXRDY)) ch = (REGISTER_8_READ(uart_base + UART_RHR)); } /****************************************************************************** * Debug ******************************************************************************/ #if (DEBUG_TRACE == 1) #include "debug.c" #endif