Skip to content

Commit 3519122

Browse files
committed
cCR changes for nRF52 PwmOut implementation.
1 parent 9f33787 commit 3519122

File tree

1 file changed

+64
-29
lines changed
  • hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/TARGET_MCU_NRF52832

1 file changed

+64
-29
lines changed

hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/TARGET_MCU_NRF52832/pwmout_api.c

Lines changed: 64 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,45 @@
4747
#include "app_util_platform.h"
4848
#include "nrf_drv_pwm.h"
4949

50-
51-
#define MAX_PWM_PERIOD_US (0x7FFF << 3) // -> 7FFF (1_us/16) * 128
50+
#define MAX_PWM_COUNTERTOP (0x7FFF) // 0x7FFF is the max of COUNTERTOP value for the PWM peripherial of the nRF52.
51+
#define MAX_PWM_PERIOD_US (MAX_PWM_COUNTERTOP * 8) // PWM hw is driven by 16 MHz clock, hence the tick is 1_us/16,
52+
// and 128 is the max prescaler value.
5253
#define MAX_PWM_PERIOD_MS ((MAX_PWM_PERIOD_US / 1000) + 1) // approximations advance
5354
#define MAX_PWM_PERIOD_S ((MAX_PWM_PERIOD_US / 1000000) + 1) // approximations advance
5455

55-
#define PWM_INSTANCE_COUNT 3
56+
#ifdef PWM0_ENABLED
57+
#define __PWM0_NUM 1
58+
#else
59+
#define __PWM0_NUM 0
60+
#endif
61+
62+
#ifdef PWM1_ENABLED
63+
#define __PWM1_NUM 1
64+
#else
65+
#define __PWM1_NUM 0
66+
#endif
67+
68+
#ifdef PWM2_ENABLED
69+
#define __PWM2_NUM 1
70+
#else
71+
#define __PWM2_NUM 0
72+
#endif
73+
74+
75+
#define PWM_INSTANCE_COUNT (__PWM0_NUM + __PWM1_NUM + __PWM2_NUM)
5676

5777
///> instances of nRF52 PWM driver
58-
static nrf_drv_pwm_t m_pwm_driver[PWM_INSTANCE_COUNT] =
78+
static const nrf_drv_pwm_t m_pwm_driver[PWM_INSTANCE_COUNT] =
5979
{
80+
#ifdef PWM0_ENABLED
6081
NRF_DRV_PWM_INSTANCE(0),
82+
#endif
83+
#ifdef PWM1_ENABLED
6184
NRF_DRV_PWM_INSTANCE(1),
85+
#endif
86+
#ifdef PWM2_ENABLED
6287
NRF_DRV_PWM_INSTANCE(2)
88+
#endif
6389
};
6490

6591
typedef struct
@@ -78,20 +104,26 @@ typedef struct
78104

79105
static pwm_t m_pwm[PWM_INSTANCE_COUNT] =
80106
{
107+
#ifdef PWM0_ENABLED
81108
{.p_pwm_driver = NULL},
109+
#endif
110+
#ifdef PWM0_ENABLED
82111
{.p_pwm_driver = NULL},
112+
#endif
113+
#ifdef PWM0_ENABLED
83114
{.p_pwm_driver = NULL}
115+
#endif
84116
}; /// Array of internal PWM instances.
85117

86118
typedef struct
87119
{
88-
uint16_t period_hwu;
89-
uint16_t duty_hwu;
120+
uint16_t period_hwu; // unit related to pwm_clk
121+
uint16_t duty_hwu; // unit related to pwm_clk
90122
nrf_pwm_clk_t pwm_clk;
91123
} pulsewidth_set_t; /// helper type for timing calculations
92124

93125

94-
static void internal_pwmout_exe(pwmout_t *obj, bool new_period);
126+
static void internal_pwmout_exe(pwmout_t *obj, bool new_period, bool initialization);
95127

96128
void pwmout_init(pwmout_t *obj, PinName pin)
97129
{
@@ -105,14 +137,14 @@ void pwmout_init(pwmout_t *obj, PinName pin)
105137

106138
obj->pwm_channel = i;
107139

108-
m_pwm[i].p_pwm_driver = &m_pwm_driver[i];
140+
m_pwm[i].p_pwm_driver = (nrf_drv_pwm_t *) &m_pwm_driver[i];
109141
m_pwm[i].signal.period_us = 200000; // 0.02 s
110142
m_pwm[i].signal.duty_us = 100000;
111-
m_pwm[i].signal.duty = (0.5);
143+
m_pwm[i].signal.duty = 0.5f;
112144

113145
obj->pwm_struct = &m_pwm[i];
114146

115-
internal_pwmout_exe(obj, true);
147+
internal_pwmout_exe(obj, true, true);
116148

117149
break;
118150
}
@@ -135,16 +167,16 @@ void pwmout_write(pwmout_t *obj, float percent)
135167
{
136168
percent = 0;
137169
}
138-
else if (percent > 100)
170+
else if (percent > 1)
139171
{
140-
percent = 100;
172+
percent = 1;
141173
}
142174

