Add gpio event driver
This commit is contained in:
		
							
								
								
									
										77
									
								
								src/platform/nrf52/gpiote.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/platform/nrf52/gpiote.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
#include "platform/nrf52/InterruptHandler.h"
 | 
			
		||||
#include "platform/nrf52/InterruptGuardian.h"
 | 
			
		||||
 | 
			
		||||
#include "platform/nrf52/gpiote.h"
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
    #include "nrf52.h"
 | 
			
		||||
    #include "nrf52_bitfields.h"
 | 
			
		||||
 | 
			
		||||
    NRF_GPIOTE_Type *const GPIOTE_REGS = reinterpret_cast<NRF_GPIOTE_Type *>(NRF_GPIOTE_BASE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
using namespace pinetime::platform::nrf52;
 | 
			
		||||
 | 
			
		||||
Gpiote::Gpiote()
 | 
			
		||||
    : InterruptHandler(InterruptGuardian::Nrf52IrqN::GPIOTE_IRQ)
 | 
			
		||||
    , num_registered(0)
 | 
			
		||||
{
 | 
			
		||||
    for(auto it = this->gpiote_channels.begin(); it != this->gpiote_channels.end(); ++it) {
 | 
			
		||||
        *it = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Gpiote::enable()
 | 
			
		||||
{
 | 
			
		||||
    NVIC_SetPriority(GPIOTE_IRQn, 7);
 | 
			
		||||
    NVIC_EnableIRQ(GPIOTE_IRQn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Gpiote::disable()
 | 
			
		||||
{
 | 
			
		||||
    NVIC_DisableIRQ(GPIOTE_IRQn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Gpiote::register_handler(pinetime::interfaces::GpioInterface *gpio)
 | 
			
		||||
{
 | 
			
		||||
    if(num_registered == GPIOTE_CHANNELS) {
 | 
			
		||||
        //FIXME: Error notification
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(num_registered == 0) {
 | 
			
		||||
        this->enable();
 | 
			
		||||
    } else {
 | 
			
		||||
        //check if gpio already registered
 | 
			
		||||
        for(auto it = this->gpiote_channels.begin(); it != this->gpiote_channels.end(); ++it) {
 | 
			
		||||
            if(*it == gpio) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    uint32_t i = 0;
 | 
			
		||||
    for(auto it = this->gpiote_channels.begin(); it != this->gpiote_channels.end(); ++it) {
 | 
			
		||||
        if(*it == nullptr) {
 | 
			
		||||
            *it = gpio;
 | 
			
		||||
            GPIOTE_REGS->INTENSET = GPIOTE_INTENSET_IN0_Msk;
 | 
			
		||||
            GPIOTE_REGS->CONFIG[i] = (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos)
 | 
			
		||||
                                   | ((gpio->pin_number()) << GPIOTE_CONFIG_PSEL_Pos)
 | 
			
		||||
                                   | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
 | 
			
		||||
        }
 | 
			
		||||
        i++;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Gpiote::handle()
 | 
			
		||||
{
 | 
			
		||||
    for(uint32_t i = 0; i < GPIOTE_CHANNELS; ++i) {
 | 
			
		||||
        if(GPIOTE_REGS->EVENTS_IN[i] != 0) {
 | 
			
		||||
            GPIOTE_REGS->EVENTS_IN[i] = 0;
 | 
			
		||||
            pinetime::interfaces::GpioInterface *h = this->gpiote_channels[i];
 | 
			
		||||
            assert(h != nullptr);
 | 
			
		||||
            h->handle();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								src/platform/nrf52/gpiote.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/platform/nrf52/gpiote.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
#ifndef __PLATFORM_NRF52_GPIOTE_H__
 | 
			
		||||
#define __PLATFORM_NRF52_GPIOTE_H__
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
 | 
			
		||||
#include "gpio_interface.h"
 | 
			
		||||
#include "platform/nrf52/InterruptHandler.h"
 | 
			
		||||
 | 
			
		||||
namespace pinetime::platform::nrf52
 | 
			
		||||
{
 | 
			
		||||
class Gpiote;
 | 
			
		||||
}
 | 
			
		||||
extern pinetime::platform::nrf52::Gpiote gpiote;
 | 
			
		||||
 | 
			
		||||
namespace pinetime::platform::nrf52
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
class Gpiote
 | 
			
		||||
    : public pinetime::platform::nrf52::InterruptHandler
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    Gpiote();
 | 
			
		||||
 | 
			
		||||
    static inline Gpiote & instance() { return gpiote; }
 | 
			
		||||
 | 
			
		||||
    void enable() override;
 | 
			
		||||
    void disable() override;
 | 
			
		||||
 | 
			
		||||
    void register_handler(pinetime::interfaces::GpioInterface *);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void handle() override;
 | 
			
		||||
 | 
			
		||||
    enum {
 | 
			
		||||
        GPIOTE_CHANNELS = 8,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::array<pinetime::interfaces::GpioInterface *, GPIOTE_CHANNELS> gpiote_channels;
 | 
			
		||||
    uint32_t num_registered;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -54,3 +54,13 @@ void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void)
 | 
			
		||||
 | 
			
		||||
    h->handle();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GPIOTE_IRQHandler(void)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t irq_nr = InterruptGuardian::Nrf52IrqN::GPIOTE_IRQ;
 | 
			
		||||
    InterruptHandler *h = InterruptGuardian::instance.nrf52_vector[irq_nr];
 | 
			
		||||
 | 
			
		||||
    assert(h != nullptr);
 | 
			
		||||
 | 
			
		||||
    h->handle();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user