mbed library sources

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Fri Jul 17 09:15:10 2015 +0100
Revision:
592:a274ee790e56
Parent:
579:53297373a894
Synchronized with git revision e7144f83a8d75df80c4877936b6ffe552b0be9e6

Full URL: https://github.com/mbedmicro/mbed/commit/e7144f83a8d75df80c4877936b6ffe552b0be9e6/

More API implementation for SAMR21

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 579:53297373a894 1 #include <gclk.h>
mbed_official 579:53297373a894 2 #include <clock.h>
mbed_official 579:53297373a894 3 #include <system_interrupt.h>
mbed_official 579:53297373a894 4
mbed_official 579:53297373a894 5 /**
mbed_official 579:53297373a894 6 * \brief Determines if the hardware module(s) are currently synchronizing to the bus.
mbed_official 579:53297373a894 7 *
mbed_official 579:53297373a894 8 * Checks to see if the underlying hardware peripheral module(s) are currently
mbed_official 579:53297373a894 9 * synchronizing across multiple clock domains to the hardware bus, This
mbed_official 579:53297373a894 10 * function can be used to delay further operations on a module until such time
mbed_official 579:53297373a894 11 * that it is ready, to prevent blocking delays for synchronization in the
mbed_official 579:53297373a894 12 * user application.
mbed_official 579:53297373a894 13 *
mbed_official 579:53297373a894 14 * \return Synchronization status of the underlying hardware module(s).
mbed_official 579:53297373a894 15 *
mbed_official 579:53297373a894 16 * \retval false if the module has completed synchronization
mbed_official 579:53297373a894 17 * \retval true if the module synchronization is ongoing
mbed_official 579:53297373a894 18 */
mbed_official 579:53297373a894 19 static inline bool system_gclk_is_syncing(void)
mbed_official 579:53297373a894 20 {
mbed_official 579:53297373a894 21 if (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {
mbed_official 579:53297373a894 22 return true;
mbed_official 579:53297373a894 23 }
mbed_official 579:53297373a894 24
mbed_official 579:53297373a894 25 return false;
mbed_official 579:53297373a894 26 }
mbed_official 579:53297373a894 27
mbed_official 579:53297373a894 28 /**
mbed_official 579:53297373a894 29 * \brief Initializes the GCLK driver.
mbed_official 579:53297373a894 30 *
mbed_official 579:53297373a894 31 * Initializes the Generic Clock module, disabling and resetting all active
mbed_official 579:53297373a894 32 * Generic Clock Generators and Channels to their power-on default values.
mbed_official 579:53297373a894 33 */
mbed_official 579:53297373a894 34 void system_gclk_init(void)
mbed_official 579:53297373a894 35 {
mbed_official 579:53297373a894 36 /* Turn on the digital interface clock */
mbed_official 579:53297373a894 37 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBA, PM_APBAMASK_GCLK);
mbed_official 579:53297373a894 38
mbed_official 579:53297373a894 39 /* Software reset the module to ensure it is re-initialized correctly */
mbed_official 579:53297373a894 40 GCLK->CTRL.reg = GCLK_CTRL_SWRST;
mbed_official 579:53297373a894 41 while (GCLK->CTRL.reg & GCLK_CTRL_SWRST) {
mbed_official 579:53297373a894 42 /* Wait for reset to complete */
mbed_official 579:53297373a894 43 }
mbed_official 579:53297373a894 44 }
mbed_official 579:53297373a894 45
mbed_official 579:53297373a894 46 /**
mbed_official 579:53297373a894 47 * \brief Writes a Generic Clock Generator configuration to the hardware module.
mbed_official 579:53297373a894 48 *
mbed_official 579:53297373a894 49 * Writes out a given configuration of a Generic Clock Generator configuration
mbed_official 579:53297373a894 50 * to the hardware module.
mbed_official 579:53297373a894 51 *
mbed_official 579:53297373a894 52 * \note Changing the clock source on the fly (on a running
mbed_official 579:53297373a894 53 * generator) can take additional time if the clock source is configured
mbed_official 579:53297373a894 54 * to only run on-demand (ONDEMAND bit is set) and it is not currently
mbed_official 579:53297373a894 55 * running (no peripheral is requesting the clock source). In this case
mbed_official 579:53297373a894 56 * the GCLK will request the new clock while still keeping a request to
mbed_official 579:53297373a894 57 * the old clock source until the new clock source is ready.
mbed_official 579:53297373a894 58 *
mbed_official 579:53297373a894 59 * \note This function will not start a generator that is not already running;
mbed_official 579:53297373a894 60 * to start the generator, call \ref system_gclk_gen_enable()
mbed_official 579:53297373a894 61 * after configuring a generator.
mbed_official 579:53297373a894 62 *
mbed_official 579:53297373a894 63 * \param[in] generator Generic Clock Generator index to configure
mbed_official 579:53297373a894 64 * \param[in] config Configuration settings for the generator
mbed_official 579:53297373a894 65 */
mbed_official 579:53297373a894 66 void system_gclk_gen_set_config(
mbed_official 579:53297373a894 67 const uint8_t generator,
mbed_official 579:53297373a894 68 struct system_gclk_gen_config *const config)
mbed_official 579:53297373a894 69 {
mbed_official 579:53297373a894 70 /* Sanity check arguments */
mbed_official 579:53297373a894 71 Assert(config);
mbed_official 579:53297373a894 72
mbed_official 579:53297373a894 73 /* Cache new register configurations to minimize sync requirements. */
mbed_official 579:53297373a894 74 uint32_t new_genctrl_config = (generator << GCLK_GENCTRL_ID_Pos);
mbed_official 579:53297373a894 75 uint32_t new_gendiv_config = (generator << GCLK_GENDIV_ID_Pos);
mbed_official 579:53297373a894 76
mbed_official 579:53297373a894 77 /* Select the requested source clock for the generator */
mbed_official 579:53297373a894 78 new_genctrl_config |= config->source_clock << GCLK_GENCTRL_SRC_Pos;
mbed_official 579:53297373a894 79
mbed_official 579:53297373a894 80 /* Configure the clock to be either high or low when disabled */
mbed_official 579:53297373a894 81 if (config->high_when_disabled) {
mbed_official 579:53297373a894 82 new_genctrl_config |= GCLK_GENCTRL_OOV;
mbed_official 579:53297373a894 83 }
mbed_official 579:53297373a894 84
mbed_official 579:53297373a894 85 /* Configure if the clock output to I/O pin should be enabled. */
mbed_official 579:53297373a894 86 if (config->output_enable) {
mbed_official 579:53297373a894 87 new_genctrl_config |= GCLK_GENCTRL_OE;
mbed_official 579:53297373a894 88 }
mbed_official 579:53297373a894 89
mbed_official 579:53297373a894 90 /* Set division factor */
mbed_official 579:53297373a894 91 if (config->division_factor > 1) {
mbed_official 579:53297373a894 92 /* Check if division is a power of two */
mbed_official 579:53297373a894 93 if (((config->division_factor & (config->division_factor - 1)) == 0)) {
mbed_official 579:53297373a894 94 /* Determine the index of the highest bit set to get the
mbed_official 579:53297373a894 95 * division factor that must be loaded into the division
mbed_official 579:53297373a894 96 * register */
mbed_official 579:53297373a894 97
mbed_official 579:53297373a894 98 uint32_t div2_count = 0;
mbed_official 579:53297373a894 99
mbed_official 579:53297373a894 100 uint32_t mask;
mbed_official 579:53297373a894 101 for (mask = (1UL << 1); mask < config->division_factor;
mbed_official 579:53297373a894 102 mask <<= 1) {
mbed_official 579:53297373a894 103 div2_count++;
mbed_official 579:53297373a894 104 }
mbed_official 579:53297373a894 105
mbed_official 579:53297373a894 106 /* Set binary divider power of 2 division factor */
mbed_official 579:53297373a894 107 new_gendiv_config |= div2_count << GCLK_GENDIV_DIV_Pos;
mbed_official 579:53297373a894 108 new_genctrl_config |= GCLK_GENCTRL_DIVSEL;
mbed_official 579:53297373a894 109 } else {
mbed_official 579:53297373a894 110 /* Set integer division factor */
mbed_official 579:53297373a894 111
mbed_official 579:53297373a894 112 new_gendiv_config |=
mbed_official 579:53297373a894 113 (config->division_factor) << GCLK_GENDIV_DIV_Pos;
mbed_official 579:53297373a894 114
mbed_official 579:53297373a894 115 /* Enable non-binary division with increased duty cycle accuracy */
mbed_official 579:53297373a894 116 new_genctrl_config |= GCLK_GENCTRL_IDC;
mbed_official 579:53297373a894 117 }
mbed_official 579:53297373a894 118
mbed_official 579:53297373a894 119 }
mbed_official 579:53297373a894 120
mbed_official 579:53297373a894 121 /* Enable or disable the clock in standby mode */
mbed_official 579:53297373a894 122 if (config->run_in_standby) {
mbed_official 579:53297373a894 123 new_genctrl_config |= GCLK_GENCTRL_RUNSTDBY;
mbed_official 579:53297373a894 124 }
mbed_official 579:53297373a894 125
mbed_official 579:53297373a894 126 while (system_gclk_is_syncing()) {
mbed_official 579:53297373a894 127 /* Wait for synchronization */
mbed_official 579:53297373a894 128 };
mbed_official 579:53297373a894 129
mbed_official 579:53297373a894 130 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 131
mbed_official 579:53297373a894 132 /* Select the correct generator */
mbed_official 579:53297373a894 133 *((uint8_t*)&GCLK->GENDIV.reg) = generator;
mbed_official 579:53297373a894 134
mbed_official 579:53297373a894 135 /* Write the new generator configuration */
mbed_official 579:53297373a894 136 while (system_gclk_is_syncing()) {
mbed_official 579:53297373a894 137 /* Wait for synchronization */
mbed_official 579:53297373a894 138 };
mbed_official 579:53297373a894 139 GCLK->GENDIV.reg = new_gendiv_config;
mbed_official 579:53297373a894 140
mbed_official 579:53297373a894 141 while (system_gclk_is_syncing()) {
mbed_official 579:53297373a894 142 /* Wait for synchronization */
mbed_official 579:53297373a894 143 };
mbed_official 579:53297373a894 144 GCLK->GENCTRL.reg = new_genctrl_config | (GCLK->GENCTRL.reg & GCLK_GENCTRL_GENEN);
mbed_official 579:53297373a894 145
mbed_official 579:53297373a894 146 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 147 }
mbed_official 579:53297373a894 148
mbed_official 579:53297373a894 149 /**
mbed_official 579:53297373a894 150 * \brief Enables a Generic Clock Generator that was previously configured.
mbed_official 579:53297373a894 151 *
mbed_official 579:53297373a894 152 * Starts the clock generation of a Generic Clock Generator that was previously
mbed_official 579:53297373a894 153 * configured via a call to \ref system_gclk_gen_set_config().
mbed_official 579:53297373a894 154 *
mbed_official 579:53297373a894 155 * \param[in] generator Generic Clock Generator index to enable
mbed_official 579:53297373a894 156 */
mbed_official 579:53297373a894 157 void system_gclk_gen_enable(
mbed_official 579:53297373a894 158 const uint8_t generator)
mbed_official 579:53297373a894 159 {
mbed_official 579:53297373a894 160 while (system_gclk_is_syncing()) {
mbed_official 579:53297373a894 161 /* Wait for synchronization */
mbed_official 579:53297373a894 162 };
mbed_official 579:53297373a894 163
mbed_official 579:53297373a894 164 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 165
mbed_official 579:53297373a894 166 /* Select the requested generator */
mbed_official 579:53297373a894 167 *((uint8_t*)&GCLK->GENCTRL.reg) = generator;
mbed_official 579:53297373a894 168 while (system_gclk_is_syncing()) {
mbed_official 579:53297373a894 169 /* Wait for synchronization */
mbed_official 579:53297373a894 170 };
mbed_official 579:53297373a894 171
mbed_official 579:53297373a894 172 /* Enable generator */
mbed_official 579:53297373a894 173 GCLK->GENCTRL.reg |= GCLK_GENCTRL_GENEN;
mbed_official 579:53297373a894 174
mbed_official 579:53297373a894 175 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 176 }
mbed_official 579:53297373a894 177
mbed_official 579:53297373a894 178 /**
mbed_official 579:53297373a894 179 * \brief Disables a Generic Clock Generator that was previously enabled.
mbed_official 579:53297373a894 180 *
mbed_official 579:53297373a894 181 * Stops the clock generation of a Generic Clock Generator that was previously
mbed_official 579:53297373a894 182 * started via a call to \ref system_gclk_gen_enable().
mbed_official 579:53297373a894 183 *
mbed_official 579:53297373a894 184 * \param[in] generator Generic Clock Generator index to disable
mbed_official 579:53297373a894 185 */
mbed_official 579:53297373a894 186 void system_gclk_gen_disable(
mbed_official 579:53297373a894 187 const uint8_t generator)
mbed_official 579:53297373a894 188 {
mbed_official 579:53297373a894 189 while (system_gclk_is_syncing()) {
mbed_official 579:53297373a894 190 /* Wait for synchronization */
mbed_official 579:53297373a894 191 };
mbed_official 579:53297373a894 192
mbed_official 579:53297373a894 193 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 194
mbed_official 579:53297373a894 195 /* Select the requested generator */
mbed_official 579:53297373a894 196 *((uint8_t*)&GCLK->GENCTRL.reg) = generator;
mbed_official 579:53297373a894 197 while (system_gclk_is_syncing()) {
mbed_official 579:53297373a894 198 /* Wait for synchronization */
mbed_official 579:53297373a894 199 };
mbed_official 579:53297373a894 200
mbed_official 579:53297373a894 201 /* Disable generator */
mbed_official 579:53297373a894 202 GCLK->GENCTRL.reg &= ~GCLK_GENCTRL_GENEN;
mbed_official 579:53297373a894 203 while (GCLK->GENCTRL.reg & GCLK_GENCTRL_GENEN) {
mbed_official 579:53297373a894 204 /* Wait for clock to become disabled */
mbed_official 579:53297373a894 205 }
mbed_official 579:53297373a894 206
mbed_official 579:53297373a894 207 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 208 }
mbed_official 579:53297373a894 209
mbed_official 579:53297373a894 210 /**
mbed_official 579:53297373a894 211 * \brief Determins if the specified Generic Clock Generator is enabled.
mbed_official 579:53297373a894 212 *
mbed_official 579:53297373a894 213 * \param[in] generator Generic Clock Generator index to check
mbed_official 579:53297373a894 214 *
mbed_official 579:53297373a894 215 * \return The enabled status.
mbed_official 579:53297373a894 216 * \retval true The Generic Clock Generator is enabled
mbed_official 579:53297373a894 217 * \retval false The Generic Clock Generator is disabled
mbed_official 579:53297373a894 218 */
mbed_official 579:53297373a894 219 bool system_gclk_gen_is_enabled(
mbed_official 579:53297373a894 220 const uint8_t generator)
mbed_official 579:53297373a894 221 {
mbed_official 579:53297373a894 222 bool enabled;
mbed_official 579:53297373a894 223
mbed_official 579:53297373a894 224 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 225
mbed_official 579:53297373a894 226 /* Select the requested generator */
mbed_official 579:53297373a894 227 *((uint8_t*)&GCLK->GENCTRL.reg) = generator;
mbed_official 579:53297373a894 228 /* Obtain the enabled status */
mbed_official 579:53297373a894 229 enabled = (GCLK->GENCTRL.reg & GCLK_GENCTRL_GENEN);
mbed_official 579:53297373a894 230
mbed_official 579:53297373a894 231 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 232
mbed_official 579:53297373a894 233 return enabled;
mbed_official 579:53297373a894 234 }
mbed_official 579:53297373a894 235
mbed_official 579:53297373a894 236 /**
mbed_official 579:53297373a894 237 * \brief Retrieves the clock frequency of a Generic Clock generator.
mbed_official 579:53297373a894 238 *
mbed_official 579:53297373a894 239 * Determines the clock frequency (in Hz) of a specified Generic Clock
mbed_official 579:53297373a894 240 * generator, used as a source to a Generic Clock Channel module.
mbed_official 579:53297373a894 241 *
mbed_official 579:53297373a894 242 * \param[in] generator Generic Clock Generator index
mbed_official 579:53297373a894 243 *
mbed_official 579:53297373a894 244 * \return The frequency of the generic clock generator, in Hz.
mbed_official 579:53297373a894 245 */
mbed_official 579:53297373a894 246 uint32_t system_gclk_gen_get_hz(
mbed_official 579:53297373a894 247 const uint8_t generator)
mbed_official 579:53297373a894 248 {
mbed_official 579:53297373a894 249 while (system_gclk_is_syncing()) {
mbed_official 579:53297373a894 250 /* Wait for synchronization */
mbed_official 579:53297373a894 251 };
mbed_official 579:53297373a894 252
mbed_official 579:53297373a894 253 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 254
mbed_official 579:53297373a894 255 /* Select the appropriate generator */
mbed_official 579:53297373a894 256 *((uint8_t*)&GCLK->GENCTRL.reg) = generator;
mbed_official 579:53297373a894 257 while (system_gclk_is_syncing()) {
mbed_official 579:53297373a894 258 /* Wait for synchronization */
mbed_official 579:53297373a894 259 };
mbed_official 579:53297373a894 260
mbed_official 579:53297373a894 261 /* Get the frequency of the source connected to the GCLK generator */
mbed_official 579:53297373a894 262 uint32_t gen_input_hz = system_clock_source_get_hz(
mbed_official 579:53297373a894 263 (enum system_clock_source)GCLK->GENCTRL.bit.SRC);
mbed_official 579:53297373a894 264
mbed_official 579:53297373a894 265 *((uint8_t*)&GCLK->GENCTRL.reg) = generator;
mbed_official 579:53297373a894 266
mbed_official 579:53297373a894 267 uint8_t divsel = GCLK->GENCTRL.bit.DIVSEL;
mbed_official 579:53297373a894 268
mbed_official 579:53297373a894 269 /* Select the appropriate generator division register */
mbed_official 579:53297373a894 270 *((uint8_t*)&GCLK->GENDIV.reg) = generator;
mbed_official 579:53297373a894 271 while (system_gclk_is_syncing()) {
mbed_official 579:53297373a894 272 /* Wait for synchronization */
mbed_official 579:53297373a894 273 };
mbed_official 579:53297373a894 274
mbed_official 579:53297373a894 275 uint32_t divider = GCLK->GENDIV.bit.DIV;
mbed_official 579:53297373a894 276
mbed_official 579:53297373a894 277 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 278
mbed_official 579:53297373a894 279 /* Check if the generator is using fractional or binary division */
mbed_official 579:53297373a894 280 if (!divsel && divider > 1) {
mbed_official 579:53297373a894 281 gen_input_hz /= divider;
mbed_official 579:53297373a894 282 } else if (divsel) {
mbed_official 579:53297373a894 283 gen_input_hz >>= (divider+1);
mbed_official 579:53297373a894 284 }
mbed_official 579:53297373a894 285
mbed_official 579:53297373a894 286 return gen_input_hz;
mbed_official 579:53297373a894 287 }
mbed_official 579:53297373a894 288
mbed_official 579:53297373a894 289 /**
mbed_official 579:53297373a894 290 * \brief Writes a Generic Clock configuration to the hardware module.
mbed_official 579:53297373a894 291 *
mbed_official 579:53297373a894 292 * Writes out a given configuration of a Generic Clock configuration to the
mbed_official 579:53297373a894 293 * hardware module. If the clock is currently running, it will be stopped.
mbed_official 579:53297373a894 294 *
mbed_official 579:53297373a894 295 * \note Once called the clock will not be running; to start the clock,
mbed_official 579:53297373a894 296 * call \ref system_gclk_chan_enable() after configuring a clock channel.
mbed_official 579:53297373a894 297 *
mbed_official 579:53297373a894 298 * \param[in] channel Generic Clock channel to configure
mbed_official 579:53297373a894 299 * \param[in] config Configuration settings for the clock
mbed_official 579:53297373a894 300 *
mbed_official 579:53297373a894 301 */
mbed_official 579:53297373a894 302 void system_gclk_chan_set_config(
mbed_official 579:53297373a894 303 const uint8_t channel,
mbed_official 579:53297373a894 304 struct system_gclk_chan_config *const config)
mbed_official 579:53297373a894 305 {
mbed_official 579:53297373a894 306 /* Sanity check arguments */
mbed_official 579:53297373a894 307 Assert(config);
mbed_official 579:53297373a894 308
mbed_official 579:53297373a894 309 /* Cache the new config to reduce sync requirements */
mbed_official 579:53297373a894 310 uint32_t new_clkctrl_config = (channel << GCLK_CLKCTRL_ID_Pos);
mbed_official 579:53297373a894 311
mbed_official 579:53297373a894 312 /* Select the desired generic clock generator */
mbed_official 579:53297373a894 313 new_clkctrl_config |= config->source_generator << GCLK_CLKCTRL_GEN_Pos;
mbed_official 579:53297373a894 314
mbed_official 579:53297373a894 315 /* Disable generic clock channel */
mbed_official 579:53297373a894 316 system_gclk_chan_disable(channel);
mbed_official 579:53297373a894 317
mbed_official 579:53297373a894 318 /* Write the new configuration */
mbed_official 579:53297373a894 319 GCLK->CLKCTRL.reg = new_clkctrl_config;
mbed_official 579:53297373a894 320 }
mbed_official 579:53297373a894 321
mbed_official 579:53297373a894 322 /**
mbed_official 579:53297373a894 323 * \brief Enables a Generic Clock that was previously configured.
mbed_official 579:53297373a894 324 *
mbed_official 579:53297373a894 325 * Starts the clock generation of a Generic Clock that was previously
mbed_official 579:53297373a894 326 * configured via a call to \ref system_gclk_chan_set_config().
mbed_official 579:53297373a894 327 *
mbed_official 579:53297373a894 328 * \param[in] channel Generic Clock channel to enable
mbed_official 579:53297373a894 329 */
mbed_official 579:53297373a894 330 void system_gclk_chan_enable(
mbed_official 579:53297373a894 331 const uint8_t channel)
mbed_official 579:53297373a894 332 {
mbed_official 579:53297373a894 333 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 334
mbed_official 579:53297373a894 335 /* Select the requested generator channel */
mbed_official 579:53297373a894 336 *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
mbed_official 579:53297373a894 337
mbed_official 579:53297373a894 338 /* Enable the generic clock */
mbed_official 579:53297373a894 339 GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_CLKEN;
mbed_official 579:53297373a894 340
mbed_official 579:53297373a894 341 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 342 }
mbed_official 579:53297373a894 343
mbed_official 579:53297373a894 344 /**
mbed_official 579:53297373a894 345 * \brief Disables a Generic Clock that was previously enabled.
mbed_official 579:53297373a894 346 *
mbed_official 579:53297373a894 347 * Stops the clock generation of a Generic Clock that was previously started
mbed_official 579:53297373a894 348 * via a call to \ref system_gclk_chan_enable().
mbed_official 579:53297373a894 349 *
mbed_official 579:53297373a894 350 * \param[in] channel Generic Clock channel to disable
mbed_official 579:53297373a894 351 */
mbed_official 579:53297373a894 352 void system_gclk_chan_disable(
mbed_official 579:53297373a894 353 const uint8_t channel)
mbed_official 579:53297373a894 354 {
mbed_official 579:53297373a894 355 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 356
mbed_official 579:53297373a894 357 /* Select the requested generator channel */
mbed_official 579:53297373a894 358 *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
mbed_official 579:53297373a894 359
mbed_official 579:53297373a894 360 /* Sanity check WRTLOCK */
mbed_official 579:53297373a894 361 Assert(!GCLK->CLKCTRL.bit.WRTLOCK);
mbed_official 579:53297373a894 362
mbed_official 579:53297373a894 363 /* Switch to known-working source so that the channel can be disabled */
mbed_official 579:53297373a894 364 uint32_t prev_gen_id = GCLK->CLKCTRL.bit.GEN;
mbed_official 579:53297373a894 365 GCLK->CLKCTRL.bit.GEN = 0;
mbed_official 579:53297373a894 366
mbed_official 579:53297373a894 367 /* Disable the generic clock */
mbed_official 579:53297373a894 368 GCLK->CLKCTRL.reg &= ~GCLK_CLKCTRL_CLKEN;
mbed_official 579:53297373a894 369 while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN) {
mbed_official 579:53297373a894 370 /* Wait for clock to become disabled */
mbed_official 579:53297373a894 371 }
mbed_official 579:53297373a894 372
mbed_official 579:53297373a894 373 /* Restore previous configured clock generator */
mbed_official 579:53297373a894 374 GCLK->CLKCTRL.bit.GEN = prev_gen_id;
mbed_official 579:53297373a894 375
mbed_official 579:53297373a894 376 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 377 }
mbed_official 579:53297373a894 378
mbed_official 579:53297373a894 379 /**
mbed_official 579:53297373a894 380 * \brief Determins if the specified Generic Clock channel is enabled.
mbed_official 579:53297373a894 381 *
mbed_official 579:53297373a894 382 * \param[in] channel Generic Clock Channel index
mbed_official 579:53297373a894 383 *
mbed_official 579:53297373a894 384 * \return The enabled status.
mbed_official 579:53297373a894 385 * \retval true The Generic Clock channel is enabled
mbed_official 579:53297373a894 386 * \retval false The Generic Clock channel is disabled
mbed_official 579:53297373a894 387 */
mbed_official 579:53297373a894 388 bool system_gclk_chan_is_enabled(
mbed_official 579:53297373a894 389 const uint8_t channel)
mbed_official 579:53297373a894 390 {
mbed_official 579:53297373a894 391 bool enabled;
mbed_official 579:53297373a894 392
mbed_official 579:53297373a894 393 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 394
mbed_official 579:53297373a894 395 /* Select the requested generic clock channel */
mbed_official 579:53297373a894 396 *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
mbed_official 579:53297373a894 397 enabled = GCLK->CLKCTRL.bit.CLKEN;
mbed_official 579:53297373a894 398
mbed_official 579:53297373a894 399 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 400
mbed_official 579:53297373a894 401 return enabled;
mbed_official 579:53297373a894 402 }
mbed_official 579:53297373a894 403
mbed_official 579:53297373a894 404 /**
mbed_official 579:53297373a894 405 * \brief Locks a Generic Clock channel from further configuration writes.
mbed_official 579:53297373a894 406 *
mbed_official 579:53297373a894 407 * Locks a generic clock channel from further configuration writes. It is only
mbed_official 579:53297373a894 408 * possible to unlock the channel configuration through a power on reset.
mbed_official 579:53297373a894 409 *
mbed_official 579:53297373a894 410 * \param[in] channel Generic Clock channel to enable
mbed_official 579:53297373a894 411 */
mbed_official 579:53297373a894 412 void system_gclk_chan_lock(
mbed_official 579:53297373a894 413 const uint8_t channel)
mbed_official 579:53297373a894 414 {
mbed_official 579:53297373a894 415 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 416
mbed_official 579:53297373a894 417 /* Select the requested generator channel */
mbed_official 579:53297373a894 418 *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
mbed_official 579:53297373a894 419
mbed_official 579:53297373a894 420 /* Lock the generic clock */
mbed_official 579:53297373a894 421 GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_WRTLOCK;
mbed_official 579:53297373a894 422
mbed_official 579:53297373a894 423 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 424 }
mbed_official 579:53297373a894 425
mbed_official 579:53297373a894 426 /**
mbed_official 579:53297373a894 427 * \brief Determins if the specified Generic Clock channel is locked.
mbed_official 579:53297373a894 428 *
mbed_official 579:53297373a894 429 * \param[in] channel Generic Clock Channel index
mbed_official 579:53297373a894 430 *
mbed_official 579:53297373a894 431 * \return The lock status.
mbed_official 579:53297373a894 432 * \retval true The Generic Clock channel is locked
mbed_official 579:53297373a894 433 * \retval false The Generic Clock channel is not locked
mbed_official 579:53297373a894 434 */
mbed_official 579:53297373a894 435 bool system_gclk_chan_is_locked(
mbed_official 579:53297373a894 436 const uint8_t channel)
mbed_official 579:53297373a894 437 {
mbed_official 579:53297373a894 438 bool locked;
mbed_official 579:53297373a894 439
mbed_official 579:53297373a894 440 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 441
mbed_official 579:53297373a894 442 /* Select the requested generic clock channel */
mbed_official 579:53297373a894 443 *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
mbed_official 579:53297373a894 444 locked = GCLK->CLKCTRL.bit.WRTLOCK;
mbed_official 579:53297373a894 445
mbed_official 579:53297373a894 446 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 447
mbed_official 579:53297373a894 448 return locked;
mbed_official 579:53297373a894 449 }
mbed_official 579:53297373a894 450
mbed_official 579:53297373a894 451 /**
mbed_official 579:53297373a894 452 * \brief Retrieves the clock frequency of a Generic Clock channel.
mbed_official 579:53297373a894 453 *
mbed_official 579:53297373a894 454 * Determines the clock frequency (in Hz) of a specified Generic Clock
mbed_official 579:53297373a894 455 * channel, used as a source to a device peripheral module.
mbed_official 579:53297373a894 456 *
mbed_official 579:53297373a894 457 * \param[in] channel Generic Clock Channel index
mbed_official 579:53297373a894 458 *
mbed_official 579:53297373a894 459 * \return The frequency of the generic clock channel, in Hz.
mbed_official 579:53297373a894 460 */
mbed_official 579:53297373a894 461 uint32_t system_gclk_chan_get_hz(
mbed_official 579:53297373a894 462 const uint8_t channel)
mbed_official 579:53297373a894 463 {
mbed_official 579:53297373a894 464 uint8_t gen_id;
mbed_official 579:53297373a894 465
mbed_official 579:53297373a894 466 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 467
mbed_official 579:53297373a894 468 /* Select the requested generic clock channel */
mbed_official 579:53297373a894 469 *((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
mbed_official 579:53297373a894 470 gen_id = GCLK->CLKCTRL.bit.GEN;
mbed_official 579:53297373a894 471
mbed_official 579:53297373a894 472 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 473
mbed_official 579:53297373a894 474 /* Return the clock speed of the associated GCLK generator */
mbed_official 579:53297373a894 475 return system_gclk_gen_get_hz(gen_id);
mbed_official 579:53297373a894 476 }