Published
Dependencies: BLE_API TLC5955 mbed nRF51822
Fork of BLE_LoopbackUART by
gsCLockGenerator.cpp
- Committer:
- roysandberg
- Date:
- 2018-06-09
- Revision:
- 14:73923b07ae4a
File content as of revision 14:73923b07ae4a:
// https://devzone.nordicsemi.com/question/44628/maximum-clock-possible-on-gpio-pin-nrf51/ // Mbed doesn't support high speed clock output, so had to hack this using direct calls to the Nordic API #include "mbed.h" // Not to be confused with the output pin #define GPIOTE_CHANNEL_NUMBER 0 /** * @enum nrf_gpiote_polarity_t * @brief Polarity for GPIOTE channel enumerator. */ typedef enum { NRF_GPIOTE_POLARITY_LOTOHI = GPIOTE_CONFIG_POLARITY_LoToHi, ///< Low to high NRF_GPIOTE_POLARITY_HITOLO = GPIOTE_CONFIG_POLARITY_HiToLo, ///< High to low NRF_GPIOTE_POLARITY_TOGGLE = GPIOTE_CONFIG_POLARITY_Toggle ///< Toggle } nrf_gpiote_polarity_t; /** * @enum nrf_gpiote_outinit_t * @brief Initial output value for GPIOTE channel enumerator. */ typedef enum { NRF_GPIOTE_INITIAL_VALUE_LOW = GPIOTE_CONFIG_OUTINIT_Low, ///< Low to high NRF_GPIOTE_INITIAL_VALUE_HIGH = GPIOTE_CONFIG_OUTINIT_High ///< High to low } nrf_gpiote_outinit_t; static void timer2_init() { // Start 16 MHz crystal oscillator. NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; NRF_CLOCK->TASKS_HFCLKSTART = 1; // Wait for the external oscillator to start up. while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) { // Do nothing. } NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // Set the timer in Timer Mode. NRF_TIMER2->PRESCALER = 0; NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; // 16 bit mode. NRF_TIMER2->TASKS_CLEAR = 1; NRF_TIMER2->CC[0] = 1; NRF_TIMER2->EVENTS_COMPARE[0] = 0; NRF_TIMER2->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos); } static void ppi_init(void) { // Configure PPI channel 0 to toggle GPIO_OUTPUT_PIN on every TIMER2 COMPARE[0] match (200 ms) NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[0]; NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[GPIOTE_CHANNEL_NUMBER]; // Enable PPI channel 0 NRF_PPI->CHEN = (PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos); } /** * @brief Config GPIOTE channel as output, setting the properly desired output level. * * * @param channel_number specifies the GPIOTE channel [0:3] to configure as an output channel. * @param pin_number specifies the pin number [0:30] to use in the GPIOTE channel. * @param polarity specifies the desired polarity in the output GPIOTE channel. * @param initial_value specifies the initial value of the GPIOTE channel input after the channel configuration. */ static __INLINE void nrf_gpiote_task_config(uint32_t channel_number, uint32_t pin_number, nrf_gpiote_polarity_t polarity, nrf_gpiote_outinit_t initial_value) { /* Check if the output desired is high or low */ if (initial_value == NRF_GPIOTE_INITIAL_VALUE_LOW) { /* Configure channel to Pin31, not connected to the pin, and configure as a tasks that will set it to proper level */ NRF_GPIOTE->CONFIG[channel_number] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | (31UL << GPIOTE_CONFIG_PSEL_Pos) | (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos); } else { /* Configure channel to Pin31, not connected to the pin, and configure as a tasks that will set it to proper level */ NRF_GPIOTE->CONFIG[channel_number] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | (31UL << GPIOTE_CONFIG_PSEL_Pos) | (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos); } /* Three NOPs are required to make sure configuration is written before setting tasks or getting events */ __NOP(); __NOP(); __NOP(); /* Launch the task to take the GPIOTE channel output to the desired level */ NRF_GPIOTE->TASKS_OUT[channel_number] = 1; /* Finally configure the channel as the caller expects. If OUTINIT works, the channel is configured properly. If it does not, the channel output inheritance sets the proper level. */ NRF_GPIOTE->CONFIG[channel_number] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | ((uint32_t)pin_number << GPIOTE_CONFIG_PSEL_Pos) | ((uint32_t)polarity << GPIOTE_CONFIG_POLARITY_Pos) | ((uint32_t)initial_value << GPIOTE_CONFIG_OUTINIT_Pos); /* Three NOPs are required to make sure configuration is written before setting tasks or getting events */ __NOP(); __NOP(); __NOP(); } void init_clock(PinName clkPin) { // configure TIMER2 timer2_init(); // configure PPI ppi_init(); nrf_gpiote_task_config(GPIOTE_CHANNEL_NUMBER, clkPin, \ NRF_GPIOTE_POLARITY_TOGGLE , NRF_GPIOTE_INITIAL_VALUE_LOW); NRF_TIMER2->TASKS_START = 1; // Start event generation. }