Published

Dependencies:   BLE_API TLC5955 mbed nRF51822

Fork of BLE_LoopbackUART by Bluetooth Low Energy

Committer:
roysandberg
Date:
Sat Jun 09 23:23:06 2018 +0000
Revision:
14:73923b07ae4a
Published

Who changed what in which revision?

UserRevisionLine numberNew contents of line
roysandberg 14:73923b07ae4a 1 // https://devzone.nordicsemi.com/question/44628/maximum-clock-possible-on-gpio-pin-nrf51/
roysandberg 14:73923b07ae4a 2
roysandberg 14:73923b07ae4a 3 // Mbed doesn't support high speed clock output, so had to hack this using direct calls to the Nordic API
roysandberg 14:73923b07ae4a 4
roysandberg 14:73923b07ae4a 5 #include "mbed.h"
roysandberg 14:73923b07ae4a 6
roysandberg 14:73923b07ae4a 7 // Not to be confused with the output pin
roysandberg 14:73923b07ae4a 8 #define GPIOTE_CHANNEL_NUMBER 0
roysandberg 14:73923b07ae4a 9
roysandberg 14:73923b07ae4a 10 /**
roysandberg 14:73923b07ae4a 11 * @enum nrf_gpiote_polarity_t
roysandberg 14:73923b07ae4a 12 * @brief Polarity for GPIOTE channel enumerator.
roysandberg 14:73923b07ae4a 13 */
roysandberg 14:73923b07ae4a 14 typedef enum
roysandberg 14:73923b07ae4a 15 {
roysandberg 14:73923b07ae4a 16 NRF_GPIOTE_POLARITY_LOTOHI = GPIOTE_CONFIG_POLARITY_LoToHi, ///< Low to high
roysandberg 14:73923b07ae4a 17 NRF_GPIOTE_POLARITY_HITOLO = GPIOTE_CONFIG_POLARITY_HiToLo, ///< High to low
roysandberg 14:73923b07ae4a 18 NRF_GPIOTE_POLARITY_TOGGLE = GPIOTE_CONFIG_POLARITY_Toggle ///< Toggle
roysandberg 14:73923b07ae4a 19 } nrf_gpiote_polarity_t;
roysandberg 14:73923b07ae4a 20
roysandberg 14:73923b07ae4a 21
roysandberg 14:73923b07ae4a 22 /**
roysandberg 14:73923b07ae4a 23 * @enum nrf_gpiote_outinit_t
roysandberg 14:73923b07ae4a 24 * @brief Initial output value for GPIOTE channel enumerator.
roysandberg 14:73923b07ae4a 25 */
roysandberg 14:73923b07ae4a 26 typedef enum
roysandberg 14:73923b07ae4a 27 {
roysandberg 14:73923b07ae4a 28 NRF_GPIOTE_INITIAL_VALUE_LOW = GPIOTE_CONFIG_OUTINIT_Low, ///< Low to high
roysandberg 14:73923b07ae4a 29 NRF_GPIOTE_INITIAL_VALUE_HIGH = GPIOTE_CONFIG_OUTINIT_High ///< High to low
roysandberg 14:73923b07ae4a 30 } nrf_gpiote_outinit_t;
roysandberg 14:73923b07ae4a 31
roysandberg 14:73923b07ae4a 32
roysandberg 14:73923b07ae4a 33
roysandberg 14:73923b07ae4a 34 static void timer2_init()
roysandberg 14:73923b07ae4a 35 {
roysandberg 14:73923b07ae4a 36 // Start 16 MHz crystal oscillator.
roysandberg 14:73923b07ae4a 37 NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
roysandberg 14:73923b07ae4a 38 NRF_CLOCK->TASKS_HFCLKSTART = 1;
roysandberg 14:73923b07ae4a 39
roysandberg 14:73923b07ae4a 40 // Wait for the external oscillator to start up.
roysandberg 14:73923b07ae4a 41 while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
roysandberg 14:73923b07ae4a 42 {
roysandberg 14:73923b07ae4a 43 // Do nothing.
roysandberg 14:73923b07ae4a 44 }
roysandberg 14:73923b07ae4a 45 NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // Set the timer in Timer Mode.
roysandberg 14:73923b07ae4a 46 NRF_TIMER2->PRESCALER = 0;
roysandberg 14:73923b07ae4a 47 NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; // 16 bit mode.
roysandberg 14:73923b07ae4a 48 NRF_TIMER2->TASKS_CLEAR = 1;
roysandberg 14:73923b07ae4a 49 NRF_TIMER2->CC[0] = 1;
roysandberg 14:73923b07ae4a 50 NRF_TIMER2->EVENTS_COMPARE[0] = 0;
roysandberg 14:73923b07ae4a 51 NRF_TIMER2->SHORTS =
roysandberg 14:73923b07ae4a 52 (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
roysandberg 14:73923b07ae4a 53 }
roysandberg 14:73923b07ae4a 54
roysandberg 14:73923b07ae4a 55 static void ppi_init(void)
roysandberg 14:73923b07ae4a 56 {
roysandberg 14:73923b07ae4a 57 // Configure PPI channel 0 to toggle GPIO_OUTPUT_PIN on every TIMER2 COMPARE[0] match (200 ms)
roysandberg 14:73923b07ae4a 58 NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[0];
roysandberg 14:73923b07ae4a 59 NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[GPIOTE_CHANNEL_NUMBER];
roysandberg 14:73923b07ae4a 60
roysandberg 14:73923b07ae4a 61 // Enable PPI channel 0
roysandberg 14:73923b07ae4a 62 NRF_PPI->CHEN = (PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos);
roysandberg 14:73923b07ae4a 63 }
roysandberg 14:73923b07ae4a 64
roysandberg 14:73923b07ae4a 65
roysandberg 14:73923b07ae4a 66 /**
roysandberg 14:73923b07ae4a 67 * @brief Config GPIOTE channel as output, setting the properly desired output level.
roysandberg 14:73923b07ae4a 68 *
roysandberg 14:73923b07ae4a 69 *
roysandberg 14:73923b07ae4a 70 * @param channel_number specifies the GPIOTE channel [0:3] to configure as an output channel.
roysandberg 14:73923b07ae4a 71 * @param pin_number specifies the pin number [0:30] to use in the GPIOTE channel.
roysandberg 14:73923b07ae4a 72 * @param polarity specifies the desired polarity in the output GPIOTE channel.
roysandberg 14:73923b07ae4a 73 * @param initial_value specifies the initial value of the GPIOTE channel input after the channel configuration.
roysandberg 14:73923b07ae4a 74 */
roysandberg 14:73923b07ae4a 75 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)
roysandberg 14:73923b07ae4a 76 {
roysandberg 14:73923b07ae4a 77 /* Check if the output desired is high or low */
roysandberg 14:73923b07ae4a 78 if (initial_value == NRF_GPIOTE_INITIAL_VALUE_LOW)
roysandberg 14:73923b07ae4a 79 {
roysandberg 14:73923b07ae4a 80 /* Configure channel to Pin31, not connected to the pin, and configure as a tasks that will set it to proper level */
roysandberg 14:73923b07ae4a 81 NRF_GPIOTE->CONFIG[channel_number] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
roysandberg 14:73923b07ae4a 82 (31UL << GPIOTE_CONFIG_PSEL_Pos) |
roysandberg 14:73923b07ae4a 83 (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
roysandberg 14:73923b07ae4a 84 }
roysandberg 14:73923b07ae4a 85 else
roysandberg 14:73923b07ae4a 86 {
roysandberg 14:73923b07ae4a 87 /* Configure channel to Pin31, not connected to the pin, and configure as a tasks that will set it to proper level */
roysandberg 14:73923b07ae4a 88 NRF_GPIOTE->CONFIG[channel_number] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
roysandberg 14:73923b07ae4a 89 (31UL << GPIOTE_CONFIG_PSEL_Pos) |
roysandberg 14:73923b07ae4a 90 (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos);
roysandberg 14:73923b07ae4a 91 }
roysandberg 14:73923b07ae4a 92
roysandberg 14:73923b07ae4a 93 /* Three NOPs are required to make sure configuration is written before setting tasks or getting events */
roysandberg 14:73923b07ae4a 94 __NOP();
roysandberg 14:73923b07ae4a 95 __NOP();
roysandberg 14:73923b07ae4a 96 __NOP();
roysandberg 14:73923b07ae4a 97
roysandberg 14:73923b07ae4a 98 /* Launch the task to take the GPIOTE channel output to the desired level */
roysandberg 14:73923b07ae4a 99 NRF_GPIOTE->TASKS_OUT[channel_number] = 1;
roysandberg 14:73923b07ae4a 100
roysandberg 14:73923b07ae4a 101 /* Finally configure the channel as the caller expects. If OUTINIT works, the channel is configured properly.
roysandberg 14:73923b07ae4a 102 If it does not, the channel output inheritance sets the proper level. */
roysandberg 14:73923b07ae4a 103 NRF_GPIOTE->CONFIG[channel_number] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
roysandberg 14:73923b07ae4a 104 ((uint32_t)pin_number << GPIOTE_CONFIG_PSEL_Pos) |
roysandberg 14:73923b07ae4a 105 ((uint32_t)polarity << GPIOTE_CONFIG_POLARITY_Pos) |
roysandberg 14:73923b07ae4a 106 ((uint32_t)initial_value << GPIOTE_CONFIG_OUTINIT_Pos);
roysandberg 14:73923b07ae4a 107
roysandberg 14:73923b07ae4a 108 /* Three NOPs are required to make sure configuration is written before setting tasks or getting events */
roysandberg 14:73923b07ae4a 109 __NOP();
roysandberg 14:73923b07ae4a 110 __NOP();
roysandberg 14:73923b07ae4a 111 __NOP();
roysandberg 14:73923b07ae4a 112 }
roysandberg 14:73923b07ae4a 113
roysandberg 14:73923b07ae4a 114 void init_clock(PinName clkPin) {
roysandberg 14:73923b07ae4a 115
roysandberg 14:73923b07ae4a 116 // configure TIMER2
roysandberg 14:73923b07ae4a 117 timer2_init();
roysandberg 14:73923b07ae4a 118
roysandberg 14:73923b07ae4a 119 // configure PPI
roysandberg 14:73923b07ae4a 120 ppi_init();
roysandberg 14:73923b07ae4a 121
roysandberg 14:73923b07ae4a 122 nrf_gpiote_task_config(GPIOTE_CHANNEL_NUMBER, clkPin, \
roysandberg 14:73923b07ae4a 123 NRF_GPIOTE_POLARITY_TOGGLE , NRF_GPIOTE_INITIAL_VALUE_LOW);
roysandberg 14:73923b07ae4a 124
roysandberg 14:73923b07ae4a 125 NRF_TIMER2->TASKS_START = 1; // Start event generation.
roysandberg 14:73923b07ae4a 126 }