From 025a38a1f743fd9e89cbd477abe3f79a8d098097 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Sat, 19 Nov 2011 17:21:31 +0100 Subject: Moved os and hal related files into subdirectories. --- .gitignore | 3 +- SConstruct | 6 +- fault.cpp | 10 --- hal/fault.cpp | 41 +++++++++ hal/i2c.cpp | 194 ++++++++++++++++++++++++++++++++++++++++ hal/i2c.h | 40 +++++++++ hal/interrupt.cpp | 157 ++++++++++++++++++++++++++++++++ hal/interrupt.h | 100 +++++++++++++++++++++ hal/rcc.cpp | 26 ++++++ hal/rcc.h | 6 ++ hal/stm32.h | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ hal/usart.h | 26 ++++++ i2c.cpp | 194 ---------------------------------------- i2c.h | 40 --------- interrupt.cpp | 157 -------------------------------- interrupt.h | 100 --------------------- main.cpp | 3 +- mutex.h | 42 --------- os/mutex.h | 42 +++++++++ os/pool.cpp | 5 ++ os/pool.h | 146 ++++++++++++++++++++++++++++++ os/thread.cpp | 4 + os/thread.h | 63 +++++++++++++ os/time.cpp | 3 + os/time.h | 23 +++++ pool.cpp | 5 -- pool.h | 146 ------------------------------ rcc.cpp | 26 ------ rcc.h | 6 -- stm32.h | 262 ------------------------------------------------------ thread.cpp | 31 ------- thread.h | 63 ------------- time.cpp | 9 -- time.h | 28 ------ usart.h | 26 ------ 35 files changed, 1146 insertions(+), 1149 deletions(-) delete mode 100644 fault.cpp create mode 100644 hal/fault.cpp create mode 100644 hal/i2c.cpp create mode 100644 hal/i2c.h create mode 100644 hal/interrupt.cpp create mode 100644 hal/interrupt.h create mode 100644 hal/rcc.cpp create mode 100644 hal/rcc.h create mode 100644 hal/stm32.h create mode 100644 hal/usart.h delete mode 100644 i2c.cpp delete mode 100644 i2c.h delete mode 100644 interrupt.cpp delete mode 100644 interrupt.h delete mode 100644 mutex.h create mode 100644 os/mutex.h create mode 100644 os/pool.cpp create mode 100644 os/pool.h create mode 100644 os/thread.cpp create mode 100644 os/thread.h create mode 100644 os/time.cpp create mode 100644 os/time.h delete mode 100644 pool.cpp delete mode 100644 pool.h delete mode 100644 rcc.cpp delete mode 100644 rcc.h delete mode 100644 stm32.h delete mode 100644 thread.cpp delete mode 100644 thread.h delete mode 100644 time.cpp delete mode 100644 time.h delete mode 100644 usart.h diff --git a/.gitignore b/.gitignore index 46fa166..f22d170 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.o +*.a *.elf -.sconsign.dblite \ No newline at end of file +.sconsign.dblite diff --git a/SConstruct b/SConstruct index 08229f4..72ac32d 100644 --- a/SConstruct +++ b/SConstruct @@ -18,13 +18,15 @@ env = Environment( AR = 'arm-none-eabi-ar', RANLIB = 'arm-none-eabi-ranlib', - #CPPPATH = [], + CPPPATH = ['os', 'hal'], #LIBPATH = [], LIBS = ['m'], ) -firmware = env.Program('suzumebachi.elf', Glob('*.cpp')) +sources = Glob('os/*.cpp') + Glob('hal/*.cpp') + Glob('*.cpp') + +firmware = env.Program('suzumebachi.elf', sources) env.Depends(firmware, 'suzumebachi.ld') env.Command('prog', ['suzumebachi.elf'], 'openocd -f openocd.cfg -c flash_chip') diff --git a/fault.cpp b/fault.cpp deleted file mode 100644 index 42ebd30..0000000 --- a/fault.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "interrupt.h" - -template<> void interrupt() { while(1); } -template<> void interrupt() { while(1); } -template<> void interrupt() { while(1); } -template<> void interrupt() { while(1); } -template<> void interrupt() { while(1); } -//template<> void interrupt() { while(1); } -template<> void interrupt() { while(1); } -//template<> void interrupt() { while(1); } diff --git a/hal/fault.cpp b/hal/fault.cpp new file mode 100644 index 0000000..a176ae6 --- /dev/null +++ b/hal/fault.cpp @@ -0,0 +1,41 @@ +#include "interrupt.h" +#include "thread.h" +#include "time.h" + +inline void __attribute__((naked)) switch_context() { + asm volatile ("cpsid i"); + + // Save unsaved registers. + asm volatile ("push {r4, r5, r6, r7, r8, r9, r10, r11, lr}" ::: "memory"); + + // Store stack pointer for old thread. + asm volatile ("str sp, [%0]" :: "r" (&Thread::active_thread->sp)); + + // Update running thread. + Thread::active_thread = Thread::active_thread->next; + + // Fetch stack pointer for new thread. + asm volatile ("ldr sp, [%0]" :: "r" (&Thread::active_thread->sp)); + + asm volatile ("cpsie i"); + + // Load registers and return. + asm volatile ("pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}" ::: "memory"); +} + +template<> +void interrupt() { + switch_context(); +} + +template<> +void interrupt() { + Time::tick(); +} + +template<> void interrupt() { while(1); } +template<> void interrupt() { while(1); } +template<> void interrupt() { while(1); } +template<> void interrupt() { while(1); } +template<> void interrupt() { while(1); } +template<> void interrupt() { while(1); } diff --git a/hal/i2c.cpp b/hal/i2c.cpp new file mode 100644 index 0000000..cee72ec --- /dev/null +++ b/hal/i2c.cpp @@ -0,0 +1,194 @@ +#include "i2c.h" + +#include "stm32.h" +#include "thread.h" + +I2C* I2C::self; + +template <> +void interrupt() { + I2C::self->irq_ev(); +} + +template <> +void interrupt() { + I2C::self->irq_er(); +} + +void I2C::irq_ev() { + uint32_t sr1 = I2C1.SR1; + I2C1.SR2; + + // EV5, SB = 1: Start condition sent. + if(sr1 & 0x01) { + // Send address. + I2C1.DR = (addr << 1) | (writing ? 0 : 1); + } + + // EV6, ADDR = 1: Address sent. + if(sr1 & 0x02) { + if(writing) { + I2C1.DR = *write_p++; + writing--; + } else { + if(reading > 1) { + I2C1.CR1 |= 0x400; // Set ACK. + } else { + I2C1.CR1 |= 0x200; // Set STOP. + } + } + } + + // EV7, RxNE = 1: Receive buffer not empty. + if(sr1 & 0x40) { + *read_p++ = I2C1.DR; + reading--; + + if(reading == 1) { + // Unset ACK, set STOP. + I2C1.CR1 = (I2C1.CR1 & ~0x400) | 0x200; + } + + if(reading == 0) { + busy = 0; + } + } + + //I2C1.CR1 &= ~0x400; + + // EV8, TxE = 1, BTF = 0: Transmit buffer empty, still writing. + if(sr1 & 0x80 && !(sr1 & 0x04)) { + if(writing) { + // Send data. + I2C1.DR = *write_p++; + writing--; + } else { + // All data sent. + + if(reading) { + // Send repeat start. + I2C1.CR1 |= 0x100; + } else { + // Send stop. + I2C1.CR1 |= 0x200; + busy = 0; + } + } + } +} + +void I2C::irq_er() { + handle_error(); +} + +void I2C::handle_error() { + I2C1.SR1; + I2C1.SR2; + + //while(1); + I2C1.CR1 |= 0x200; + busy = 0; +} + +void I2C::enable() { + RCC.enable(RCC.I2C1); + asm volatile("nop"); + + I2C1.CR1 = 0x8000; + I2C1.CR1 = 0; + + I2C1.CR2 = 0x700 | 36; + I2C1.TRISE = 37; + I2C1.CCR = 180; + + Interrupt::enable(Interrupt::I2C1_EV); + Interrupt::enable(Interrupt::I2C1_ER); + + I2C1.CR1 = 1; +} + +void I2C::write_reg(uint8_t addr_, uint8_t reg, uint8_t data) { + addr = addr_; + writing = 2; + reading = 0; + volatile uint8_t buf[] = {reg, data}; + write_p = buf; + busy = 1; + + I2C1.CR1 |= 0x100; + + while(busy) { + Thread::yield(); + } + + /* + while(!(I2C1.SR1 & 0x01)); // Wait for SB. + + I2C1.DR = (addr << 1) | 0; + while (!(I2C1.SR1 & 0x02)); // Wait for ADDR. + I2C1.SR2; + + I2C1.DR = reg; + while (!(I2C1.SR1 & 0x80)); // Wait for TxE. + + I2C1.DR = data; + while (!(I2C1.SR1 & 0x04)); // Wait for BTF. + + I2C1.CR1 |= 0x200;*/ +} + +void I2C::read_reg(uint8_t addr_, uint8_t reg, uint8_t len, uint8_t* buf) { + addr = addr_; + writing = 1; + reading = len; + write_p = ® + read_p = buf; + busy = 1; + + I2C1.CR1 |= 0x100; + + while(busy) { + Thread::yield(); + } + + /* + I2C1.CR1 |= 0x100; + while(!(I2C1.SR1 & 0x01)); // Wait for SB. + + I2C1.DR = (addr << 1) | 0; + while (!(I2C1.SR1 & 0x02)); // Wait for ADDR. + I2C1.SR2; + + I2C1.DR = reg; + while (!(I2C1.SR1 & 0x80)); // Wait for TxE. + + I2C1.CR1 |= 0x100; + while(!(I2C1.SR1 & 0x01)); // Wait for SB. + + I2C1.DR = (addr << 1) | 1; + while (!(I2C1.SR1 & 0x02)); // Wait for ADDR. + I2C1.SR2; + + I2C1.CR1 |= 0x400; // Set ACK. + + while(len) { + if(len == 3) { + while (!(I2C1.SR1 & 0x04)); // Wait for BTF. + + I2C1.CR1 &= ~0x400; // Clear ACK. + *buf++ = I2C1.DR; + len--; + + I2C1.CR1 |= 0x200; // Set STOP. + *buf++ = I2C1.DR; + len--; + + } else { + while (!(I2C1.SR1 & 0x40)); // Wait for RxNE. + + *buf++ = I2C1.DR; + len--; + } + } + */ +} diff --git a/hal/i2c.h b/hal/i2c.h new file mode 100644 index 0000000..3d58056 --- /dev/null +++ b/hal/i2c.h @@ -0,0 +1,40 @@ +#ifndef I2C_H +#define I2C_H + +#include + +#include "interrupt.h" + +class I2C { + friend void interrupt(); + friend void interrupt(); + + private: + static I2C* self; + + volatile uint8_t addr; + volatile uint8_t writing; + volatile uint8_t reading; + volatile uint8_t* write_p; + volatile uint8_t* read_p; + + volatile bool busy; + + void irq_ev(); + void irq_er(); + void handle_error(); + + public: + I2C() { + self = this; + } + + void enable(); + + void write_reg(uint8_t addr_, uint8_t reg, uint8_t data); + void read_reg(uint8_t addr_, uint8_t reg, uint8_t len, uint8_t* buf); +}; + + + +#endif diff --git a/hal/interrupt.cpp b/hal/interrupt.cpp new file mode 100644 index 0000000..e9e7b24 --- /dev/null +++ b/hal/interrupt.cpp @@ -0,0 +1,157 @@ +#include "interrupt.h" + +void entry(); + +extern "C" void unused_interrupt() { + while(1) {} +} + +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); +template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); + +typedef void (*vector_t)(); + +vector_t vectors[] __attribute__((section(".vectors"))) = { + (vector_t)0x20004ffc, + entry, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + 0, + 0, + 0, + 0, + interrupt, + 0, + 0, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, + interrupt, +}; diff --git a/hal/interrupt.h b/hal/interrupt.h new file mode 100644 index 0000000..f817103 --- /dev/null +++ b/hal/interrupt.h @@ -0,0 +1,100 @@ +#ifndef INTERRUPT_H +#define INTERRUPT_H + +#include "stm32.h" + +namespace Interrupt { + enum Exception { + NMI = 2, + HardFault = 3, + MemManage = 4, + BusFault = 5, + UsageFault = 6, + SVCall = 11, + PendSV = 14, + SysTick = 15 + }; + + enum IRQ { + WWDG, + PVD, + TAMPER, + RTC, + FLASH, + RCC, + EXTI0, + EXTI1, + EXTI2, + EXTI3, + EXTI4, + DMA1_Channel1, + DMA1_Channel2, + DMA1_Channel3, + DMA1_Channel4, + DMA1_Channel5, + DMA1_Channel6, + DMA1_Channel7, + ADC1_2, + USB_HP_CAN_TX, + USB_LP_CAN_RX0, + CAN_RX1, + CAN_SCE, + EXTI9_5, + TIM1_BRK, + TIM1_UP, + TIM1_TRG_COM, + TIM1_CC, + TIM2, + TIM3, + TIM4, + I2C1_EV, + I2C1_ER, + I2C2_EV, + I2C2_ER, + SPI1, + SPI2, + USART1, + USART2, + USART3, + EXTI15_10, + RTCAlarm, + USBWakeup, + TIM8_BRK, + TIM8_UP, + TIM8_TRG_COM, + TIM8_CC, + ADC3, + FSMC, + SDIO, + TIM5, + SPI3, + UART4, + UART5, + TIM6, + TIM7, + DMA2_Channel1, + DMA2_Channel2, + DMA2_Channel3, + DMA2_Channel4_5 + }; + + inline void enable(IRQ n) { + NVIC.ISER[n >> 5] = 1 << (n & 0x1f); + } + + inline void set_priority(Exception n, uint8_t priority) { + SCB.SHPR[n - 4] = priority; + } + + inline void set_priority(IRQ n, uint8_t priority) { + NVIC.IPR[n] = priority; + } +}; + +template +void interrupt(); + +template +void interrupt(); + +#endif diff --git a/hal/rcc.cpp b/hal/rcc.cpp new file mode 100644 index 0000000..e3ae38d --- /dev/null +++ b/hal/rcc.cpp @@ -0,0 +1,26 @@ +#include "rcc.h" +#include "stm32.h" + +void rcc_init() { + // Set flash latency. + FLASH.ACR = 0x12; + + // Enable HSE. + RCC.CR |= 0x10000; + while(RCC.CR & 0x20000); + + // Configure and enable PLL. + RCC.CFGR = 0x1d0000; + RCC.CR |= 0x1000000; + while(RCC.CR & 0x2000000); + + // Switch to PLL. + RCC.CFGR |= 0x2; + while(!(RCC.CFGR & 0x8)); + + // Set APB1 prescaler to /2. + RCC.CFGR |= 0x400; + + // Set ADCCLK prescaler to /6. + RCC.CFGR |= 0x8000; +} diff --git a/hal/rcc.h b/hal/rcc.h new file mode 100644 index 0000000..8c5fb86 --- /dev/null +++ b/hal/rcc.h @@ -0,0 +1,6 @@ +#ifndef RCC_H +#define RCC_H + +void rcc_init(); + +#endif diff --git a/hal/stm32.h b/hal/stm32.h new file mode 100644 index 0000000..8144e80 --- /dev/null +++ b/hal/stm32.h @@ -0,0 +1,262 @@ +#ifndef STM32_H +#define STM32_H + +#include + +struct NVIC_t { + volatile uint32_t ISER[32]; + volatile uint32_t ICER[32]; + volatile uint32_t ISPR[32]; + volatile uint32_t ICPR[32]; + volatile uint32_t IABR[64]; + volatile uint8_t IPR[2816]; + volatile uint32_t STIR; +}; + +static NVIC_t& NVIC = *(NVIC_t*)0xe000e100; + +struct SCB_t { + volatile uint32_t CPUID; + volatile uint32_t ICSR; + volatile uint32_t VTOR; + volatile uint32_t AIRCR; + volatile uint32_t SCR; + volatile uint32_t CCR; + volatile uint8_t SHPR[12]; + volatile uint32_t SHCSR; + volatile uint32_t CFSR; + volatile uint32_t HFSR; + volatile uint32_t DFSR; + volatile uint32_t MMAR; + volatile uint32_t BFAR; +}; + +static SCB_t& SCB = *(SCB_t*)0xe000ed00; + +struct RCC_t { + volatile uint32_t CR; + volatile uint32_t CFGR; + volatile uint32_t CIR; + volatile uint32_t APB2RSTR; + volatile uint32_t APB1RSTR; + volatile uint32_t AHBENR; + volatile uint32_t APB2ENR; + volatile uint32_t APB1ENR; + volatile uint32_t BDCR; + volatile uint32_t CSR; + + enum AHB_dev { + DMA1 = 1 << 0, + DMA2 = 1 << 1, + SRAM = 1 << 2, + FLITF = 1 << 4, + CRC = 1 << 6, + FSMC = 1 << 8, + SDIO = 1 << 10 + }; + + enum APB1_dev { + TIM2 = 1 << 0, + TIM3 = 1 << 1, + TIM4 = 1 << 2, + TIM5 = 1 << 3, + TIM6 = 1 << 4, + TIM7 = 1 << 5, + TIM12 = 1 << 6, + TIM13 = 1 << 7, + TIM14 = 1 << 8, + WWDG = 1 << 11, + SPI2 = 1 << 14, + SPI3 = 1 << 15, + USART2 = 1 << 17, + USART3 = 1 << 18, + UART4 = 1 << 19, + UART5 = 1 << 20, + I2C1 = 1 << 21, + I2C2 = 1 << 22, + USB = 1 << 23, + CAN = 1 << 25, + BKP = 1 << 27, + PWR = 1 << 28, + DAC = 1 << 29 + }; + + enum APB2_dev { + AFIO = 1 << 0, + IOPA = 1 << 2, + IOPB = 1 << 3, + IOPC = 1 << 4, + IOPD = 1 << 5, + IOPE = 1 << 6, + IOPF = 1 << 7, + IOPG = 1 << 8, + ADC1 = 1 << 9, + ADC2 = 1 << 10, + TIM1 = 1 << 11, + SPI1 = 1 << 12, + TIM8 = 1 << 13, + USART1 = 1 << 14, + ADC3 = 1 << 15, + TIM9 = 1 << 19, + TIM10 = 1 << 20, + TIM11 = 1 << 21 + }; + + inline void enable(AHB_dev dev) { + AHBENR |= dev; + } + + inline void enable(APB1_dev dev) { + APB1ENR |= dev; + } + + inline void enable(APB2_dev dev) { + APB2ENR |= dev; + } +}; + +static RCC_t& RCC = *(RCC_t*)0x40021000; + +struct STK_t { + volatile uint32_t CTRL; + volatile uint32_t LOAD; + volatile uint32_t VAL; + volatile uint32_t CALIB; +}; + +static STK_t& STK = *(STK_t*)0xe000e010; + +struct FLASH_t { + volatile uint32_t ACR; + volatile uint32_t KEYR; + volatile uint32_t OPTKEYR; + volatile uint32_t SR; + volatile uint32_t CR; + volatile uint32_t AR; + volatile uint32_t RESERVED; + volatile uint32_t OBR; + volatile uint32_t WRPR; +}; + +static FLASH_t& FLASH = *(FLASH_t*)0x40022000; + +struct GPIO_t { + volatile uint32_t CRL; + volatile uint32_t CRH; + volatile uint32_t IDR; + volatile uint32_t ODR; + volatile uint32_t BSRR; + volatile uint32_t BRR; + volatile uint32_t LCKR; +}; + +static GPIO_t& GPIOA = *(GPIO_t*)0x40010800; +static GPIO_t& GPIOB = *(GPIO_t*)0x40010c00; +static GPIO_t& GPIOC = *(GPIO_t*)0x40011000; + +struct I2C_t { + volatile uint32_t CR1; + volatile uint32_t CR2; + volatile uint32_t OAR1; + volatile uint32_t OAR2; + volatile uint32_t DR; + volatile uint32_t SR1; + volatile uint32_t SR2; + volatile uint32_t CCR; + volatile uint32_t TRISE; +}; + +static I2C_t& I2C1 = *(I2C_t*)0x40005400; +static I2C_t& I2C2 = *(I2C_t*)0x40005800; + +struct USART_t { + volatile uint32_t SR; + volatile uint32_t DR; + volatile uint32_t BRR; + volatile uint32_t CR1; + volatile uint32_t CR2; + volatile uint32_t CR3; + volatile uint32_t GTPR; +}; + +static USART_t& USART1 = *(USART_t*)0x40013800; +static USART_t& USART2 = *(USART_t*)0x40004400; +static USART_t& USART3 = *(USART_t*)0x40004800; + +struct TIM_t { + volatile uint32_t CR1; + volatile uint32_t CR2; + volatile uint32_t SMCR; + volatile uint32_t DIER; + volatile uint32_t SR; + volatile uint32_t EGR; + volatile uint32_t CCMR1; + volatile uint32_t CCMR2; + volatile uint32_t CCER; + volatile uint32_t CNT; + volatile uint32_t PSC; + volatile uint32_t ARR; + volatile uint32_t RCR; + volatile uint32_t CCR1; + volatile uint32_t CCR2; + volatile uint32_t CCR3; + volatile uint32_t CCR4; + volatile uint32_t BDTR; + volatile uint32_t DCR; + volatile uint32_t DMAR; +}; + +static TIM_t& TIM1 = *(TIM_t*)0x40012c00; +static TIM_t& TIM2 = *(TIM_t*)0x40000000; +static TIM_t& TIM3 = *(TIM_t*)0x40000400; +static TIM_t& TIM4 = *(TIM_t*)0x40000800; +static TIM_t& TIM5 = *(TIM_t*)0x40000c00; +static TIM_t& TIM6 = *(TIM_t*)0x40001000; +static TIM_t& TIM7 = *(TIM_t*)0x40001400; +static TIM_t& TIM8 = *(TIM_t*)0x40013400; + +struct ADC_t { + volatile uint32_t SR; + volatile uint32_t CR1; + volatile uint32_t CR2; + volatile uint32_t SMPR1; + volatile uint32_t SMPR2; + volatile uint32_t JOFR1; + volatile uint32_t JOFR2; + volatile uint32_t JOFR3; + volatile uint32_t JOFR4; + volatile uint32_t HTR; + volatile uint32_t LTR; + volatile uint32_t SQR1; + volatile uint32_t SQR2; + volatile uint32_t SQR3; + volatile uint32_t JSQR; + volatile uint32_t JDR1; + volatile uint32_t JDR2; + volatile uint32_t JDR3; + volatile uint32_t JDR4; + volatile uint32_t DR; +}; + +static ADC_t& ADC1 = *(ADC_t*)0x40012400; +static ADC_t& ADC2 = *(ADC_t*)0x40012800; +static ADC_t& ADC3 = *(ADC_t*)0x40013c00; + +struct DMA_t { + struct CH_t { + volatile uint32_t CCR; + volatile uint32_t CNDTR; + volatile uint32_t CPAR; + volatile uint32_t CMAR; + uint32_t _reserved; + }; + + volatile uint32_t ISR; + volatile uint32_t IFCR; + CH_t CH[7]; +}; + +static DMA_t& DMA1 = *(DMA_t*)0x40020000; +static DMA_t& DMA2 = *(DMA_t*)0x40020400; + +#endif diff --git a/hal/usart.h b/hal/usart.h new file mode 100644 index 0000000..8fde39a --- /dev/null +++ b/hal/usart.h @@ -0,0 +1,26 @@ +#ifndef USART_H +#define USART_H + +template<> +void interrupt() { + USART1.DR; + //GPIOB.ODR ^= 1 << 1; +} + +void usart_enable() { + RCC.enable(RCC.USART1); + USART1.BRR = 625; // 115200 baud + USART1.CR1 = 0x202c; + + Interrupt::enable(Interrupt::USART1); +} + +void usart_send(uint8_t data) { + while(!(USART1.SR & 0x80)) { + Thread::yield(); + } // Wait for TXE. + + USART1.DR = data; +} + +#endif diff --git a/i2c.cpp b/i2c.cpp deleted file mode 100644 index cee72ec..0000000 --- a/i2c.cpp +++ /dev/null @@ -1,194 +0,0 @@ -#include "i2c.h" - -#include "stm32.h" -#include "thread.h" - -I2C* I2C::self; - -template <> -void interrupt() { - I2C::self->irq_ev(); -} - -template <> -void interrupt() { - I2C::self->irq_er(); -} - -void I2C::irq_ev() { - uint32_t sr1 = I2C1.SR1; - I2C1.SR2; - - // EV5, SB = 1: Start condition sent. - if(sr1 & 0x01) { - // Send address. - I2C1.DR = (addr << 1) | (writing ? 0 : 1); - } - - // EV6, ADDR = 1: Address sent. - if(sr1 & 0x02) { - if(writing) { - I2C1.DR = *write_p++; - writing--; - } else { - if(reading > 1) { - I2C1.CR1 |= 0x400; // Set ACK. - } else { - I2C1.CR1 |= 0x200; // Set STOP. - } - } - } - - // EV7, RxNE = 1: Receive buffer not empty. - if(sr1 & 0x40) { - *read_p++ = I2C1.DR; - reading--; - - if(reading == 1) { - // Unset ACK, set STOP. - I2C1.CR1 = (I2C1.CR1 & ~0x400) | 0x200; - } - - if(reading == 0) { - busy = 0; - } - } - - //I2C1.CR1 &= ~0x400; - - // EV8, TxE = 1, BTF = 0: Transmit buffer empty, still writing. - if(sr1 & 0x80 && !(sr1 & 0x04)) { - if(writing) { - // Send data. - I2C1.DR = *write_p++; - writing--; - } else { - // All data sent. - - if(reading) { - // Send repeat start. - I2C1.CR1 |= 0x100; - } else { - // Send stop. - I2C1.CR1 |= 0x200; - busy = 0; - } - } - } -} - -void I2C::irq_er() { - handle_error(); -} - -void I2C::handle_error() { - I2C1.SR1; - I2C1.SR2; - - //while(1); - I2C1.CR1 |= 0x200; - busy = 0; -} - -void I2C::enable() { - RCC.enable(RCC.I2C1); - asm volatile("nop"); - - I2C1.CR1 = 0x8000; - I2C1.CR1 = 0; - - I2C1.CR2 = 0x700 | 36; - I2C1.TRISE = 37; - I2C1.CCR = 180; - - Interrupt::enable(Interrupt::I2C1_EV); - Interrupt::enable(Interrupt::I2C1_ER); - - I2C1.CR1 = 1; -} - -void I2C::write_reg(uint8_t addr_, uint8_t reg, uint8_t data) { - addr = addr_; - writing = 2; - reading = 0; - volatile uint8_t buf[] = {reg, data}; - write_p = buf; - busy = 1; - - I2C1.CR1 |= 0x100; - - while(busy) { - Thread::yield(); - } - - /* - while(!(I2C1.SR1 & 0x01)); // Wait for SB. - - I2C1.DR = (addr << 1) | 0; - while (!(I2C1.SR1 & 0x02)); // Wait for ADDR. - I2C1.SR2; - - I2C1.DR = reg; - while (!(I2C1.SR1 & 0x80)); // Wait for TxE. - - I2C1.DR = data; - while (!(I2C1.SR1 & 0x04)); // Wait for BTF. - - I2C1.CR1 |= 0x200;*/ -} - -void I2C::read_reg(uint8_t addr_, uint8_t reg, uint8_t len, uint8_t* buf) { - addr = addr_; - writing = 1; - reading = len; - write_p = ® - read_p = buf; - busy = 1; - - I2C1.CR1 |= 0x100; - - while(busy) { - Thread::yield(); - } - - /* - I2C1.CR1 |= 0x100; - while(!(I2C1.SR1 & 0x01)); // Wait for SB. - - I2C1.DR = (addr << 1) | 0; - while (!(I2C1.SR1 & 0x02)); // Wait for ADDR. - I2C1.SR2; - - I2C1.DR = reg; - while (!(I2C1.SR1 & 0x80)); // Wait for TxE. - - I2C1.CR1 |= 0x100; - while(!(I2C1.SR1 & 0x01)); // Wait for SB. - - I2C1.DR = (addr << 1) | 1; - while (!(I2C1.SR1 & 0x02)); // Wait for ADDR. - I2C1.SR2; - - I2C1.CR1 |= 0x400; // Set ACK. - - while(len) { - if(len == 3) { - while (!(I2C1.SR1 & 0x04)); // Wait for BTF. - - I2C1.CR1 &= ~0x400; // Clear ACK. - *buf++ = I2C1.DR; - len--; - - I2C1.CR1 |= 0x200; // Set STOP. - *buf++ = I2C1.DR; - len--; - - } else { - while (!(I2C1.SR1 & 0x40)); // Wait for RxNE. - - *buf++ = I2C1.DR; - len--; - } - } - */ -} diff --git a/i2c.h b/i2c.h deleted file mode 100644 index 3d58056..0000000 --- a/i2c.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef I2C_H -#define I2C_H - -#include - -#include "interrupt.h" - -class I2C { - friend void interrupt(); - friend void interrupt(); - - private: - static I2C* self; - - volatile uint8_t addr; - volatile uint8_t writing; - volatile uint8_t reading; - volatile uint8_t* write_p; - volatile uint8_t* read_p; - - volatile bool busy; - - void irq_ev(); - void irq_er(); - void handle_error(); - - public: - I2C() { - self = this; - } - - void enable(); - - void write_reg(uint8_t addr_, uint8_t reg, uint8_t data); - void read_reg(uint8_t addr_, uint8_t reg, uint8_t len, uint8_t* buf); -}; - - - -#endif diff --git a/interrupt.cpp b/interrupt.cpp deleted file mode 100644 index e9e7b24..0000000 --- a/interrupt.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "interrupt.h" - -void entry(); - -extern "C" void unused_interrupt() { - while(1) {} -} - -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); -template<> void interrupt() __attribute__ ((weak, alias ("unused_interrupt"))); - -typedef void (*vector_t)(); - -vector_t vectors[] __attribute__((section(".vectors"))) = { - (vector_t)0x20004ffc, - entry, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - 0, - 0, - 0, - 0, - interrupt, - 0, - 0, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, - interrupt, -}; diff --git a/interrupt.h b/interrupt.h deleted file mode 100644 index f817103..0000000 --- a/interrupt.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef INTERRUPT_H -#define INTERRUPT_H - -#include "stm32.h" - -namespace Interrupt { - enum Exception { - NMI = 2, - HardFault = 3, - MemManage = 4, - BusFault = 5, - UsageFault = 6, - SVCall = 11, - PendSV = 14, - SysTick = 15 - }; - - enum IRQ { - WWDG, - PVD, - TAMPER, - RTC, - FLASH, - RCC, - EXTI0, - EXTI1, - EXTI2, - EXTI3, - EXTI4, - DMA1_Channel1, - DMA1_Channel2, - DMA1_Channel3, - DMA1_Channel4, - DMA1_Channel5, - DMA1_Channel6, - DMA1_Channel7, - ADC1_2, - USB_HP_CAN_TX, - USB_LP_CAN_RX0, - CAN_RX1, - CAN_SCE, - EXTI9_5, - TIM1_BRK, - TIM1_UP, - TIM1_TRG_COM, - TIM1_CC, - TIM2, - TIM3, - TIM4, - I2C1_EV, - I2C1_ER, - I2C2_EV, - I2C2_ER, - SPI1, - SPI2, - USART1, - USART2, - USART3, - EXTI15_10, - RTCAlarm, - USBWakeup, - TIM8_BRK, - TIM8_UP, - TIM8_TRG_COM, - TIM8_CC, - ADC3, - FSMC, - SDIO, - TIM5, - SPI3, - UART4, - UART5, - TIM6, - TIM7, - DMA2_Channel1, - DMA2_Channel2, - DMA2_Channel3, - DMA2_Channel4_5 - }; - - inline void enable(IRQ n) { - NVIC.ISER[n >> 5] = 1 << (n & 0x1f); - } - - inline void set_priority(Exception n, uint8_t priority) { - SCB.SHPR[n - 4] = priority; - } - - inline void set_priority(IRQ n, uint8_t priority) { - NVIC.IPR[n] = priority; - } -}; - -template -void interrupt(); - -template -void interrupt(); - -#endif diff --git a/main.cpp b/main.cpp index b576869..635467b 100644 --- a/main.cpp +++ b/main.cpp @@ -127,7 +127,8 @@ Thread gps_thread(gps_stack, sizeof(gps_stack), gps_thread_main); int main() { // Initialize system timer. - Time::init(); + STK.LOAD = 72000000 / 8 / 1000; // 1000 Hz. + STK.CTRL = 0x03; RCC.enable(RCC.AFIO); RCC.enable(RCC.IOPA); diff --git a/mutex.h b/mutex.h deleted file mode 100644 index d12331d..0000000 --- a/mutex.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef MUTEX_H -#define MUTEX_H - -class Mutex { - private: - uint8_t locked; - public: - Mutex() : locked(0) {} - Mutex(uint8_t l) : locked(l) {} - - bool trylock() { - uint8_t val; - - // Check if mutex is locked. - asm volatile ("ldrexb %0, [%1]" : "=r" (val) : "r" (&locked)); - if(val) { - return false; - } - - // Try taking the lock. - asm volatile ("strexb %0, %1, [%2]" : "=r" (val) : "r" (1), "r" (&locked)); - if(val) { - return false; - } - - asm volatile("dmb"); - return true; - } - - void lock() { - while(!trylock()) { - Thread::yield(); - } - } - - void unlock() { - asm volatile("dmb"); - locked = 0; - } -}; - -#endif diff --git a/os/mutex.h b/os/mutex.h new file mode 100644 index 0000000..d12331d --- /dev/null +++ b/os/mutex.h @@ -0,0 +1,42 @@ +#ifndef MUTEX_H +#define MUTEX_H + +class Mutex { + private: + uint8_t locked; + public: + Mutex() : locked(0) {} + Mutex(uint8_t l) : locked(l) {} + + bool trylock() { + uint8_t val; + + // Check if mutex is locked. + asm volatile ("ldrexb %0, [%1]" : "=r" (val) : "r" (&locked)); + if(val) { + return false; + } + + // Try taking the lock. + asm volatile ("strexb %0, %1, [%2]" : "=r" (val) : "r" (1), "r" (&locked)); + if(val) { + return false; + } + + asm volatile("dmb"); + return true; + } + + void lock() { + while(!trylock()) { + Thread::yield(); + } + } + + void unlock() { + asm volatile("dmb"); + locked = 0; + } +}; + +#endif diff --git a/os/pool.cpp b/os/pool.cpp new file mode 100644 index 0000000..f059b05 --- /dev/null +++ b/os/pool.cpp @@ -0,0 +1,5 @@ +#include "pool.h" + +void* operator new(unsigned int, char* buf) { + return (void*)buf; +} diff --git a/os/pool.h b/os/pool.h new file mode 100644 index 0000000..1cb0a71 --- /dev/null +++ b/os/pool.h @@ -0,0 +1,146 @@ +#ifndef POOL_H +#define POOL_H + +#include "stdint.h" + +template +class BasePool { + public: + struct Element { + unsigned int use_count; + BasePool* pool; + + char data[sizeof(T)]; + }; + + virtual void free(Element* e) = 0; +}; + +template +class P { + private: + typedef typename BasePool::Element Element; + + Element* e; + + void inc() { + e->use_count++; + } + + void dec() { + e->use_count--; + if(!e->use_count) { + T* p = (T*)e->data; + p->~T(); + e->pool->free(e); + } + } + + public: + P() : e(0) {} + + explicit P(Element* ep) : e(ep) { + inc(); + } + + P(const P& p) : e(p.e) { + inc(); + } + + ~P() { + if(e) { + dec(); + } + } + + void operator=(const P& p) { + if(e) { + dec(); + } + + e = p.e; + + if(e) { + inc(); + } + } + + void reset() { + if(e) { + dec(); + } + + e = 0; + } + + T* operator->() { + return (T*)e->data; + } + + T* operator*() { + return (T*)e->data; + } + + operator bool() { + return bool(e); + } +}; + +template +class Pool : public BasePool { + private: + typedef typename BasePool::Element Element; + + union Node { + Element e; + Node* next; + }; + + Node elements[size]; + + Node* next_free; + + void free(Element* e) { + Node* n = (Node*)e; + + n->next = next_free; + next_free = n; + } + + Element* alloc() { + if(!next_free) { + return 0; + } + + Element* e = &next_free->e; + next_free = next_free->next; + + e->use_count = 0; + e->pool = this; + + return e; + } + + public: + Pool() : next_free(0) { + for(unsigned int i = 0; i < size; i++) { + free(&elements[i].e); + } + } + + P create() { + Element* e = alloc(); + + if(!e) { + return P(); + } + + new (e->data) T; + + return P(e); + } +}; + +void* operator new(unsigned int, char* buf); + +#endif diff --git a/os/thread.cpp b/os/thread.cpp new file mode 100644 index 0000000..426fffd --- /dev/null +++ b/os/thread.cpp @@ -0,0 +1,4 @@ +#include "thread.h" + +Thread Thread::main_thread __attribute__ ((init_priority (1000))); +Thread* Thread::active_thread = &Thread::main_thread; diff --git a/os/thread.h b/os/thread.h new file mode 100644 index 0000000..2213d6f --- /dev/null +++ b/os/thread.h @@ -0,0 +1,63 @@ +#ifndef THREAD_H +#define THREAD_H + +#include + +class Thread { + friend void switch_context(); + + private: + struct int_frame_t { + // Software saved. + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t lr_ex; + + // Hardware saved. + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r12; + uint32_t lr; + uint32_t pc; + uint32_t psr; + }; + + int_frame_t* sp; + + Thread* next; + + static Thread* active_thread; + static Thread main_thread; + + Thread() : next(this) {} + + public: + Thread(void* stack, uint32_t stack_size, void (*func)()) { + sp = (int_frame_t*)((uint8_t*)stack + stack_size - sizeof(int_frame_t)); + + sp->lr_ex = 0xfffffff9; + + // frame->lr = thread exit handler + sp->pc = (uint32_t)func; + sp->psr = 0x01000000; + } + + void start() { + next = active_thread->next; + active_thread->next = this; + } + + static inline void yield() { + asm volatile("svc 0"); + } +}; + +#endif diff --git a/os/time.cpp b/os/time.cpp new file mode 100644 index 0000000..6c96027 --- /dev/null +++ b/os/time.cpp @@ -0,0 +1,3 @@ +#include "time.h" + +volatile uint32_t Time::systime; diff --git a/os/time.h b/os/time.h new file mode 100644 index 0000000..f4706e0 --- /dev/null +++ b/os/time.h @@ -0,0 +1,23 @@ +#ifndef TIME_H +#define TIME_H + +#include "thread.h" + +class Time { + private: + static volatile uint32_t systime; + + public: + inline static void tick() { + systime++; + } + + inline static void sleep(uint32_t ms) { + ms += systime; + while(systime < ms) { + Thread::yield(); + } + } +}; + +#endif diff --git a/pool.cpp b/pool.cpp deleted file mode 100644 index f059b05..0000000 --- a/pool.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "pool.h" - -void* operator new(unsigned int, char* buf) { - return (void*)buf; -} diff --git a/pool.h b/pool.h deleted file mode 100644 index 1cb0a71..0000000 --- a/pool.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef POOL_H -#define POOL_H - -#include "stdint.h" - -template -class BasePool { - public: - struct Element { - unsigned int use_count; - BasePool* pool; - - char data[sizeof(T)]; - }; - - virtual void free(Element* e) = 0; -}; - -template -class P { - private: - typedef typename BasePool::Element Element; - - Element* e; - - void inc() { - e->use_count++; - } - - void dec() { - e->use_count--; - if(!e->use_count) { - T* p = (T*)e->data; - p->~T(); - e->pool->free(e); - } - } - - public: - P() : e(0) {} - - explicit P(Element* ep) : e(ep) { - inc(); - } - - P(const P& p) : e(p.e) { - inc(); - } - - ~P() { - if(e) { - dec(); - } - } - - void operator=(const P& p) { - if(e) { - dec(); - } - - e = p.e; - - if(e) { - inc(); - } - } - - void reset() { - if(e) { - dec(); - } - - e = 0; - } - - T* operator->() { - return (T*)e->data; - } - - T* operator*() { - return (T*)e->data; - } - - operator bool() { - return bool(e); - } -}; - -template -class Pool : public BasePool { - private: - typedef typename BasePool::Element Element; - - union Node { - Element e; - Node* next; - }; - - Node elements[size]; - - Node* next_free; - - void free(Element* e) { - Node* n = (Node*)e; - - n->next = next_free; - next_free = n; - } - - Element* alloc() { - if(!next_free) { - return 0; - } - - Element* e = &next_free->e; - next_free = next_free->next; - - e->use_count = 0; - e->pool = this; - - return e; - } - - public: - Pool() : next_free(0) { - for(unsigned int i = 0; i < size; i++) { - free(&elements[i].e); - } - } - - P create() { - Element* e = alloc(); - - if(!e) { - return P(); - } - - new (e->data) T; - - return P(e); - } -}; - -void* operator new(unsigned int, char* buf); - -#endif diff --git a/rcc.cpp b/rcc.cpp deleted file mode 100644 index e3ae38d..0000000 --- a/rcc.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "rcc.h" -#include "stm32.h" - -void rcc_init() { - // Set flash latency. - FLASH.ACR = 0x12; - - // Enable HSE. - RCC.CR |= 0x10000; - while(RCC.CR & 0x20000); - - // Configure and enable PLL. - RCC.CFGR = 0x1d0000; - RCC.CR |= 0x1000000; - while(RCC.CR & 0x2000000); - - // Switch to PLL. - RCC.CFGR |= 0x2; - while(!(RCC.CFGR & 0x8)); - - // Set APB1 prescaler to /2. - RCC.CFGR |= 0x400; - - // Set ADCCLK prescaler to /6. - RCC.CFGR |= 0x8000; -} diff --git a/rcc.h b/rcc.h deleted file mode 100644 index 8c5fb86..0000000 --- a/rcc.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef RCC_H -#define RCC_H - -void rcc_init(); - -#endif diff --git a/stm32.h b/stm32.h deleted file mode 100644 index 8144e80..0000000 --- a/stm32.h +++ /dev/null @@ -1,262 +0,0 @@ -#ifndef STM32_H -#define STM32_H - -#include - -struct NVIC_t { - volatile uint32_t ISER[32]; - volatile uint32_t ICER[32]; - volatile uint32_t ISPR[32]; - volatile uint32_t ICPR[32]; - volatile uint32_t IABR[64]; - volatile uint8_t IPR[2816]; - volatile uint32_t STIR; -}; - -static NVIC_t& NVIC = *(NVIC_t*)0xe000e100; - -struct SCB_t { - volatile uint32_t CPUID; - volatile uint32_t ICSR; - volatile uint32_t VTOR; - volatile uint32_t AIRCR; - volatile uint32_t SCR; - volatile uint32_t CCR; - volatile uint8_t SHPR[12]; - volatile uint32_t SHCSR; - volatile uint32_t CFSR; - volatile uint32_t HFSR; - volatile uint32_t DFSR; - volatile uint32_t MMAR; - volatile uint32_t BFAR; -}; - -static SCB_t& SCB = *(SCB_t*)0xe000ed00; - -struct RCC_t { - volatile uint32_t CR; - volatile uint32_t CFGR; - volatile uint32_t CIR; - volatile uint32_t APB2RSTR; - volatile uint32_t APB1RSTR; - volatile uint32_t AHBENR; - volatile uint32_t APB2ENR; - volatile uint32_t APB1ENR; - volatile uint32_t BDCR; - volatile uint32_t CSR; - - enum AHB_dev { - DMA1 = 1 << 0, - DMA2 = 1 << 1, - SRAM = 1 << 2, - FLITF = 1 << 4, - CRC = 1 << 6, - FSMC = 1 << 8, - SDIO = 1 << 10 - }; - - enum APB1_dev { - TIM2 = 1 << 0, - TIM3 = 1 << 1, - TIM4 = 1 << 2, - TIM5 = 1 << 3, - TIM6 = 1 << 4, - TIM7 = 1 << 5, - TIM12 = 1 << 6, - TIM13 = 1 << 7, - TIM14 = 1 << 8, - WWDG = 1 << 11, - SPI2 = 1 << 14, - SPI3 = 1 << 15, - USART2 = 1 << 17, - USART3 = 1 << 18, - UART4 = 1 << 19, - UART5 = 1 << 20, - I2C1 = 1 << 21, - I2C2 = 1 << 22, - USB = 1 << 23, - CAN = 1 << 25, - BKP = 1 << 27, - PWR = 1 << 28, - DAC = 1 << 29 - }; - - enum APB2_dev { - AFIO = 1 << 0, - IOPA = 1 << 2, - IOPB = 1 << 3, - IOPC = 1 << 4, - IOPD = 1 << 5, - IOPE = 1 << 6, - IOPF = 1 << 7, - IOPG = 1 << 8, - ADC1 = 1 << 9, - ADC2 = 1 << 10, - TIM1 = 1 << 11, - SPI1 = 1 << 12, - TIM8 = 1 << 13, - USART1 = 1 << 14, - ADC3 = 1 << 15, - TIM9 = 1 << 19, - TIM10 = 1 << 20, - TIM11 = 1 << 21 - }; - - inline void enable(AHB_dev dev) { - AHBENR |= dev; - } - - inline void enable(APB1_dev dev) { - APB1ENR |= dev; - } - - inline void enable(APB2_dev dev) { - APB2ENR |= dev; - } -}; - -static RCC_t& RCC = *(RCC_t*)0x40021000; - -struct STK_t { - volatile uint32_t CTRL; - volatile uint32_t LOAD; - volatile uint32_t VAL; - volatile uint32_t CALIB; -}; - -static STK_t& STK = *(STK_t*)0xe000e010; - -struct FLASH_t { - volatile uint32_t ACR; - volatile uint32_t KEYR; - volatile uint32_t OPTKEYR; - volatile uint32_t SR; - volatile uint32_t CR; - volatile uint32_t AR; - volatile uint32_t RESERVED; - volatile uint32_t OBR; - volatile uint32_t WRPR; -}; - -static FLASH_t& FLASH = *(FLASH_t*)0x40022000; - -struct GPIO_t { - volatile uint32_t CRL; - volatile uint32_t CRH; - volatile uint32_t IDR; - volatile uint32_t ODR; - volatile uint32_t BSRR; - volatile uint32_t BRR; - volatile uint32_t LCKR; -}; - -static GPIO_t& GPIOA = *(GPIO_t*)0x40010800; -static GPIO_t& GPIOB = *(GPIO_t*)0x40010c00; -static GPIO_t& GPIOC = *(GPIO_t*)0x40011000; - -struct I2C_t { - volatile uint32_t CR1; - volatile uint32_t CR2; - volatile uint32_t OAR1; - volatile uint32_t OAR2; - volatile uint32_t DR; - volatile uint32_t SR1; - volatile uint32_t SR2; - volatile uint32_t CCR; - volatile uint32_t TRISE; -}; - -static I2C_t& I2C1 = *(I2C_t*)0x40005400; -static I2C_t& I2C2 = *(I2C_t*)0x40005800; - -struct USART_t { - volatile uint32_t SR; - volatile uint32_t DR; - volatile uint32_t BRR; - volatile uint32_t CR1; - volatile uint32_t CR2; - volatile uint32_t CR3; - volatile uint32_t GTPR; -}; - -static USART_t& USART1 = *(USART_t*)0x40013800; -static USART_t& USART2 = *(USART_t*)0x40004400; -static USART_t& USART3 = *(USART_t*)0x40004800; - -struct TIM_t { - volatile uint32_t CR1; - volatile uint32_t CR2; - volatile uint32_t SMCR; - volatile uint32_t DIER; - volatile uint32_t SR; - volatile uint32_t EGR; - volatile uint32_t CCMR1; - volatile uint32_t CCMR2; - volatile uint32_t CCER; - volatile uint32_t CNT; - volatile uint32_t PSC; - volatile uint32_t ARR; - volatile uint32_t RCR; - volatile uint32_t CCR1; - volatile uint32_t CCR2; - volatile uint32_t CCR3; - volatile uint32_t CCR4; - volatile uint32_t BDTR; - volatile uint32_t DCR; - volatile uint32_t DMAR; -}; - -static TIM_t& TIM1 = *(TIM_t*)0x40012c00; -static TIM_t& TIM2 = *(TIM_t*)0x40000000; -static TIM_t& TIM3 = *(TIM_t*)0x40000400; -static TIM_t& TIM4 = *(TIM_t*)0x40000800; -static TIM_t& TIM5 = *(TIM_t*)0x40000c00; -static TIM_t& TIM6 = *(TIM_t*)0x40001000; -static TIM_t& TIM7 = *(TIM_t*)0x40001400; -static TIM_t& TIM8 = *(TIM_t*)0x40013400; - -struct ADC_t { - volatile uint32_t SR; - volatile uint32_t CR1; - volatile uint32_t CR2; - volatile uint32_t SMPR1; - volatile uint32_t SMPR2; - volatile uint32_t JOFR1; - volatile uint32_t JOFR2; - volatile uint32_t JOFR3; - volatile uint32_t JOFR4; - volatile uint32_t HTR; - volatile uint32_t LTR; - volatile uint32_t SQR1; - volatile uint32_t SQR2; - volatile uint32_t SQR3; - volatile uint32_t JSQR; - volatile uint32_t JDR1; - volatile uint32_t JDR2; - volatile uint32_t JDR3; - volatile uint32_t JDR4; - volatile uint32_t DR; -}; - -static ADC_t& ADC1 = *(ADC_t*)0x40012400; -static ADC_t& ADC2 = *(ADC_t*)0x40012800; -static ADC_t& ADC3 = *(ADC_t*)0x40013c00; - -struct DMA_t { - struct CH_t { - volatile uint32_t CCR; - volatile uint32_t CNDTR; - volatile uint32_t CPAR; - volatile uint32_t CMAR; - uint32_t _reserved; - }; - - volatile uint32_t ISR; - volatile uint32_t IFCR; - CH_t CH[7]; -}; - -static DMA_t& DMA1 = *(DMA_t*)0x40020000; -static DMA_t& DMA2 = *(DMA_t*)0x40020400; - -#endif diff --git a/thread.cpp b/thread.cpp deleted file mode 100644 index a08bd61..0000000 --- a/thread.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "thread.h" -#include "interrupt.h" - -Thread Thread::main_thread __attribute__ ((init_priority (1000))); -Thread* Thread::active_thread = &Thread::main_thread; - -inline void __attribute__((naked)) switch_context() { - asm volatile ("cpsid i"); - - // Save unsaved registers. - asm volatile ("push {r4, r5, r6, r7, r8, r9, r10, r11, lr}" ::: "memory"); - - // Store stack pointer for old thread. - asm volatile ("str sp, [%0]" :: "r" (&Thread::active_thread->sp)); - - // Update running thread. - Thread::active_thread = Thread::active_thread->next; - - // Fetch stack pointer for new thread. - asm volatile ("ldr sp, [%0]" :: "r" (&Thread::active_thread->sp)); - - asm volatile ("cpsie i"); - - // Load registers and return. - asm volatile ("pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}" ::: "memory"); -} - -template<> -void interrupt() { - switch_context(); -} diff --git a/thread.h b/thread.h deleted file mode 100644 index 2213d6f..0000000 --- a/thread.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef THREAD_H -#define THREAD_H - -#include - -class Thread { - friend void switch_context(); - - private: - struct int_frame_t { - // Software saved. - uint32_t r4; - uint32_t r5; - uint32_t r6; - uint32_t r7; - uint32_t r8; - uint32_t r9; - uint32_t r10; - uint32_t r11; - uint32_t lr_ex; - - // Hardware saved. - uint32_t r0; - uint32_t r1; - uint32_t r2; - uint32_t r3; - uint32_t r12; - uint32_t lr; - uint32_t pc; - uint32_t psr; - }; - - int_frame_t* sp; - - Thread* next; - - static Thread* active_thread; - static Thread main_thread; - - Thread() : next(this) {} - - public: - Thread(void* stack, uint32_t stack_size, void (*func)()) { - sp = (int_frame_t*)((uint8_t*)stack + stack_size - sizeof(int_frame_t)); - - sp->lr_ex = 0xfffffff9; - - // frame->lr = thread exit handler - sp->pc = (uint32_t)func; - sp->psr = 0x01000000; - } - - void start() { - next = active_thread->next; - active_thread->next = this; - } - - static inline void yield() { - asm volatile("svc 0"); - } -}; - -#endif diff --git a/time.cpp b/time.cpp deleted file mode 100644 index a5d1f0b..0000000 --- a/time.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "time.h" -#include "interrupt.h" - -volatile uint32_t Time::systime; - -template<> -void interrupt() { - Time::systime++; -} diff --git a/time.h b/time.h deleted file mode 100644 index f43d8a6..0000000 --- a/time.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef TIME_H -#define TIME_H - -#include "stm32.h" -#include "interrupt.h" -#include "thread.h" - -class Time { - friend void interrupt(); - - private: - static volatile uint32_t systime; - - public: - static void init() { - STK.LOAD = 72000000 / 8 / 1000; // 1000 Hz. - STK.CTRL = 0x03; - } - - inline static void sleep(uint32_t ms) { - ms += systime; - while(systime < ms) { - Thread::yield(); - } - } -}; - -#endif diff --git a/usart.h b/usart.h deleted file mode 100644 index 8fde39a..0000000 --- a/usart.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef USART_H -#define USART_H - -template<> -void interrupt() { - USART1.DR; - //GPIOB.ODR ^= 1 << 1; -} - -void usart_enable() { - RCC.enable(RCC.USART1); - USART1.BRR = 625; // 115200 baud - USART1.CR1 = 0x202c; - - Interrupt::enable(Interrupt::USART1); -} - -void usart_send(uint8_t data) { - while(!(USART1.SR & 0x80)) { - Thread::yield(); - } // Wait for TXE. - - USART1.DR = data; -} - -#endif -- cgit v1.2.3