/* * main.c - main C entry * by uratan! 2012.10.9 */ //#define __MAIN_C__ /* <== inform common.h to alloc variables */ #include "common.h" #include "LPC1830.h" /* * reset myself if SPIFI is configured unproperly */ #define ENABLE_SPIFI_RETRY 1 /* * for my interrupt vector table */ typedef void(*handler)(void); #define N_FAULTs 16 #define N_IRQs 64 #define N_VECTORs (N_FAULTs + N_IRQs) /* 16+64=80 ==> ..->32->64->[128]->256->.. */ handler my_vector_tab[N_VECTORs] __attribute__ ((aligned(128*4))); /* * */ typedef VOLATILE unsigned char v_u_c; /* * functions */ int main(void); void nops(void); void brchs(void) __attribute__ ((section (".romexec"))); void init_SW2_intr(void); void PINT0_IRQ_Handler(void) __attribute__ ((interrupt)); void init_my_vector_table(void); void set_my_vector(int n, handler hdlr_entry); void Exception_Handler(void) __attribute__ ((interrupt)); void NMI_Handler(void) __attribute__ ((interrupt)); void HardFault_Handler(void) __attribute__ ((interrupt)); void MemManage_Handler(void) __attribute__ ((interrupt)); void BusFault_Handler(void) __attribute__ ((interrupt)); void UsageFault_Handler(void) __attribute__ ((interrupt)); void SVCall_Handler(void) __attribute__ ((interrupt)); void DebugMon_Handler(void) __attribute__ ((interrupt)); void PendSV_Handler(void) __attribute__ ((interrupt)); void SysTick_Handler(void) __attribute__ ((interrupt)); /* in spifi.c */ extern void spifi_c_init(void); extern void spifi_set_clock(int try_18MHz); extern int spifi_initial_flash(void); /* * */ int main(void) { u_char c; int i, m; /* * setup LED2(green) and LED3(blue), and P2_7, P1_8, etc */ cm_initial_GPIO(); cm_init_uart(57600); /* * use GPIO3[5] (P6_9) for monitor */ #define SCU_SFS_P6_9 *(_v_u_l *)(LPC_SCU_BASE + 0x324) #define GPIO3_DIR *(_v_u_l *)(LPC_GPIO_BASE + 0x00c) #define GPIO3_SET *(_v_u_l *)(LPC_GPIO_BASE + 0x20c) #define GPIO3_CLR *(_v_u_l *)(LPC_GPIO_BASE + 0x28c) #define GPIO3_NOT *(_v_u_l *)(LPC_GPIO_BASE + 0x30c) #define G3_5_MONI (1 <<5) SCU_SFS_P6_9 = SFS_FUNC_0 | SFS_DisPUP | SFS_EnINPUT; GPIO3_DIR |= G3_5_MONI; GPIO3_SET = G3_5_MONI; rprintf( "" "\r\n" "/*" "\r\n" " * test SPIFI-flash" "\r\n" " */" "\r\n" "" "\r\n" ); rprintf("run @ 0x%08x (M3_MEMMAP: 0x%08x)\r\n", (u_long)main, M3_MEMMAP); rprintf("\r\n"); if(M3_MEMMAP >= 0x80000000) { /* * booted from SPIFI, confirm SPIFI initialization properness */ rprintf("IDIVB_CTRL is: 0x%08x\r\n", IDIVB_CTRL); #if ENABLE_SPIFI_RETRY if(IDIVB_CTRL != 0x09000820) { VOLATILE u_long t; rprintf("retry SPIFI\r\n"); for(t=0; t auto-clear */ while(1) ; } #endif /* ENABLE_SPIFI_RETRY */ } else { /* * maybe booted from USART3 */ spifi_c_init(); spifi_set_clock(/*try_18MHz=*/ 1); spifi_initial_flash(); } /* * prepare to generate interrupt by SW2 */ init_my_vector_table(); init_SW2_intr(); /* * start */ rprintf("select test\r\n"); while(1) { GPIO3_SET = G3_5_MONI; c = cm_getchar(); switch(c) { case 'c': rprintf("clear cache\r\n"); for(i=0; i<256; i++) { m = *(v_u_c *)(0x80100000 + i); } break; case '1': rprintf("test #1\r\n"); GPIO3_CLR = G3_5_MONI; for(i=0; i<16; i++) { m = *(v_u_c *)(0x80000000 + i); GPIO3_NOT = G3_5_MONI; } break; case '2': rprintf("test #2\r\n"); GPIO3_CLR = G3_5_MONI; for(i=0; i<16*16; i+=16) { m = *(v_u_c *)(0x80000000 + i); GPIO3_NOT = G3_5_MONI; } break; case '3': rprintf("test #3\r\n"); GPIO3_CLR = G3_5_MONI; for(i=0; i<16*16; i+=16) { m = *(v_u_c *)(0x8000000f + i); GPIO3_NOT = G3_5_MONI; } break; case '4': rprintf("test #4\r\n"); GPIO3_CLR = G3_5_MONI; for(i=0; i<16*8; i+=8) { m = *(v_u_c *)(0x80000000 + i); GPIO3_NOT = G3_5_MONI; } break; case '5': rprintf("test #5\r\n"); GPIO3_CLR = G3_5_MONI; for(i=0; i<16*8; i+=8) { m = *(v_u_c *)(0x80000007 + i); GPIO3_NOT = G3_5_MONI; } break; case 'z': rprintf("clear cache-z\r\n"); for(i=0; i<256; i++) { m = *(v_u_c *)(0x14100000 + i); } break; case 'a': rprintf("test #1a\r\n"); GPIO3_CLR = G3_5_MONI; for(i=0; i<16; i++) { m = *(v_u_c *)(0x14000000 + i); GPIO3_NOT = G3_5_MONI; } break; case 's': rprintf("test #2s\r\n"); GPIO3_CLR = G3_5_MONI; for(i=0; i<16*16; i+=16) { m = *(v_u_c *)(0x14000000 + i); GPIO3_NOT = G3_5_MONI; } break; case 'd': rprintf("test #3d\r\n"); GPIO3_CLR = G3_5_MONI; for(i=0; i<16*16; i+=16) { m = *(v_u_c *)(0x1400000f + i); GPIO3_NOT = G3_5_MONI; } break; case 'n': rprintf("run nops()\r\n"); GPIO3_CLR = G3_5_MONI; while(1) { nops(); GPIO3_NOT = G3_5_MONI; } break; /* never */ case 'b': rprintf("run brchs()\r\n"); GPIO3_CLR = G3_5_MONI; brchs(); break; default: break; } } /* never return */ } /* * */ void nops(void) { /* 256 bytes of nops to fill full of cache */ __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); /* a little more */ __asm("nop;nop;nop;nop;nop;nop;nop;nop;"); } /* * */ void brchs(void) { /* prepare to output monitor */ __asm(" ldr r1, =0x400f630c"); /* GPIO3_NOT */ __asm(" movs r5, #32"); /* G3_5_MONI */ /* tune phase vs 8byte boundary */ #define DELAY 0 switch(DELAY) { default: case 9: __asm("nop"); case 8: __asm("nop"); case 7: __asm("nop"); case 6: __asm("nop"); case 5: __asm("nop"); case 4: __asm("nop"); case 3: __asm("nop"); case 2: __asm("nop"); case 1: __asm("nop"); case 0: ; } /* * loop periods * DELAY | start from | period * -------------------------------- * 0 | 0000_00a4 | 35.00usec * 1 | 0000_00a6 | 35.01usec * 2 | 0000_00a8 | 34.51usec * 3 | 0000_00aa | 34.51usec * 4 | 0000_00ac | 35.01usec */ /* 256 bytes of branchs to fill full of cache */ /* the last half does not traced, so not loaded to cache */ __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); /* comment out this when you confirm some phase */ //__asm("str r5, [r1, #0];b .+14;nop;nop;nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); /* a little more (always back to -528 either above monitor is or not) */ __asm("b .+16;nop;nop;nop; nop;nop;nop;nop;"); __asm("b .-528; nop;nop;nop;nop;nop;nop;nop;"); /* make the executable same length */ switch(DELAY) { case 0: __asm("nop"); case 1: __asm("nop"); case 2: __asm("nop"); case 3: __asm("nop"); case 4: __asm("nop"); case 5: __asm("nop"); case 6: __asm("nop"); case 7: __asm("nop"); case 8: __asm("nop"); case 9: default: ; } /* never return */ } /* =============================================================== */ /* * for interrupt by GPIO pin */ #define PINT0_IRQn 32 #define SCU_PINTSEL0 *(_v_u_l *)(LPC_SCU_BASE + 0xE00) #define LPC_PINT_BASE 0x40087000 #define PINT_ISEL *(_v_u_l *)(LPC_PINT_BASE + 0x000) #define PINT_IENR *(_v_u_l *)(LPC_PINT_BASE + 0x004) #define PINT_IENF *(_v_u_l *)(LPC_PINT_BASE + 0x010) #define PINT_IST *(_v_u_l *)(LPC_PINT_BASE + 0x024) #define CM3_SCS_BASE 0xE000E000 #define NVIC_ISER1 *(_v_u_l *)(CM3_SCS_BASE + 0x104) #define NVIC_IPri32 *(v_u_c *)(CM3_SCS_BASE + 0x420) #define VTOR *(_v_u_l *)(CM3_SCS_BASE + 0xD08) /* * GPIO0[7] is driven by SW2 */ void init_SW2_intr(void) { /* setup the vector */ set_my_vector(PINT0_IRQn, PINT0_IRQ_Handler); /* connect GPIO0[7] to PINT0, configure for falling-edge intr */ SCU_PINTSEL0 = ((0<<5) | 7) <<0; /* GPIO_0_7 --> PINT0 */ PINT_ISEL &= ~(1 <<0); /* PINT0: edge sinsitive */ PINT_IENR &= ~(1 <<0); /* disable rising edge intr */ PINT_IENF |= (1 <<0); /* enable falling edge intr */ /* * registers about this PINTx is very complex, study more */ /* preemption = 1, sub-priority = 1 */ /* <== ??? */ NVIC_IPri32 = 0x50; /* enable interrupt, no need to read-modify-write */ NVIC_ISER1 = 1 <<(PINT0_IRQn -32); } /* * */ void PINT0_IRQ_Handler(void) { if(PINT_IST & (1 <<0)) { /* PINT0 request exist */ PINT_IST = (1 <<0); /* both edge intr cleared */ /* send trigger */ GPIO3_SET = G3_5_MONI; cm_putchar('!'); /* also make the pulse fat */ GPIO3_CLR = G3_5_MONI; } } /* =============================================================== */ /* * */ void init_my_vector_table(void) { int i; /* * setup my vector table */ for(i=0; i