mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 189:f392fc9709a3 1 /* mbed Microcontroller Library
AnnaBridge 189:f392fc9709a3 2 * Copyright (c) 2018 GigaDevice Semiconductor Inc.
AnnaBridge 189:f392fc9709a3 3 *
AnnaBridge 189:f392fc9709a3 4 * SPDX-License-Identifier: Apache-2.0
AnnaBridge 189:f392fc9709a3 5 *
AnnaBridge 189:f392fc9709a3 6 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 189:f392fc9709a3 7 * you may not use this file except in compliance with the License.
AnnaBridge 189:f392fc9709a3 8 * You may obtain a copy of the License at
AnnaBridge 189:f392fc9709a3 9 *
AnnaBridge 189:f392fc9709a3 10 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 189:f392fc9709a3 11 *
AnnaBridge 189:f392fc9709a3 12 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 189:f392fc9709a3 13 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 189:f392fc9709a3 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 189:f392fc9709a3 15 * See the License for the specific language governing permissions and
AnnaBridge 189:f392fc9709a3 16 * limitations under the License.
AnnaBridge 189:f392fc9709a3 17 */
AnnaBridge 189:f392fc9709a3 18 #include "pwmout_api.h"
AnnaBridge 189:f392fc9709a3 19 #include "cmsis.h"
AnnaBridge 189:f392fc9709a3 20 #include "pinmap.h"
AnnaBridge 189:f392fc9709a3 21 #include "mbed_error.h"
AnnaBridge 189:f392fc9709a3 22 #include "PeripheralPins.h"
AnnaBridge 189:f392fc9709a3 23
AnnaBridge 189:f392fc9709a3 24 #define DEV_PWMOUT_APB_MASK 0x00010000U
AnnaBridge 189:f392fc9709a3 25 #define DEV_PWMOUT_APB1 0U
AnnaBridge 189:f392fc9709a3 26 #define DEV_PWMOUT_APB2 1U
AnnaBridge 189:f392fc9709a3 27
AnnaBridge 189:f392fc9709a3 28 static uint32_t timer_get_clock(uint32_t timer_periph);
AnnaBridge 189:f392fc9709a3 29
AnnaBridge 189:f392fc9709a3 30 static void dev_pwmout_init(pwmout_t *obj)
AnnaBridge 189:f392fc9709a3 31 {
AnnaBridge 189:f392fc9709a3 32 timer_oc_parameter_struct timer_ocintpara;
AnnaBridge 189:f392fc9709a3 33 timer_parameter_struct timer_initpara;
AnnaBridge 189:f392fc9709a3 34
AnnaBridge 189:f392fc9709a3 35 MBED_ASSERT(obj);
AnnaBridge 189:f392fc9709a3 36 uint32_t periph = obj->pwm;
AnnaBridge 189:f392fc9709a3 37
AnnaBridge 189:f392fc9709a3 38 switch (periph) {
AnnaBridge 189:f392fc9709a3 39 case TIMER0:
AnnaBridge 189:f392fc9709a3 40 rcu_periph_clock_enable(RCU_TIMER0);
AnnaBridge 189:f392fc9709a3 41 break;
AnnaBridge 189:f392fc9709a3 42
AnnaBridge 189:f392fc9709a3 43 case TIMER1:
AnnaBridge 189:f392fc9709a3 44 rcu_periph_clock_enable(RCU_TIMER1);
AnnaBridge 189:f392fc9709a3 45 break;
AnnaBridge 189:f392fc9709a3 46
AnnaBridge 189:f392fc9709a3 47 case TIMER2:
AnnaBridge 189:f392fc9709a3 48 rcu_periph_clock_enable(RCU_TIMER2);
AnnaBridge 189:f392fc9709a3 49 break;
AnnaBridge 189:f392fc9709a3 50
AnnaBridge 189:f392fc9709a3 51 case TIMER3:
AnnaBridge 189:f392fc9709a3 52 rcu_periph_clock_enable(RCU_TIMER3);
AnnaBridge 189:f392fc9709a3 53 break;
AnnaBridge 189:f392fc9709a3 54
AnnaBridge 189:f392fc9709a3 55 case TIMER4:
AnnaBridge 189:f392fc9709a3 56 rcu_periph_clock_enable(RCU_TIMER4);
AnnaBridge 189:f392fc9709a3 57 break;
AnnaBridge 189:f392fc9709a3 58
AnnaBridge 189:f392fc9709a3 59 case TIMER7:
AnnaBridge 189:f392fc9709a3 60 rcu_periph_clock_enable(RCU_TIMER7);
AnnaBridge 189:f392fc9709a3 61 break;
AnnaBridge 189:f392fc9709a3 62 case TIMER8:
AnnaBridge 189:f392fc9709a3 63 rcu_periph_clock_enable(RCU_TIMER8);
AnnaBridge 189:f392fc9709a3 64 break;
AnnaBridge 189:f392fc9709a3 65
AnnaBridge 189:f392fc9709a3 66 case TIMER9:
AnnaBridge 189:f392fc9709a3 67 rcu_periph_clock_enable(RCU_TIMER9);
AnnaBridge 189:f392fc9709a3 68 break;
AnnaBridge 189:f392fc9709a3 69
AnnaBridge 189:f392fc9709a3 70 case TIMER10:
AnnaBridge 189:f392fc9709a3 71 rcu_periph_clock_enable(RCU_TIMER10);
AnnaBridge 189:f392fc9709a3 72 break;
AnnaBridge 189:f392fc9709a3 73
AnnaBridge 189:f392fc9709a3 74 case TIMER11:
AnnaBridge 189:f392fc9709a3 75 rcu_periph_clock_enable(RCU_TIMER11);
AnnaBridge 189:f392fc9709a3 76 break;
AnnaBridge 189:f392fc9709a3 77
AnnaBridge 189:f392fc9709a3 78 case TIMER12:
AnnaBridge 189:f392fc9709a3 79 rcu_periph_clock_enable(RCU_TIMER12);
AnnaBridge 189:f392fc9709a3 80 break;
AnnaBridge 189:f392fc9709a3 81
AnnaBridge 189:f392fc9709a3 82 case TIMER13:
AnnaBridge 189:f392fc9709a3 83 rcu_periph_clock_enable(RCU_TIMER13);
AnnaBridge 189:f392fc9709a3 84 break;
AnnaBridge 189:f392fc9709a3 85 }
AnnaBridge 189:f392fc9709a3 86 /* configure TIMER base function */
AnnaBridge 189:f392fc9709a3 87 timer_initpara.prescaler = 119;
AnnaBridge 189:f392fc9709a3 88 timer_initpara.period = 9999;
AnnaBridge 189:f392fc9709a3 89 timer_initpara.clockdivision = 0;
AnnaBridge 189:f392fc9709a3 90 timer_initpara.counterdirection = TIMER_COUNTER_UP;
AnnaBridge 189:f392fc9709a3 91 timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
AnnaBridge 189:f392fc9709a3 92
AnnaBridge 189:f392fc9709a3 93 timer_init(obj->pwm, &timer_initpara);
AnnaBridge 189:f392fc9709a3 94
AnnaBridge 189:f392fc9709a3 95 /* configure TIMER channel output function */
AnnaBridge 189:f392fc9709a3 96 timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
AnnaBridge 189:f392fc9709a3 97 timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
AnnaBridge 189:f392fc9709a3 98 timer_ocintpara.outputnstate = TIMER_CCXN_ENABLE;
AnnaBridge 189:f392fc9709a3 99 timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
AnnaBridge 189:f392fc9709a3 100 timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
AnnaBridge 189:f392fc9709a3 101 timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
AnnaBridge 189:f392fc9709a3 102 timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_HIGH;
AnnaBridge 189:f392fc9709a3 103 timer_channel_output_config(obj->pwm, obj->ch, &timer_ocintpara);
AnnaBridge 189:f392fc9709a3 104 timer_channel_output_mode_config(obj->pwm, obj->ch, TIMER_OC_MODE_PWM0);
AnnaBridge 189:f392fc9709a3 105 timer_channel_output_fast_config(obj->pwm, obj->ch, TIMER_OC_FAST_DISABLE);
AnnaBridge 189:f392fc9709a3 106
AnnaBridge 189:f392fc9709a3 107 timer_primary_output_config(obj->pwm, ENABLE);
AnnaBridge 189:f392fc9709a3 108 }
AnnaBridge 189:f392fc9709a3 109
AnnaBridge 189:f392fc9709a3 110 static uint8_t dev_pwmout_apb_check(uint32_t periph)
AnnaBridge 189:f392fc9709a3 111 {
AnnaBridge 189:f392fc9709a3 112 uint8_t reval = DEV_PWMOUT_APB1;
AnnaBridge 189:f392fc9709a3 113
AnnaBridge 189:f392fc9709a3 114 /* check peripherals belongs to APB1 or APB2 */
AnnaBridge 189:f392fc9709a3 115 if (DEV_PWMOUT_APB_MASK == (periph & DEV_PWMOUT_APB_MASK)) {
AnnaBridge 189:f392fc9709a3 116 reval = DEV_PWMOUT_APB2;
AnnaBridge 189:f392fc9709a3 117 }
AnnaBridge 189:f392fc9709a3 118
AnnaBridge 189:f392fc9709a3 119 return reval;
AnnaBridge 189:f392fc9709a3 120 }
AnnaBridge 189:f392fc9709a3 121
AnnaBridge 189:f392fc9709a3 122 void pwmout_init(pwmout_t *obj, PinName pin)
AnnaBridge 189:f392fc9709a3 123 {
AnnaBridge 189:f392fc9709a3 124 MBED_ASSERT(obj);
AnnaBridge 189:f392fc9709a3 125
AnnaBridge 189:f392fc9709a3 126 obj->pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
AnnaBridge 189:f392fc9709a3 127 MBED_ASSERT(obj->pwm != (PWMName)NC);
AnnaBridge 189:f392fc9709a3 128
AnnaBridge 189:f392fc9709a3 129 uint32_t function = pinmap_function(pin, PinMap_PWM);
AnnaBridge 189:f392fc9709a3 130 MBED_ASSERT(function != (uint32_t)NC);
AnnaBridge 189:f392fc9709a3 131 obj->ch = GD_PIN_CHANNEL_GET(function);
AnnaBridge 189:f392fc9709a3 132 /* Peripheral initialization */
AnnaBridge 189:f392fc9709a3 133 dev_pwmout_init(obj);
AnnaBridge 189:f392fc9709a3 134 /* pin function initialization */
AnnaBridge 189:f392fc9709a3 135 pinmap_pinout(pin, PinMap_PWM);
AnnaBridge 189:f392fc9709a3 136 }
AnnaBridge 189:f392fc9709a3 137
AnnaBridge 189:f392fc9709a3 138 void pwmout_free(pwmout_t *obj)
AnnaBridge 189:f392fc9709a3 139 {
AnnaBridge 189:f392fc9709a3 140 timer_channel_output_state_config(obj->pwm, obj->ch, TIMER_CCX_DISABLE);
AnnaBridge 189:f392fc9709a3 141 }
AnnaBridge 189:f392fc9709a3 142
AnnaBridge 189:f392fc9709a3 143 void pwmout_write(pwmout_t *obj, float value)
AnnaBridge 189:f392fc9709a3 144 {
AnnaBridge 189:f392fc9709a3 145 uint16_t period;
AnnaBridge 189:f392fc9709a3 146 uint16_t pulse;
AnnaBridge 189:f392fc9709a3 147
AnnaBridge 189:f392fc9709a3 148 timer_disable(obj->pwm);
AnnaBridge 189:f392fc9709a3 149 /* overflow protection */
AnnaBridge 189:f392fc9709a3 150 if (value < (float)0.0) {
AnnaBridge 189:f392fc9709a3 151 value = 0.0;
AnnaBridge 189:f392fc9709a3 152 } else if (value > (float)1.0) {
AnnaBridge 189:f392fc9709a3 153 value = 1.0;
AnnaBridge 189:f392fc9709a3 154 }
AnnaBridge 189:f392fc9709a3 155
AnnaBridge 189:f392fc9709a3 156 period = TIMER_CAR(obj->pwm);
AnnaBridge 189:f392fc9709a3 157 pulse = (uint16_t)(period * value);
AnnaBridge 189:f392fc9709a3 158
AnnaBridge 189:f392fc9709a3 159 timer_channel_output_pulse_value_config(obj->pwm, obj->ch, pulse);
AnnaBridge 189:f392fc9709a3 160
AnnaBridge 189:f392fc9709a3 161 timer_enable(obj->pwm);
AnnaBridge 189:f392fc9709a3 162 }
AnnaBridge 189:f392fc9709a3 163
AnnaBridge 189:f392fc9709a3 164 float pwmout_read(pwmout_t *obj)
AnnaBridge 189:f392fc9709a3 165 {
AnnaBridge 189:f392fc9709a3 166 float value = 0;
AnnaBridge 189:f392fc9709a3 167 uint16_t period;
AnnaBridge 189:f392fc9709a3 168 uint16_t pulse;
AnnaBridge 189:f392fc9709a3 169
AnnaBridge 189:f392fc9709a3 170 period = TIMER_CAR(obj->pwm);
AnnaBridge 189:f392fc9709a3 171
AnnaBridge 189:f392fc9709a3 172 switch (obj->ch) {
AnnaBridge 189:f392fc9709a3 173 case TIMER_CH_0:
AnnaBridge 189:f392fc9709a3 174 pulse = TIMER_CH0CV(obj->pwm);
AnnaBridge 189:f392fc9709a3 175 break;
AnnaBridge 189:f392fc9709a3 176
AnnaBridge 189:f392fc9709a3 177 case TIMER_CH_1:
AnnaBridge 189:f392fc9709a3 178 pulse = TIMER_CH1CV(obj->pwm);
AnnaBridge 189:f392fc9709a3 179 break;
AnnaBridge 189:f392fc9709a3 180
AnnaBridge 189:f392fc9709a3 181 case TIMER_CH_2:
AnnaBridge 189:f392fc9709a3 182 pulse = TIMER_CH2CV(obj->pwm);
AnnaBridge 189:f392fc9709a3 183 break;
AnnaBridge 189:f392fc9709a3 184
AnnaBridge 189:f392fc9709a3 185 case TIMER_CH_3:
AnnaBridge 189:f392fc9709a3 186 pulse = TIMER_CH3CV(obj->pwm);
AnnaBridge 189:f392fc9709a3 187 break;
AnnaBridge 189:f392fc9709a3 188
AnnaBridge 189:f392fc9709a3 189 default:
AnnaBridge 189:f392fc9709a3 190 error("Error: pwm channel error! \r\n");
AnnaBridge 189:f392fc9709a3 191 }
AnnaBridge 189:f392fc9709a3 192
AnnaBridge 189:f392fc9709a3 193 /* calculated waveform duty ratio */
AnnaBridge 189:f392fc9709a3 194 value = (float)(pulse) / (float)(period);
AnnaBridge 189:f392fc9709a3 195
AnnaBridge 189:f392fc9709a3 196 if (value > (float)1.0) {
AnnaBridge 189:f392fc9709a3 197 value = (float)1.0;
AnnaBridge 189:f392fc9709a3 198 }
AnnaBridge 189:f392fc9709a3 199
AnnaBridge 189:f392fc9709a3 200 return value;
AnnaBridge 189:f392fc9709a3 201 }
AnnaBridge 189:f392fc9709a3 202
AnnaBridge 189:f392fc9709a3 203 void pwmout_period(pwmout_t *obj, float seconds)
AnnaBridge 189:f392fc9709a3 204 {
AnnaBridge 189:f392fc9709a3 205 pwmout_period_us(obj, seconds * 1000000.0f);
AnnaBridge 189:f392fc9709a3 206 }
AnnaBridge 189:f392fc9709a3 207
AnnaBridge 189:f392fc9709a3 208 void pwmout_period_ms(pwmout_t *obj, int ms)
AnnaBridge 189:f392fc9709a3 209 {
AnnaBridge 189:f392fc9709a3 210 pwmout_period_us(obj, ms * 1000);
AnnaBridge 189:f392fc9709a3 211 }
AnnaBridge 189:f392fc9709a3 212
AnnaBridge 189:f392fc9709a3 213 void pwmout_period_us(pwmout_t *obj, int us)
AnnaBridge 189:f392fc9709a3 214 {
AnnaBridge 189:f392fc9709a3 215
AnnaBridge 189:f392fc9709a3 216 uint32_t ultemp = 0;
AnnaBridge 189:f392fc9709a3 217 uint32_t timer_clk = 0;
AnnaBridge 189:f392fc9709a3 218 uint32_t period = us - 1;
AnnaBridge 189:f392fc9709a3 219 uint32_t prescaler;
AnnaBridge 189:f392fc9709a3 220 float duty_ratio;
AnnaBridge 189:f392fc9709a3 221
AnnaBridge 189:f392fc9709a3 222 duty_ratio = pwmout_read(obj);
AnnaBridge 189:f392fc9709a3 223
AnnaBridge 189:f392fc9709a3 224 timer_disable(obj->pwm);
AnnaBridge 189:f392fc9709a3 225
AnnaBridge 189:f392fc9709a3 226 timer_clk = timer_get_clock(obj->pwm);
AnnaBridge 189:f392fc9709a3 227
AnnaBridge 189:f392fc9709a3 228 ultemp = (timer_clk / 1000000);
AnnaBridge 189:f392fc9709a3 229 prescaler = ultemp;
AnnaBridge 189:f392fc9709a3 230 obj->cnt_unit = 1;
AnnaBridge 189:f392fc9709a3 231
AnnaBridge 189:f392fc9709a3 232 while (period > 0xFFFF) {
AnnaBridge 189:f392fc9709a3 233 obj->cnt_unit = obj->cnt_unit << 1;
AnnaBridge 189:f392fc9709a3 234 period = period >> 1;
AnnaBridge 189:f392fc9709a3 235 prescaler = ultemp * obj->cnt_unit;
AnnaBridge 189:f392fc9709a3 236 }
AnnaBridge 189:f392fc9709a3 237
AnnaBridge 189:f392fc9709a3 238 if (prescaler > 0xFFFF) {
AnnaBridge 189:f392fc9709a3 239 error("Error: TIMER prescaler value is overflow \r\n");
AnnaBridge 189:f392fc9709a3 240 }
AnnaBridge 189:f392fc9709a3 241
AnnaBridge 189:f392fc9709a3 242 timer_autoreload_value_config(obj->pwm, period);
AnnaBridge 189:f392fc9709a3 243 timer_prescaler_config(obj->pwm, prescaler - 1, TIMER_PSC_RELOAD_NOW);
AnnaBridge 189:f392fc9709a3 244
AnnaBridge 189:f392fc9709a3 245 ultemp = duty_ratio * us;
AnnaBridge 189:f392fc9709a3 246
AnnaBridge 189:f392fc9709a3 247 pwmout_pulsewidth_us(obj, ultemp);
AnnaBridge 189:f392fc9709a3 248
AnnaBridge 189:f392fc9709a3 249 timer_enable(obj->pwm);
AnnaBridge 189:f392fc9709a3 250 }
AnnaBridge 189:f392fc9709a3 251
AnnaBridge 189:f392fc9709a3 252 void pwmout_pulsewidth(pwmout_t *obj, float seconds)
AnnaBridge 189:f392fc9709a3 253 {
AnnaBridge 189:f392fc9709a3 254 pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
AnnaBridge 189:f392fc9709a3 255 }
AnnaBridge 189:f392fc9709a3 256
AnnaBridge 189:f392fc9709a3 257 void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
AnnaBridge 189:f392fc9709a3 258 {
AnnaBridge 189:f392fc9709a3 259 pwmout_pulsewidth_us(obj, ms * 1000);
AnnaBridge 189:f392fc9709a3 260 }
AnnaBridge 189:f392fc9709a3 261
AnnaBridge 189:f392fc9709a3 262 void pwmout_pulsewidth_us(pwmout_t *obj, int us)
AnnaBridge 189:f392fc9709a3 263 {
AnnaBridge 189:f392fc9709a3 264 uint32_t pulse;
AnnaBridge 189:f392fc9709a3 265 uint32_t period;
AnnaBridge 189:f392fc9709a3 266
AnnaBridge 189:f392fc9709a3 267 period = TIMER_CAR(obj->pwm);
AnnaBridge 189:f392fc9709a3 268 pulse = us / obj->cnt_unit;
AnnaBridge 189:f392fc9709a3 269
AnnaBridge 189:f392fc9709a3 270 if (pulse > period) {
AnnaBridge 189:f392fc9709a3 271 pulse = period;
AnnaBridge 189:f392fc9709a3 272 }
AnnaBridge 189:f392fc9709a3 273
AnnaBridge 189:f392fc9709a3 274 timer_channel_output_pulse_value_config(obj->pwm, obj->ch, pulse);
AnnaBridge 189:f392fc9709a3 275 }
AnnaBridge 189:f392fc9709a3 276
AnnaBridge 189:f392fc9709a3 277 static uint32_t timer_get_clock(uint32_t timer_periph)
AnnaBridge 189:f392fc9709a3 278 {
AnnaBridge 189:f392fc9709a3 279 uint32_t timerclk;
AnnaBridge 189:f392fc9709a3 280
AnnaBridge 189:f392fc9709a3 281 if ((TIMER0 == timer_periph) || (TIMER7 == timer_periph) ||
AnnaBridge 189:f392fc9709a3 282 (TIMER8 == timer_periph) || (TIMER9 == timer_periph) || (TIMER10 == timer_periph)) {
AnnaBridge 189:f392fc9709a3 283 /* get the current APB2 TIMER clock source */
AnnaBridge 189:f392fc9709a3 284 if (RCU_APB2_CKAHB_DIV1 == (RCU_CFG0 & RCU_CFG0_APB2PSC)) {
AnnaBridge 189:f392fc9709a3 285 timerclk = rcu_clock_freq_get(CK_APB2);
AnnaBridge 189:f392fc9709a3 286 } else {
AnnaBridge 189:f392fc9709a3 287 timerclk = rcu_clock_freq_get(CK_APB2) * 2;
AnnaBridge 189:f392fc9709a3 288 }
AnnaBridge 189:f392fc9709a3 289 } else {
AnnaBridge 189:f392fc9709a3 290 /* get the current APB1 TIMER clock source */
AnnaBridge 189:f392fc9709a3 291 if (RCU_APB1_CKAHB_DIV1 == (RCU_CFG0 & RCU_CFG0_APB1PSC)) {
AnnaBridge 189:f392fc9709a3 292 timerclk = rcu_clock_freq_get(CK_APB1);
AnnaBridge 189:f392fc9709a3 293 } else {
AnnaBridge 189:f392fc9709a3 294 timerclk = rcu_clock_freq_get(CK_APB1) * 2;
AnnaBridge 189:f392fc9709a3 295 }
AnnaBridge 189:f392fc9709a3 296 }
AnnaBridge 189:f392fc9709a3 297
AnnaBridge 189:f392fc9709a3 298 return timerclk;
AnnaBridge 189:f392fc9709a3 299 }