143175
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
144176

145-
p_pwm_signal->duty = percent / 100;
177+
p_pwm_signal->duty = percent;
146178

147-
int us = (((int)p_pwm_signal->period_us) * percent) / 100;
179+
int us = (((int)p_pwm_signal->period_us) * percent);
148180

149181
pwmout_pulsewidth_us(obj, us);
150182
}
@@ -153,7 +185,7 @@ float pwmout_read(pwmout_t *obj)
153185
{
154186
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
155187

156-
return (float)p_pwm_signal->duty_us / (float)p_pwm_signal->period_us * 100;
188+
return (float)p_pwm_signal->duty_us / (float)p_pwm_signal->period_us;
157189
}
158190

159191
void pwmout_period(pwmout_t *obj, float seconds)
@@ -209,7 +241,7 @@ void pwmout_period_us(pwmout_t *obj, int us)
209241

210242
p_pwm_signal->period_us = us;
211243

212-
internal_pwmout_exe(obj, true);
244+
internal_pwmout_exe(obj, true, false);
213245
}
214246

215247
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
@@ -263,40 +295,40 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
263295
p_pwm_signal->duty_us = us;
264296
p_pwm_signal->duty = us / p_pwm_signal->period_us;
265297

266-
internal_pwmout_exe(obj, false);
298+
internal_pwmout_exe(obj, false, false);
267299
}
268300

269301

270302

271303

272304

273305

274-
static ret_code_t pulsewidth_us_set_get(int period_us, int duty_us, pulsewidth_set_t * const p_settings)
306+
static ret_code_t pulsewidth_us_set_get(int period_hwu, int duty_hwu, pulsewidth_set_t * p_settings)
275307
{
276308
uint16_t div;
277309
nrf_pwm_clk_t pwm_clk = NRF_PWM_CLK_16MHz;
278310

279-
for(div = 1; div <= 128 ; div <<= 1)
311+
for(div = 1; div <= 128 ; div <<= 1) // 128 is the maximum of clock prescaler for PWM peripherial
280312
{
281-
if (0x7FFF >= period_us)
313+
if (MAX_PWM_COUNTERTOP >= period_hwu)
282314
{
283-
p_settings->period_hwu = period_us; // unit [us/16 * div]
284-
p_settings->duty_hwu = duty_us; // unit [us/16 * div]
315+
p_settings->period_hwu = period_hwu; // unit [us/16 * div]
316+
p_settings->duty_hwu = duty_hwu; // unit [us/16 * div]
285317
p_settings->pwm_clk = pwm_clk;
286318

287319
return NRF_SUCCESS;
288320
}
289321

290-
period_us >>= 1;
291-
duty_us >>= 1;
322+
period_hwu >>= 1;
323+
duty_hwu >>= 1;
292324
pwm_clk++;
293325
}
294326

295327
return NRF_ERROR_INVALID_PARAM;
296328
}
297329

298330

299-
static void internal_pwmout_exe(pwmout_t *obj, bool new_period)
331+
static void internal_pwmout_exe(pwmout_t *obj, bool new_period, bool initialization)
300332
{
301333
pulsewidth_set_t pulsewidth_set;
302334
pwm_signal_t * p_pwm_signal;
@@ -305,13 +337,13 @@ static void internal_pwmout_exe(pwmout_t *obj, bool new_period)
305337

306338
p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
307339

308-
if (NRF_SUCCESS == pulsewidth_us_set_get(p_pwm_signal->period_us * 16,
309-
p_pwm_signal->duty_us * 16,
340+
if (NRF_SUCCESS == pulsewidth_us_set_get(p_pwm_signal->period_us * 16, // base clk for PWM is 16 MHz
341+
p_pwm_signal->duty_us * 16, // base clk for PWM is 16 MHz
310342
&pulsewidth_set))
311343
{
312344
p_pwm_driver = (((pwm_t*)obj->pwm_struct)->p_pwm_driver);
313345

314-
nrf_pwm_sequence_t seq =
346+
const nrf_pwm_sequence_t seq =
315347
{
316348
.values.p_common = (nrf_pwm_values_common_t*) (((pwm_t*)obj->pwm_struct)->seq_values),
317349
.length = 1,
@@ -340,7 +372,10 @@ static void internal_pwmout_exe(pwmout_t *obj, bool new_period)
340372
.step_mode = NRF_PWM_STEP_AUTO
341373
};
342374

343-
nrf_drv_pwm_uninit(p_pwm_driver);
375+
if (!initialization)
376+
{
377+
nrf_drv_pwm_uninit(p_pwm_driver);
378+
}
344379

345380
ret_code = nrf_drv_pwm_init( p_pwm_driver, &config0, NULL);
346381

0 commit comments

Comments
 (0)