diff --git a/src/application/spi/main.cc b/src/application/spi/main.cc index c6fff86..3f742f9 100644 --- a/src/application/spi/main.cc +++ b/src/application/spi/main.cc @@ -1,9 +1,9 @@ -#include "delay.h" - #include "platform/cm4/InterruptHandler.h" #include "platform/cm4/InterruptGuardian.h" +#include "platform/cm4/SystemTick.h" + #include "platform/nrf52/gpio.h" #include "platform/nrf52/spi.h" #include "platform/nrf52/InterruptHandler.h" @@ -11,19 +11,22 @@ using namespace pinetime::platform; -const uint8_t buf[] = "Test"; +uint8_t buf[] = "Test"; nrf52::Gpio led_1(17); nrf52::Gpio lcd_chip_select(25); -nrf52::Spi spi_0(0, 2, 3, 4, lcd_chip_select); cm4::InterruptGuardian cm4::InterruptGuardian::instance; nrf52::InterruptGuardian nrf52::InterruptGuardian::instance; int main(void) { + cm4::SystemTick ticker; + ticker.enable(); + + cm4::InterruptGuardian::enable_interrupts(); + nrf52::Spi spi_0(0, 2, 3, 4, lcd_chip_select); while(1) { - delay_ms(200); spi_0.send(buf, sizeof(buf)); led_1.toggle(); } diff --git a/src/application/st7789_lcd/main.cc b/src/application/st7789_lcd/main.cc index 0b5333d..b3a7ba1 100644 --- a/src/application/st7789_lcd/main.cc +++ b/src/application/st7789_lcd/main.cc @@ -1,5 +1,3 @@ -#include "delay.h" - #include "platform/cm4/InterruptHandler.h" #include "platform/cm4/InterruptGuardian.h" @@ -26,10 +24,10 @@ nrf52::InterruptGuardian nrf52::InterruptGuardian::instance; int main(void) { + cm4::InterruptGuardian::enable_interrupts(); lcd.init(); lcd.clear(0); while(true) { - delay_ms(200); led_1.toggle(); } } diff --git a/src/platform/nrf52/InterruptGuardian.h b/src/platform/nrf52/InterruptGuardian.h index 08ead62..594d4ba 100644 --- a/src/platform/nrf52/InterruptGuardian.h +++ b/src/platform/nrf52/InterruptGuardian.h @@ -15,43 +15,43 @@ public: InterruptGuardian(); enum Nrf52IrqN { - POWER_CLOCK_IRQn, //!< 0 POWER_CLOCK - RADIO_IRQn, //!< 1 RADIO - UARTE0_UART0_IRQn, //!< 2 UARTE0_UART0 - SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, //!< 3 SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 - SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn, //!< 4 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 - NFCT_IRQn, //!< 5 NFCT - GPIOTE_IRQn, //!< 6 GPIOTE - SAADC_IRQn, //!< 7 SAADC - TIMER0_IRQn, //!< 8 TIMER0 - TIMER1_IRQn, //!< 9 TIMER1 - TIMER2_IRQn, //!< 10 TIMER2 - RTC0_IRQn, //!< 11 RTC0 - TEMP_IRQn, //!< 12 TEMP - RNG_IRQn, //!< 13 RNG - ECB_IRQn, //!< 14 ECB - CCM_AAR_IRQn, //!< 15 CCM_AAR - WDT_IRQn, //!< 16 WDT - RTC1_IRQn, //!< 17 RTC1 - QDEC_IRQn, //!< 18 QDEC - COMP_LPCOMP_IRQn, //!< 19 COMP_LPCOMP - SWI0_EGU0_IRQn, //!< 20 SWI0_EGU0 - SWI1_EGU1_IRQn, //!< 21 SWI1_EGU1 - SWI2_EGU2_IRQn, //!< 22 SWI2_EGU2 - SWI3_EGU3_IRQn, //!< 23 SWI3_EGU3 - SWI4_EGU4_IRQn, //!< 24 SWI4_EGU4 - SWI5_EGU5_IRQn, //!< 25 SWI5_EGU5 - TIMER3_IRQn, //!< 26 TIMER3 - TIMER4_IRQn, //!< 27 TIMER4 - PWM0_IRQn, //!< 28 PWM0 - PDM_IRQn, //!< 29 PDM - MWU_IRQn, //!< 32 MWU - PWM1_IRQn, //!< 33 PWM1 - PWM2_IRQn, //!< 34 PWM2 - SPIM2_SPIS2_SPI2_IRQn, //!< 35 SPIM2_SPIS2_SPI2 - RTC2_IRQn, //!< 36 RTC2 - I2S_IRQn, //!< 37 I2S - FPU_IRQn //!< 38 FPU + POWER_CLOCK_IRQ, //!< 0 POWER_CLOCK + RADIO_IRQ, //!< 1 RADIO + UARTE0_UART0_IRQ, //!< 2 UARTE0_UART0 + SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQ, //!< 3 SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 + SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQ, //!< 4 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 + NFCT_IRQ, //!< 5 NFCT + GPIOTE_IRQ, //!< 6 GPIOTE + SAADC_IRQ, //!< 7 SAADC + TIMER0_IRQ, //!< 8 TIMER0 + TIMER1_IRQ, //!< 9 TIMER1 + TIMER2_IRQ, //!< 10 TIMER2 + RTC0_IRQ, //!< 11 RTC0 + TEMP_IRQ, //!< 12 TEMP + RNG_IRQ, //!< 13 RNG + ECB_IRQ, //!< 14 ECB + CCM_AAR_IRQ, //!< 15 CCM_AAR + WDT_IRQ, //!< 16 WDT + RTC1_IRQ, //!< 17 RTC1 + QDEC_IRQ, //!< 18 QDEC + COMP_LPCOMP_IRQ, //!< 19 COMP_LPCOMP + SWI0_EGU0_IRQ, //!< 20 SWI0_EGU0 + SWI1_EGU1_IRQ, //!< 21 SWI1_EGU1 + SWI2_EGU2_IRQ, //!< 22 SWI2_EGU2 + SWI3_EGU3_IRQ, //!< 23 SWI3_EGU3 + SWI4_EGU4_IRQ, //!< 24 SWI4_EGU4 + SWI5_EGU5_IRQ, //!< 25 SWI5_EGU5 + TIMER3_IRQ, //!< 26 TIMER3 + TIMER4_IRQ, //!< 27 TIMER4 + PWM0_IRQ, //!< 28 PWM0 + PDM_IRQ, //!< 29 PDM + MWU_IRQ, //!< 32 MWU + PWM1_IRQ, //!< 33 PWM1 + PWM2_IRQ, //!< 34 PWM2 + SPIM2_SPIS2_SPI2_IRQ, //!< 35 SPIM2_SPIS2_SPI2 + RTC2_IRQ, //!< 36 RTC2 + I2S_IRQ, //!< 37 I2S + FPU_IRQ //!< 38 FPU }; private: diff --git a/src/platform/nrf52/low_level_interrupt.cc b/src/platform/nrf52/low_level_interrupt.cc index 953a8f2..35807ab 100644 --- a/src/platform/nrf52/low_level_interrupt.cc +++ b/src/platform/nrf52/low_level_interrupt.cc @@ -44,3 +44,13 @@ extern "C" { } using namespace pinetime::platform::nrf52; + +void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) +{ + uint32_t irq_nr = InterruptGuardian::Nrf52IrqN::SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQ; + InterruptHandler *h = InterruptGuardian::instance.nrf52_vector[irq_nr]; + + assert(h != nullptr); + + h->handle(); +} diff --git a/src/platform/nrf52/spi.cc b/src/platform/nrf52/spi.cc index 1e6664a..c6f2f3a 100644 --- a/src/platform/nrf52/spi.cc +++ b/src/platform/nrf52/spi.cc @@ -1,70 +1,130 @@ #include +#include "platform/nrf52/InterruptHandler.h" +#include "platform/nrf52/InterruptGuardian.h" + #include "platform/nrf52/spi.h" extern "C" { #include "nrf52.h" #include "nrf52_bitfields.h" - NRF_SPI_Type *SPI_REGS = reinterpret_cast(NRF_SPI0_BASE); + NRF_GPIO_Type *const GPIO_REGS = reinterpret_cast(NRF_P0_BASE); + NRF_SPIM_Type *SPIM_REGS = reinterpret_cast(NRF_SPIM0_BASE); } using namespace pinetime::platform::nrf52; Spi::Spi(uint32_t instance, uint32_t sck, uint32_t mosi, uint32_t miso, pinetime::interfaces::GpioInterface & cs) - : chip_select(cs) + : InterruptHandler(InterruptGuardian::Nrf52IrqN::SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQ) + , chip_select(cs) + , xfer_active(false) { assert(instance < 3); - if(instance == 0) { - SPI_REGS = reinterpret_cast(NRF_SPI0_BASE); + // sck pin + GPIO_REGS->OUTCLR = 1UL << sck; + GPIO_REGS->PIN_CNF[mosi] = GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos + | GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos + | GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos + | GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos + | GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos; + // mosi pin + GPIO_REGS->OUTCLR = 1UL << mosi; + GPIO_REGS->PIN_CNF[mosi] = GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos + | GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos + | GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos + | GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos + | GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos; + // miso pin + GPIO_REGS->PIN_CNF[miso] = GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos + | GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos + | GPIO_PIN_CNF_PULL_Pulldown << GPIO_PIN_CNF_PULL_Pos + | GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos + | GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos; + // ss already configured by gpio driver + + IRQn_Type irq = SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn; + if(instance == 2) { + SPIM_REGS = reinterpret_cast(NRF_SPIM2_BASE); + irq = SPIM2_SPIS2_SPI2_IRQn; } else if(instance == 1) { - SPI_REGS = reinterpret_cast(NRF_SPI1_BASE); + SPIM_REGS = reinterpret_cast(NRF_SPIM1_BASE); + irq = SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn; } else { - SPI_REGS = reinterpret_cast(NRF_SPI2_BASE); + SPIM_REGS = reinterpret_cast(NRF_SPIM0_BASE); + irq = SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn; } this->chip_select.set(); - SPI_REGS->ENABLE = 0; - SPI_REGS->PSEL.SCK = sck; - SPI_REGS->PSEL.MOSI = mosi; - SPI_REGS->PSEL.MISO = miso; - SPI_REGS->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M8; + SPIM_REGS->ENABLE = 0; + SPIM_REGS->PSEL.SCK = sck; + SPIM_REGS->PSEL.MOSI = mosi; + SPIM_REGS->PSEL.MISO = miso; + SPIM_REGS->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M8; - SPI_REGS->CONFIG = (0x03 << 1); //Sample on trailing edge of clock, shift serial data on leading edge, SCK polarity Active low - SPI_REGS->EVENTS_READY = 0; - SPI_REGS->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos); + SPIM_REGS->CONFIG = (0x03 << 1); //Sample on trailing edge of clock, shift serial data on leading edge, SCK polarity Active low + SPIM_REGS->EVENTS_ENDRX = 0; + SPIM_REGS->EVENTS_ENDTX = 0; + SPIM_REGS->EVENTS_END = 0; + + SPIM_REGS->INTENSET = (1 << 1) // Stopped + | (1 << 6) // End + | (1 << 19); // Started + + SPIM_REGS->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); + + NVIC_SetPriority(irq, 2); + NVIC_EnableIRQ(irq); } + Spi::~Spi() { - SPI_REGS->ENABLE = 0; + SPIM_REGS->ENABLE = 0; } void Spi::send(const uint8_t * buffer, uint32_t len) { this->chip_select.clear(); - for(unsigned int i = 0; i < len; i++) { - this->transfer(buffer[i]); - } + this->xfer_active = true; + + SPIM_REGS->TXD.PTR = reinterpret_cast(buffer); + SPIM_REGS->TXD.MAXCNT = len; + SPIM_REGS->TXD.LIST = 0; + + SPIM_REGS->RXD.PTR = 0; + SPIM_REGS->RXD.MAXCNT = 0; + SPIM_REGS->RXD.LIST = 0; + + SPIM_REGS->EVENTS_END = 0; + + SPIM_REGS->TASKS_START = 1; + + // FIXME: LOW POWER??? + while(this->xfer_active); + this->chip_select.set(); } void Spi::recv(uint8_t * buffer, uint32_t len) { - this->chip_select.clear(); - for(unsigned int i = 0; i < len; i++) { - buffer[i] = this->transfer(buffer[i]); - } - this->chip_select.set(); + // FIXME: not implemented yet } -uint32_t Spi::transfer(uint32_t data) +void Spi::handle() { - volatile uint32_t ret; - SPI_REGS->EVENTS_READY = 0; - SPI_REGS->TXD = data; - while(SPI_REGS->EVENTS_READY == 0) {;} - ret = SPI_REGS->RXD; - return ret; -} \ No newline at end of file + if((SPIM_REGS->INTENSET & (1 << 6)) && (SPIM_REGS->EVENTS_END == 1)) { + SPIM_REGS->EVENTS_END = 0; + this->xfer_active = false; + } + + if((SPIM_REGS->INTENSET & (1 << 19)) && (SPIM_REGS->EVENTS_STARTED == 1)) { + SPIM_REGS->EVENTS_STARTED = 0; + } + + if((SPIM_REGS->INTENSET & (1 << 1)) && (SPIM_REGS->EVENTS_STOPPED == 1)) { + SPIM_REGS->EVENTS_STOPPED = 0; + this->xfer_active = false; + } +} diff --git a/src/platform/nrf52/spi.h b/src/platform/nrf52/spi.h index 13654a5..81797d6 100644 --- a/src/platform/nrf52/spi.h +++ b/src/platform/nrf52/spi.h @@ -4,9 +4,13 @@ #include "gpio_interface.h" #include "spi_interface.h" +#include "platform/nrf52/InterruptHandler.h" + namespace pinetime::platform::nrf52 { -class Spi : public pinetime::interfaces::SpiInterface +class Spi + : public pinetime::platform::nrf52::InterruptHandler + , public pinetime::interfaces::SpiInterface { public: Spi(uint32_t instance, uint32_t sck, uint32_t mosi, uint32_t miso, pinetime::interfaces::GpioInterface & cs); @@ -17,7 +21,10 @@ public: private: uint32_t transfer(uint32_t); + void handle() override; + pinetime::interfaces::GpioInterface & chip_select; + volatile bool xfer_active; }; }