[11U68]fix P0_11 to use GPIO

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Wed Jun 03 08:30:08 2015 +0100
Revision:
556:a217bc785985
Parent:
554:edd95c0879f8
Synchronized with git revision dd1ab3a5e660410cfbfd2286c513ef820ed2d22f

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

Silicon Labs - Improvements in RAM footprint of HAL.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 525:c320967f86b9 1 /* mbed Microcontroller Library
mbed_official 525:c320967f86b9 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 525:c320967f86b9 3 *
mbed_official 525:c320967f86b9 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 525:c320967f86b9 5 * you may not use this file except in compliance with the License.
mbed_official 525:c320967f86b9 6 * You may obtain a copy of the License at
mbed_official 525:c320967f86b9 7 *
mbed_official 525:c320967f86b9 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 525:c320967f86b9 9 *
mbed_official 525:c320967f86b9 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 525:c320967f86b9 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 525:c320967f86b9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 525:c320967f86b9 13 * See the License for the specific language governing permissions and
mbed_official 525:c320967f86b9 14 * limitations under the License.
mbed_official 525:c320967f86b9 15 */
mbed_official 525:c320967f86b9 16
mbed_official 525:c320967f86b9 17 #include "device.h"
mbed_official 525:c320967f86b9 18 #include "clocking.h"
mbed_official 525:c320967f86b9 19 #if DEVICE_PWMOUT
mbed_official 525:c320967f86b9 20
mbed_official 525:c320967f86b9 21 #include "mbed_assert.h"
mbed_official 525:c320967f86b9 22 #include "pwmout_api.h"
mbed_official 525:c320967f86b9 23 #include "cmsis.h"
mbed_official 525:c320967f86b9 24 #include "pinmap.h"
mbed_official 525:c320967f86b9 25 #include "PeripheralPins.h"
mbed_official 525:c320967f86b9 26 #include "device_peripherals.h"
mbed_official 544:1af5f1c39e80 27 #include "sleepmodes.h"
mbed_official 525:c320967f86b9 28
mbed_official 525:c320967f86b9 29 #include "em_cmu.h"
mbed_official 525:c320967f86b9 30 #include "em_gpio.h"
mbed_official 525:c320967f86b9 31 #include "em_timer.h"
mbed_official 525:c320967f86b9 32
mbed_official 544:1af5f1c39e80 33 static int pwm_prescaler_div;
mbed_official 525:c320967f86b9 34
mbed_official 548:1abac31e188e 35 uint32_t pwmout_get_channel_route(pwmout_t *obj)
mbed_official 548:1abac31e188e 36 {
mbed_official 548:1abac31e188e 37 MBED_ASSERT(obj->channel != (PWMName) NC);
mbed_official 525:c320967f86b9 38
mbed_official 548:1abac31e188e 39 switch (obj->channel) {
mbed_official 548:1abac31e188e 40 case PWM_CH0:
mbed_official 548:1abac31e188e 41 return TIMER_ROUTE_CC0PEN;
mbed_official 548:1abac31e188e 42 break;
mbed_official 548:1abac31e188e 43 case PWM_CH1:
mbed_official 548:1abac31e188e 44 return TIMER_ROUTE_CC1PEN;
mbed_official 548:1abac31e188e 45 break;
mbed_official 548:1abac31e188e 46 case PWM_CH2:
mbed_official 548:1abac31e188e 47 return TIMER_ROUTE_CC2PEN;
mbed_official 548:1abac31e188e 48 break;
mbed_official 548:1abac31e188e 49 default:
mbed_official 548:1abac31e188e 50 return 0;
mbed_official 548:1abac31e188e 51 }
mbed_official 525:c320967f86b9 52 }
mbed_official 525:c320967f86b9 53
mbed_official 525:c320967f86b9 54 void pwmout_enable_pins(pwmout_t *obj, uint8_t enable)
mbed_official 525:c320967f86b9 55 {
mbed_official 525:c320967f86b9 56 if (enable) {
mbed_official 525:c320967f86b9 57 pin_mode(obj->pin, PushPull);
mbed_official 525:c320967f86b9 58 } else {
mbed_official 525:c320967f86b9 59 // TODO_LP return PinMode to the previous state
mbed_official 525:c320967f86b9 60 pin_mode(obj->pin, Disabled);
mbed_official 525:c320967f86b9 61 }
mbed_official 525:c320967f86b9 62 }
mbed_official 525:c320967f86b9 63
mbed_official 525:c320967f86b9 64 void pwmout_enable(pwmout_t *obj, uint8_t enable)
mbed_official 525:c320967f86b9 65 {
mbed_official 548:1abac31e188e 66 /* Start with default CC (Compare/Capture) channel parameters */
mbed_official 548:1abac31e188e 67 TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
mbed_official 525:c320967f86b9 68 if (enable) {
mbed_official 525:c320967f86b9 69 /* Set mode to PWM */
mbed_official 525:c320967f86b9 70 timerCCInit.mode = timerCCModePWM;
mbed_official 544:1af5f1c39e80 71 }
mbed_official 525:c320967f86b9 72
mbed_official 544:1af5f1c39e80 73 /* Configure CC channel */
mbed_official 544:1af5f1c39e80 74 TIMER_InitCC(PWM_TIMER, obj->channel, &timerCCInit);
mbed_official 525:c320967f86b9 75 }
mbed_official 525:c320967f86b9 76
mbed_official 544:1af5f1c39e80 77 void pwmout_init(pwmout_t *obj, PinName pin)
mbed_official 544:1af5f1c39e80 78 {
mbed_official 548:1abac31e188e 79 obj->channel = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
mbed_official 548:1abac31e188e 80 obj->pin = pin;
mbed_official 548:1abac31e188e 81 MBED_ASSERT(obj->channel != (PWMName) NC);
mbed_official 544:1af5f1c39e80 82
mbed_official 548:1abac31e188e 83 /* Turn on clock */
mbed_official 548:1abac31e188e 84 CMU_ClockEnable(PWM_TIMER_CLOCK, true);
mbed_official 544:1af5f1c39e80 85
mbed_official 548:1abac31e188e 86 /* Turn on timer */
mbed_official 548:1abac31e188e 87 if(!(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING)) {
mbed_official 548:1abac31e188e 88 TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
mbed_official 548:1abac31e188e 89 TIMER_Init(PWM_TIMER, &timerInit);
mbed_official 548:1abac31e188e 90 }
mbed_official 544:1af5f1c39e80 91
mbed_official 544:1af5f1c39e80 92 /* Enable correct channel */
mbed_official 548:1abac31e188e 93 uint32_t routeloc = pwmout_get_channel_route(obj);
mbed_official 548:1abac31e188e 94 if(PWM_TIMER->ROUTE & routeloc) {
mbed_official 548:1abac31e188e 95 //This channel was already in use
mbed_official 548:1abac31e188e 96 //TODO: gracefully handle this case
mbed_official 548:1abac31e188e 97 } else {
mbed_official 548:1abac31e188e 98 //This channel was unused up to now
mbed_official 548:1abac31e188e 99 PWM_TIMER->ROUTE |= routeloc;
mbed_official 548:1abac31e188e 100 blockSleepMode(EM1);
mbed_official 544:1af5f1c39e80 101
mbed_official 548:1abac31e188e 102 //TODO: check if any channel was up already, then don't re-init timer
mbed_official 548:1abac31e188e 103 pwmout_enable(obj, true);
mbed_official 548:1abac31e188e 104 pwmout_enable_pins(obj, true);
mbed_official 548:1abac31e188e 105 }
mbed_official 544:1af5f1c39e80 106
mbed_official 544:1af5f1c39e80 107 /* Route correct channel to location 1 */
mbed_official 544:1af5f1c39e80 108 PWM_TIMER->ROUTE &= ~_TIMER_ROUTE_LOCATION_MASK;
mbed_official 544:1af5f1c39e80 109 PWM_TIMER->ROUTE |= PWM_ROUTE;
mbed_official 544:1af5f1c39e80 110
mbed_official 544:1af5f1c39e80 111 /* Set default 20ms frequency and 0ms pulse width */
mbed_official 544:1af5f1c39e80 112 pwmout_period(obj, 0.02);
mbed_official 544:1af5f1c39e80 113 }
mbed_official 544:1af5f1c39e80 114
mbed_official 548:1abac31e188e 115 void pwmout_free(pwmout_t *obj)
mbed_official 548:1abac31e188e 116 {
mbed_official 548:1abac31e188e 117 uint32_t routeloc = pwmout_get_channel_route(obj);
mbed_official 548:1abac31e188e 118 if(PWM_TIMER->ROUTE & routeloc) {
mbed_official 548:1abac31e188e 119 //This channel was in use, so disable
mbed_official 548:1abac31e188e 120 PWM_TIMER->ROUTE &= ~routeloc;
mbed_official 548:1abac31e188e 121 pwmout_enable_pins(obj, false);
mbed_official 548:1abac31e188e 122 unblockSleepMode(EM1);
mbed_official 544:1af5f1c39e80 123
mbed_official 548:1abac31e188e 124 //TODO: check if all channels are down, then switch off timer
mbed_official 548:1abac31e188e 125 } else {
mbed_official 548:1abac31e188e 126 //This channel was disabled already
mbed_official 548:1abac31e188e 127 }
mbed_official 544:1af5f1c39e80 128 }
mbed_official 525:c320967f86b9 129
mbed_official 525:c320967f86b9 130 void pwmout_write(pwmout_t *obj, float value)
mbed_official 525:c320967f86b9 131 {
mbed_official 525:c320967f86b9 132 if (value < 0.0f) {
mbed_official 525:c320967f86b9 133 value = 0;
mbed_official 525:c320967f86b9 134 } else if (value > 1.0f) {
mbed_official 525:c320967f86b9 135 value = 1;
mbed_official 525:c320967f86b9 136 }
mbed_official 525:c320967f86b9 137
mbed_official 556:a217bc785985 138 float pulse_period_in_s = obj->period_cycles / ((float) (REFERENCE_FREQUENCY >> pwm_prescaler_div));
mbed_official 525:c320967f86b9 139 pwmout_pulsewidth(obj, value * pulse_period_in_s);
mbed_official 525:c320967f86b9 140 }
mbed_official 525:c320967f86b9 141
mbed_official 525:c320967f86b9 142 float pwmout_read(pwmout_t *obj)
mbed_official 525:c320967f86b9 143 {
mbed_official 525:c320967f86b9 144 return obj->width_cycles / (float) obj->period_cycles;
mbed_official 525:c320967f86b9 145 }
mbed_official 525:c320967f86b9 146
mbed_official 525:c320967f86b9 147 // Set the PWM period, keeping the absolute pulse width the same.
mbed_official 525:c320967f86b9 148 void pwmout_period(pwmout_t *obj, float seconds)
mbed_official 525:c320967f86b9 149 {
mbed_official 525:c320967f86b9 150 // Find the lowest prescaler divider possible.
mbed_official 525:c320967f86b9 151 // This gives us max resolution for a given period
mbed_official 525:c320967f86b9 152
mbed_official 525:c320967f86b9 153 //The value of the top register if prescaler is set to 0
mbed_official 556:a217bc785985 154 int cycles = REFERENCE_FREQUENCY * seconds;
mbed_official 544:1af5f1c39e80 155 pwm_prescaler_div = 0;
mbed_official 525:c320967f86b9 156
mbed_official 525:c320967f86b9 157 //The top register is only 16 bits, so we keep dividing till we are below 0xFFFF
mbed_official 525:c320967f86b9 158 while (cycles > 0xFFFF) {
mbed_official 525:c320967f86b9 159 cycles /= 2;
mbed_official 544:1af5f1c39e80 160 pwm_prescaler_div++;
mbed_official 525:c320967f86b9 161
mbed_official 544:1af5f1c39e80 162 //Max pwm_prescaler_div supported is 10
mbed_official 544:1af5f1c39e80 163 if (pwm_prescaler_div > 10) {
mbed_official 544:1af5f1c39e80 164 pwm_prescaler_div = 10;
mbed_official 525:c320967f86b9 165 cycles = 0xFFFF; //Set it to max possible value;
mbed_official 525:c320967f86b9 166 break;
mbed_official 525:c320967f86b9 167 }
mbed_official 525:c320967f86b9 168 }
mbed_official 525:c320967f86b9 169
mbed_official 525:c320967f86b9 170 obj->period_cycles = cycles;
mbed_official 525:c320967f86b9 171
mbed_official 525:c320967f86b9 172 //Set prescaler
mbed_official 544:1af5f1c39e80 173 PWM_TIMER->CTRL = (PWM_TIMER->CTRL & ~_TIMER_CTRL_PRESC_MASK) | (pwm_prescaler_div << _TIMER_CTRL_PRESC_SHIFT);
mbed_official 525:c320967f86b9 174
mbed_official 525:c320967f86b9 175 /* Set Top Value, which controls the PWM period */
mbed_official 525:c320967f86b9 176 TIMER_TopSet(PWM_TIMER, obj->period_cycles);
mbed_official 525:c320967f86b9 177 }
mbed_official 525:c320967f86b9 178
mbed_official 525:c320967f86b9 179 void pwmout_period_ms(pwmout_t *obj, int ms)
mbed_official 525:c320967f86b9 180 {
mbed_official 525:c320967f86b9 181 pwmout_period(obj, ms / 1000.0f);
mbed_official 525:c320967f86b9 182 }
mbed_official 525:c320967f86b9 183
mbed_official 525:c320967f86b9 184 void pwmout_period_us(pwmout_t *obj, int us)
mbed_official 525:c320967f86b9 185 {
mbed_official 556:a217bc785985 186 pwmout_period(obj, us / 1000000.0f);
mbed_official 525:c320967f86b9 187 }
mbed_official 525:c320967f86b9 188
mbed_official 525:c320967f86b9 189 void pwmout_pulsewidth(pwmout_t *obj, float seconds)
mbed_official 525:c320967f86b9 190 {
mbed_official 556:a217bc785985 191 obj->width_cycles = (uint32_t) (((float) (REFERENCE_FREQUENCY >> pwm_prescaler_div)) * seconds);
mbed_official 525:c320967f86b9 192 TIMER_CompareBufSet(PWM_TIMER, obj->channel, obj->width_cycles);
mbed_official 525:c320967f86b9 193 }
mbed_official 525:c320967f86b9 194
mbed_official 525:c320967f86b9 195 void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
mbed_official 525:c320967f86b9 196 {
mbed_official 556:a217bc785985 197 obj->width_cycles = (uint32_t) ((REFERENCE_FREQUENCY >> pwm_prescaler_div) * ms) / 1000;
mbed_official 556:a217bc785985 198 TIMER_CompareBufSet(PWM_TIMER, obj->channel, obj->width_cycles);
mbed_official 525:c320967f86b9 199 }
mbed_official 525:c320967f86b9 200
mbed_official 525:c320967f86b9 201 void pwmout_pulsewidth_us(pwmout_t *obj, int us)
mbed_official 525:c320967f86b9 202 {
mbed_official 556:a217bc785985 203 obj->width_cycles = (uint32_t) ((REFERENCE_FREQUENCY >> pwm_prescaler_div) * us) / 1000000;
mbed_official 556:a217bc785985 204 TIMER_CompareBufSet(PWM_TIMER, obj->channel, obj->width_cycles);
mbed_official 525:c320967f86b9 205 }
mbed_official 525:c320967f86b9 206
mbed_official 525:c320967f86b9 207 #endif