diff --git a/platform/stm32f1xx/debug.c b/platform/stm32f1xx/debug.c index 456502ca..91fa0634 100644 --- a/platform/stm32f1xx/debug.c +++ b/platform/stm32f1xx/debug.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,9 @@ #include #include -void stm32_debug_init(void) +static cbuf_t debug_rx_buf; + +void stm32_debug_early_init(void) { // XXX move this into usart driver if (DEBUG_UART == USART1) { @@ -49,15 +52,41 @@ void stm32_debug_init(void) init.USART_WordLength = USART_WordLength_8b; init.USART_StopBits = USART_StopBits_1; init.USART_Parity = USART_Parity_No; - init.USART_Mode = USART_Mode_Tx; + init.USART_Mode = USART_Mode_Tx|USART_Mode_Rx; init.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(DEBUG_UART, &init); USART_ITConfig(DEBUG_UART, USART_IT_RXNE, DISABLE); + NVIC_DisableIRQ(DEBUG_UART_IRQ); + USART_Cmd(DEBUG_UART, ENABLE); } +/* later in the init process */ +void stm32_debug_init(void) +{ + cbuf_initialize(&debug_rx_buf, 16); + + USART_ITConfig(DEBUG_UART, USART_IT_RXNE, ENABLE); + NVIC_EnableIRQ(DEBUG_UART_IRQ); +} + +void stm32_debug_rx_irq(void) +{ + inc_critical_section(); + + while (USART_GetFlagStatus(DEBUG_UART, USART_FLAG_RXNE)) { + char c = USART_ReceiveData(DEBUG_UART); + cbuf_write(&debug_rx_buf, &c, 1, false); + } + + USART_ClearFlag(DEBUG_UART, USART_IT_RXNE); + + dec_critical_section(); + thread_preempt(); +} + void _dputc(char c) { if (c == '\n') { @@ -72,7 +101,7 @@ void _dputc(char c) int dgetc(char *c, bool wait) { - return -1; + return cbuf_read(&debug_rx_buf, c, 1, wait); } void debug_dump_regs(void) diff --git a/platform/stm32f1xx/include/platform/platform_cm3.h b/platform/stm32f1xx/include/platform/platform_cm3.h new file mode 100644 index 00000000..54b92b56 --- /dev/null +++ b/platform/stm32f1xx/include/platform/platform_cm3.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2012 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __PLATFORM_CM3_H +#define __PLATFORM_CM3_H + +#include + +#endif + diff --git a/platform/stm32f1xx/include/platform/stm32.h b/platform/stm32f1xx/include/platform/stm32.h index 21f333f6..842a2e73 100644 --- a/platform/stm32f1xx/include/platform/stm32.h +++ b/platform/stm32f1xx/include/platform/stm32.h @@ -1,7 +1,35 @@ +/* + * Copyright (c) 2012 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ #ifndef __PLATFORM_STM32_H #define __PLATFORM_STM32_H +void stm32_debug_early_init(void); void stm32_debug_init(void); +void stm32_timer_early_init(void); +void stm32_timer_init(void); + +// XXX refactor this into a proper usart driver +void stm32_debug_rx_irq(void); #endif diff --git a/platform/stm32f1xx/init.c b/platform/stm32f1xx/init.c index 4c106f0a..ccbabce8 100644 --- a/platform/stm32f1xx/init.c +++ b/platform/stm32f1xx/init.c @@ -23,12 +23,15 @@ #include #include #include +#include void platform_early_init(void) { + stm32_timer_early_init(); } void platform_init(void) { + stm32_timer_init(); } diff --git a/platform/stm32f1xx/rules.mk b/platform/stm32f1xx/rules.mk index 93551c64..1910cb3f 100644 --- a/platform/stm32f1xx/rules.mk +++ b/platform/stm32f1xx/rules.mk @@ -21,6 +21,7 @@ OBJS += \ $(LOCAL_DIR)/init.o \ $(LOCAL_DIR)/debug.o \ $(LOCAL_DIR)/timer.o \ + $(LOCAL_DIR)/vectab.o \ # $(LOCAL_DIR)/debug.o \ $(LOCAL_DIR)/interrupts.o \ @@ -40,4 +41,7 @@ OBJS += \ LINKER_SCRIPT += \ $(BUILDDIR)/system-twosegment.ld +MODULES += \ + lib/cbuf + include $(LOCAL_DIR)/STM32F10x_StdPeriph_Driver/rules.mk $(LOCAL_DIR)/CMSIS/rules.mk diff --git a/platform/stm32f1xx/timer.c b/platform/stm32f1xx/timer.c index 8db60bc5..1c30ce65 100644 --- a/platform/stm32f1xx/timer.c +++ b/platform/stm32f1xx/timer.c @@ -21,24 +21,153 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include +#include #include +#include #include #include +#include +#include +#include +#include + +#define TIME_BASE_COUNT 0xffff +#define TICK_RATE 1000000 + +static volatile uint64_t ticks = 0; + +static platform_timer_callback cb; +static void *cb_args; + +void stm32_tim2_irq(void) +{ + /* time base */ + ticks += TIME_BASE_COUNT; + TIM_ClearITPendingBit(TIM2, TIM_IT_Update); +} + +void stm32_tim3_irq(void) +{ + inc_critical_section(); + + TIM_ClearITPendingBit(TIM3, TIM_IT_Update); + + bool resched = false; + if (cb) { + time_t now = current_time(); + if (cb(cb_args, now) == INT_RESCHEDULE) + resched = true; + } + + if (resched) { + // have the cortex-m3 queue a preemption + cm3_trigger_preempt(); + } + + dec_critical_section(); +} + +static void stm32_tim_irq(uint num) +{ + printf("tim irq %d\n", num); + PANIC_UNIMPLEMENTED; +} + +void stm32_tim4_irq(void) +{ + stm32_tim_irq(4); +} + +void stm32_tim5_irq(void) +{ + stm32_tim_irq(5); +} + +void stm32_tim6_irq(void) +{ + stm32_tim_irq(6); +} + +void stm32_tim7_irq(void) +{ + stm32_tim_irq(7); +} time_t current_time(void) { - PANIC_UNIMPLEMENTED; - return 0; + return current_time_hires() / 1000; } bigtime_t current_time_hires(void) { - PANIC_UNIMPLEMENTED; - return 0; + bigtime_t res = 0; + do { + uint64_t t = ticks; + uint16_t delta = TIM_GetCounter(TIM2); + + if (ticks != t) + continue; + + res = t + delta; + } while (0); + + return res; } status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval) { - PANIC_UNIMPLEMENTED; + TRACEF("callback %p, arg %p, interval %d\n", callback, arg, interval); + + cb = callback; + cb_args = arg; + + TIM_Cmd(TIM3, DISABLE); + + TIM_SetCounter(TIM3, interval); + TIM_SetAutoreload(TIM3, interval); + + TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); + TIM_ClearITPendingBit(TIM3, TIM_IT_Update); + NVIC_EnableIRQ(TIM3_IRQn); + + TIM_Cmd(TIM3, ENABLE); + + return NO_ERROR; +} + +void stm32_timer_early_init(void) +{ + /* start the time base unit */ + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); + + TIM_TimeBaseInitTypeDef tbase; + TIM_TimeBaseStructInit(&tbase); + + /* try to run the clock at 1Mhz */ + RCC_ClocksTypeDef clocks; + RCC_GetClocksFreq(&clocks); + + // XXX why do we need a *2 here? + tbase.TIM_Prescaler = (clocks.PCLK1_Frequency / 1000000) * 2 - 1; + + TIM_TimeBaseInit(TIM2, &tbase); + + TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); + TIM_ClearITPendingBit(TIM2, TIM_IT_Update); + NVIC_SetPriority(TIM2_IRQn, cm3_highest_priority()); + NVIC_EnableIRQ(TIM2_IRQn); + + TIM_Cmd(TIM2, ENABLE); + + /* for dynamic ticks, use TIM3 */ + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); + + /* run the tick at ms resolution */ + TIM_PrescalerConfig(TIM3, (clocks.PCLK1_Frequency / 1000) * 2 - 1, TIM_PSCReloadMode_Immediate); + TIM_CounterModeConfig(TIM3, TIM_CounterMode_Down); +} + +void stm32_timer_init(void) +{ } diff --git a/platform/stm32f1xx/vectab.c b/platform/stm32f1xx/vectab.c new file mode 100644 index 00000000..144a2b19 --- /dev/null +++ b/platform/stm32f1xx/vectab.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include +#include +#include +#include + +extern void stm32_tim2_irq(void); +extern void stm32_tim3_irq(void); +extern void stm32_tim4_irq(void); +extern void stm32_tim5_irq(void); +extern void stm32_tim6_irq(void); +extern void stm32_tim7_irq(void); + +void stm32_USART1_IRQ(void) +{ + if (DEBUG_UART == USART1) + stm32_debug_rx_irq(); + else + PANIC_UNIMPLEMENTED; +} + +void stm32_USART2_IRQ(void) +{ + if (DEBUG_UART == USART2) + stm32_debug_rx_irq(); + else + PANIC_UNIMPLEMENTED; +} + +void stm32_USART3_IRQ(void) +{ + if (DEBUG_UART == USART3) + stm32_debug_rx_irq(); + else + PANIC_UNIMPLEMENTED; +} + +/* appended to the end of the main vector table */ +const void * const __SECTION(".text.boot.vectab2") vectab2[] = +{ + [TIM2_IRQn] = stm32_tim2_irq, + [TIM3_IRQn] = stm32_tim3_irq, + [TIM4_IRQn] = stm32_tim4_irq, + [TIM5_IRQn] = stm32_tim5_irq, + [TIM6_IRQn] = stm32_tim6_irq, + [TIM7_IRQn] = stm32_tim7_irq, + + [USART1_IRQn] = stm32_USART1_IRQ, + [USART2_IRQn] = stm32_USART2_IRQ, + [USART3_IRQn] = stm32_USART3_IRQ, + [NUM_IRQn] = 0, +}; + diff --git a/target/stm32-p107/include/target/debugconfig.h b/target/stm32-p107/include/target/debugconfig.h index d83d1ec6..7208cf6c 100644 --- a/target/stm32-p107/include/target/debugconfig.h +++ b/target/stm32-p107/include/target/debugconfig.h @@ -26,5 +26,6 @@ #include #define DEBUG_UART USART3 +#define DEBUG_UART_IRQ USART3_IRQn #endif diff --git a/target/stm32-p107/init.c b/target/stm32-p107/init.c index b6130cee..8f593dae 100644 --- a/target/stm32-p107/init.c +++ b/target/stm32-p107/init.c @@ -50,10 +50,15 @@ void target_early_init(void) init.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOD, &init); - stm32_debug_init(); + stm32_debug_early_init(); } void target_init(void) { + TRACE_ENTRY; + + stm32_debug_init(); + + TRACE_EXIT; }