From: Robin Krens Date: Thu, 18 Jul 2019 16:55:33 +0000 (+0800) Subject: uart small ping pong receive, update of register functions X-Git-Url: https://robinkrens.nl/gitweb/?a=commitdiff_plain;h=e9d02925e4e4cd03ef878ad9b4af6c94f1cac9cc;p=cortex-from-scratch uart small ping pong receive, update of register functions no priorities, so one handler might keep 霸占 the CPU --- diff --git a/Makefile b/Makefile index 9eba3b4..c4803b9 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,8 @@ all: $(CC) $(CFLAGS) -c -I./include -ffreestanding -o sysinfo.o sysinfo.c $(CC) $(CFLAGS) -c -I./include -ffreestanding -o lib.o lib.c $(CC) $(CFLAGS) -c -I./include -ffreestanding -o mm.o mm.c - $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o ivt.o systick.o sysinfo.o lib.o mm.o + $(CC) $(CFLAGS) -c -I./include -ffreestanding -o regf.o regf.c + $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o ivt.o systick.o sysinfo.o lib.o mm.o regf.o $(MKIMG) -Obinary -R .data start.out kernel.bin run: diff --git a/include/mmap.h b/include/mmap.h index 6fa4adc..d0f9338 100644 --- a/include/mmap.h +++ b/include/mmap.h @@ -6,12 +6,11 @@ * * */ - #define BSS_BASE ((volatile uint32_t *)(0x20000800)) //TODO: .data flexible siz #define TOTAL_MEM_SIZE 64000; /* SYSTEM INFO AND DEBUG */ -#define MCU_ID ((volatile uint32_t*)( 0xE0042000)) +#define MCU_ID ((volatile uint32_t*)( 0xE000ED00)) #define FLASH_MEM ((volatile uint32_t*)( 0x1FFFF000)) /* SYSTEM CONTROL BLOCK REGISTER */ @@ -19,6 +18,7 @@ /* NESTED VECTOR INTERRUPT CONTROL REGISTER */ #define NVIC_ISER0 ((volatile uint32_t*)( 0xE000E100)) // interrupt set enable register +#define NVIC_ISER1 ((volatile uint32_t*)( 0xE000E104)) // interrupt set enable register /* SYSTICK REGISTER */ #define STK_CTRL ((volatile uint32_t *)(0xE000E010)) @@ -30,7 +30,7 @@ /* SYSTEM CONTROL REGISTER */ #define SYSCTRL_RCC ((volatile unsigned long *)(0x40021000)) -#define RCC_APB2ENR ((volatile unsigned long *)(0x40021018)) // register to enable USART1 +#define RCC_APB2ENR ((volatile uint32_t *)(0x40021018)) // register to enable USART1 #define SYSCTRL_RIS ((volatile unsigned long *)(0x400FE050)) #define SYSCTRL_RCGC1 ((volatile unsigned long *)(0x400FE104)) @@ -38,7 +38,14 @@ #define GPIOPA_AFSEL ((volatile unsigned long *)(0x40004420)) #define GPIOA_CRH ((volatile unsigned long *)(0x40010804)) -#define AFIO_EVCR ((volatile unsigned long *)(0x40010000)) + +#define AFIO_EVCR ((volatile uint32_t *)(0x40010000)) +//#define AFIO_EXTICR1 ((volatile uint32_t *)(AFIO_EVCR + 0x08)) + +/* EXTERNAL INTERRUPTS */ +#define EXTI_IMR ((volatile uint32_t *)(0x40010400)) +#define EXTI_RTSR ((volatile uint32_t *) (EXTI_IMR + 0x08)) +//#define EXTI_FTSR ((volatile uint32_t *) (EXTI_IMR + 0x04)) /* UART1 REGISTERS */ #define USART1_BASE ((volatile uint32_t) (0x40013800)) diff --git a/include/stm32.h b/include/stm32.h index 4f52257..62ee93e 100644 --- a/include/stm32.h +++ b/include/stm32.h @@ -34,4 +34,8 @@ extern void * mm_alloc(size_t); extern void free(void *); extern void test_memory(uint32_t *); +/* REGF.C */ +extern void regw_u8(volatile uint32_t *, uint8_t, short, short); +extern void regw_u32(volatile uint32_t *, uint32_t, short, short); + #endif diff --git a/ivt.c b/ivt.c index 1b4cb9b..6df1e8b 100644 --- a/ivt.c +++ b/ivt.c @@ -5,15 +5,63 @@ #include /* + * These values are pushed on the stack just before + * entering the ISR. Normally, this would require + * assembly or inline assembly code. I use a so-called + * 'naked function' __attribute__ ((interrupt)) which + * gives me a little bit more control over the caller + * + * The following register are pushed to the stack + * in reverse order + * + * */ +struct interrupt_frame { + + uint32_t r0; // N-32 + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r12; + uint32_t lr; + uint32_t pc; + uint32_t psr; // N-4 +}; + +/* * Vector table, each entry contains an interrupt - * service routine: * + * service routine: * * interrupt vector 1-15: processor exceptions - * interrupt vector 16-32: irq0 - irq .. + * interrupt vector 16-64: irq0 - irq .. * */ -uint32_t ivt[32]; +uint32_t ivt[64]; +/* each message corresponds to each and every exception. + * We get the correct message by accessing + * exception_message[interrupt_number] + * exception_message[0] is not used (=MSP)*/ +unsigned char *exception_messages[] = +{ + "--", + "RESET", + "NMI", + "HARD FAULT", + "MEMMANAGE FAULT", + "BUS FAULT", + "USAGE FAULT", + "RESERVED", + "SVC", + "DEBUG MONITOR", + "RESERVED", + "PENDSV", + "SYSTICK", + "IRQ1", + "IRQ2", + "IRQ3", + "IRQ4", + // add more if needed +}; void ivt_set_gate(unsigned char num, void * isr(), short pri) { @@ -24,9 +72,25 @@ void ivt_set_gate(unsigned char num, void * isr(), short pri) { /* Dummy interrupt */ -void * dummy_isr() { +__attribute__ ((interrupt)) +void * dummy_isr(struct interrupt_frame * frame) { + + + uint32_t * p = (volatile uint32_t *) 0x21000000; + addrtohex(frame->r0); + addrtohex(frame->r1); + addrtohex(frame->r2); + addrtohex(frame->r3); + addrtohex(frame->r12); + addrtohex(frame->lr); + addrtohex(frame->pc); + addrtohex(frame->psr); + + //__asm__ __volatile__ ("MRS r0, IPSR"); + //addrtohex(frame->r0); uart_puts("EXCEPTION X: SYSTEM HALTED\n"); + for(;;); } @@ -40,18 +104,16 @@ void ivt_init() { // don't need to relocate or init this here extern void * reset, * nmi, * hardfault; - ivt_set_gate(1, dummy_isr, 0); - ivt_set_gate(2, dummy_isr, 0); - ivt_set_gate(3, dummy_isr, 0); - ivt_set_gate(4, dummy_isr, 0); - ivt_set_gate(5, dummy_isr, 0); - ivt_set_gate(6, dummy_isr, 0); + for (int i = 1; i < 7; i++) { + ivt_set_gate(i, dummy_isr, 0); + } /* the vector table starts at 0x0. Since the address 0x0 point to * bootcode, it is on ROM or FLASH. The vector table can be * relocated to other memory locations. We can do this by setting * a register in the NVIC called the vector table offset register */ - *SCB_VTOR = (volatile uint32_t) &ivt; + //*SCB_VTOR = (volatile uint32_t) &ivt; + regw_u32(SCB_VTOR, (uint32_t) &ivt, 0, 0x01); } diff --git a/lib.c b/lib.c index 69bb12d..bc5bc8c 100644 --- a/lib.c +++ b/lib.c @@ -7,7 +7,7 @@ /* Temporary libc functions, which can later be * replaced by a *real* library */ -char hexbuf[8] = {'0', '0','0', '0','0', '0','0', '0'}; +char hexbuf[8]; void addrtohex(uint32_t addr) { char tmpbuf[6] = {'A', 'B', 'C', 'D', 'E', 'F'}; @@ -33,3 +33,5 @@ void addrtohex(uint32_t addr) { uart_putc('\n'); } + + diff --git a/main.c b/main.c index 84496d5..4134c95 100644 --- a/main.c +++ b/main.c @@ -1,7 +1,7 @@ #include #include #include -#include // <-- your own header file located located in ./include +#include // <-- my own header file located located in ./include #include @@ -46,19 +46,23 @@ void main() ivt_init(); // clock_init(); uart_init(); - systick_init(); +// systick_init(); uart_puts("LOADING SYSTEM 0.1 ...\n"); sysinfo(); mm_init(); - int * p2 = mm_alloc(200); - *p2 = 0x12345678; + //int * p2 = mm_alloc(512); + //memset(p2, 'a', 512); - test_memory(p2); + //addrtohex(p2); + //addrtohex(*p2); - addrtohex(p2); - addrtohex(*p2); + //uint32_t * p = (volatile unsigned) 0x21000000; + //regw_u32(p, 0x0CCCCCCCC, 4, 0x01); + //regw_u8(p, 0xFF, 0, 0x02); + + //addrtohex(*p); //addrtohex((volatile uint32_t) 0x12345678 ); //addrtohex((volatile uint32_t) SCB_VTOR ); diff --git a/regf.c b/regf.c new file mode 100644 index 0000000..257a417 --- /dev/null +++ b/regf.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +#define O_WRITE 0x01 +#define SET 0x02 +#define CLEAR 0x03 + +/* write value (uint8_t) to register */ +void regw_u8(volatile uint32_t * reg, uint8_t val, short shift, short flag) { + + switch(flag) { + case O_WRITE: + (*(volatile uint32_t *) (reg)) = (val << shift); + break; + case SET: + (*(volatile uint32_t *) (reg)) = + ((*(volatile uint32_t *) (reg)) | (val << shift)); + break; + case CLEAR: + (*(volatile uint32_t *) (reg)) = (val << shift); + break; + } +} + +/* write value (uint32_t) to register */ +void regw_u32(volatile uint32_t * reg, uint32_t val, short shift, short flag) { + + switch(flag) { + case O_WRITE: + (*(volatile uint32_t *) (reg)) = (val << shift); + break; + case SET: + (*(volatile uint32_t *) (reg)) = + ((*(volatile uint32_t *) (reg)) | (val << shift)); + case CLEAR: + // + break; + } +} + + diff --git a/sysinfo.c b/sysinfo.c index fb19c9b..3971d3b 100644 --- a/sysinfo.c +++ b/sysinfo.c @@ -21,6 +21,7 @@ void sysinfo() { tmp = (tmp >> 16); uart_puts("# REVISION: "); +// addrtohex(tmp); switch (tmp) { case 0x1000: uart_puts("REVISION A\n"); diff --git a/systick.c b/systick.c index 777d04d..48065ef 100644 --- a/systick.c +++ b/systick.c @@ -4,13 +4,34 @@ #include #include +struct interrupt_frame { -void * systick_handler() { + uint32_t r0; // N-32 + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r12; + uint32_t lr; + uint32_t pc; + uint32_t psr; // N-4 +}; + + +/* void * systick_handler() { // *RANDOM_ADDR = (volatile uint32_t) 0x10101010 ; // uart_puts("TEST"); +} */ + +__attribute__ ((interrupt)) +void * systick_handler(struct interrupt_frame * frame) { + + uart_puts("TICKING\n"); +// addrtohex((uint32_t) 0x12345678); + // for(;;); } + void systick_init() { /* Enable the counter and enable the interrupt diff --git a/uart.c b/uart.c index a3905c4..4751645 100644 --- a/uart.c +++ b/uart.c @@ -4,14 +4,39 @@ #include #include +#define RXNE ((*USART1_SR >> 5) & 0x1) + +#define O_WRITE 0x01 +#define SET 0x02 +#define CLEAR 0x03 + +void * uart_handler() { + + uart_puts("\n echo: "); + while (RXNE) { + char echochar = *USART1_DR; + // regw_u8(USART1_DR, echochar, 0, O_WRITE); + uart_putc(echochar); + } +//for(;;); + +} void uart_init() { + // global interrupt setup +// regw_u32(EXTI_IMR, 0x000FFFFF, 0, O_WRITE); +// regw_u32(EXTI_RTSR, 0x000FFFFF, 0, O_WRITE); + + + regw_u32(RCC_APB2ENR, 0x4005, 0, SET);// enable clock to UART1, AFIO and GPIOA - *RCC_APB2ENR = 0x4005; // enable clock to UART1, AFIO and GPIOA - *GPIOA_CRH = 0x444444D4; // (after enable GPIOA), on PA9&PA10 and set mode to alternative output - *AFIO_EVCR = 0x89; // (after enable) set event control register, output on PA, Pin 9 + /* (after enable GPIOA), on PA9&PA10 and set mode + * to alternative output */ + regw_u32(GPIOA_CRH, 0x444444D4, 0, O_WRITE); + regw_u8(AFIO_EVCR, 0x89, 0, O_WRITE);// set event control register, output on PA, Pin 9 - *USART1_CR1 = (0 << 13); // disable temporarily to set values + //disable temporarily to set values + regw_u8(USART1_CR1, 0x0, 13, SET); /* baud rate 115200, 8MHz / (16 * USARTDIV) * USARTDIV = 4.34 @@ -19,28 +44,17 @@ void uart_init() { * MANTISSA: 0d4.34 0d4 -> 0x4 * USART_BRR = 0x45*/ - /* baud rate 2400 - * - * 16 * 0.33 -> 0x5 - * 208 -> 0x34 */ - - *USART1_BRR = (volatile uint32_t) 0x00000045; + regw_u32(USART1_BRR, 0x00000045, 0, O_WRITE); + regw_u32(USART1_CR2, 0x0000, 0, O_WRITE); //set stop bit, default is 1 stop bit 0x00 - *USART1_CR2 = (volatile uint32_t) 0x0000; // set stop bit, default is 1 stop bit 0x00 - // enable DMA - // *USART1_CR3 = 0x0C0; /* parity = 8 bit, UART1 enabled, * TX and RX enabled, interrupts enabled */ - *USART1_CR1 = (volatile uint32_t) 0x000030AC; - -/* - * Configure UART0: - 1. Disable the UART by clearing the UARTEN bit in the UARTCTL register. - 2. Write the integer portion of the BRD to the UARTIBRD register. - 3. Write the fractional portion of the BRD to the UARTFBRD register. - 4. Write the desired serial parameters to the UARTLCRH register - 5. Enable the UART by setting the UARTEN bit in the UARTCTL register. -*/ + //regw_u32(USART1_CR1, 0x000030AC, 0, O_WRITE); + regw_u32(USART1_CR1, 0x0000302C, 0, O_WRITE); + + ivt_set_gate(53, uart_handler, 0); + + *NVIC_ISER1 = (1 << 5); // Enable UART interrupt at NVIC } void wait() { @@ -51,34 +65,33 @@ extern void uart_putc(unsigned char ch) { if (ch == '\n') { while (*USART1_SR & 0x0C) { } // transmit data register empty and complete - *USART1_DR = 0x0D; // return line + regw_u8(USART1_DR, 0x0D, 0, O_WRITE); // return line } - while (*USART1_SR & 0x0C) {} - *USART1_DR = ch; + regw_u8(USART1_DR, ch, 0, O_WRITE); - - wait(); } -extern void uart_puts(unsigned char *str) -{ - +extern void uart_puts(unsigned char *str) { int i; - - for (i = 0; i < strlen(str); i++) - { + for (i = 0; i < strlen(str); i++) { uart_putc(str[i]); } } -char * uart_read() { +char uart_read() { - return NULL; + /* while (buffer not empty) + * read() + * uart_putc(ch) // echo + * if ch = enter + * process inquiry. + */ + }