Skip to content

Commit f799850

Browse files
Start implementing PWM
1 parent b82783f commit f799850

File tree

6 files changed

+482
-0
lines changed

6 files changed

+482
-0
lines changed

targets/TARGET_Ambiq_Micro/TARGET_Apollo3/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ target_sources(mbed-apollo3
5151
device/us_ticker.c
5252
device/itm_api.c
5353
device/analogin_api.c
54+
device/pwmout_api.c
5455

5556
sdk/CMSIS/AmbiqMicro/Source/system_apollo3.c
5657

targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralPins.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,50 @@ const PinMap PinMap_SPI_SSEL[] = {
267267
};
268268

269269
/************PWM***************/
270+
// Note: The Apollo3 has fairly flexible PWM pin mapping options. Each IO pin which has a PWM function
271+
// can actually map to one of 6 different PWM module outputs. However, there are as many PWM module
272+
// outputs as there are pins, so we don't need to use this just to give every pin its own PWM output.
273+
// For now, we always use the first possible option (Output Selection 2 in Table 814).
270274
const PinMap PinMap_PWM[] = {
275+
{IO_12, CTIMER_A0_OUT1, AM_HAL_PIN_12_CTIM0},
276+
{IO_25, CTIMER_A0_OUT2, AM_HAL_PIN_25_CTIM1},
277+
{IO_13, CTIMER_B0_OUT1, AM_HAL_PIN_13_CTIM2},
278+
{IO_26, CTIMER_B0_OUT2, AM_HAL_PIN_26_CTIM3},
279+
{IO_18, CTIMER_A1_OUT1, AM_HAL_PIN_18_CTIM4},
280+
{IO_27, CTIMER_A1_OUT2, AM_HAL_PIN_27_CTIM5},
281+
{IO_19, CTIMER_B1_OUT1, AM_HAL_PIN_19_CTIM6},
282+
{IO_28, CTIMER_B1_OUT2, AM_HAL_PIN_28_CTIM7},
283+
{IO_5, CTIMER_A2_OUT1, AM_HAL_PIN_5_CTIM8},
284+
{IO_29, CTIMER_A2_OUT2, AM_HAL_PIN_29_CTIM9},
285+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
286+
{IO_30, CTIMER_B2_OUT2, AM_HAL_PIN_30_CTIM11},
287+
{IO_22, CTIMER_A3_OUT1, AM_HAL_PIN_22_CTIM12},
288+
{IO_31, CTIMER_A3_OUT2, AM_HAL_PIN_31_CTIM13},
289+
{IO_23, CTIMER_B3_OUT1, AM_HAL_PIN_23_CTIM14},
290+
{IO_32, CTIMER_B3_OUT2, AM_HAL_PIN_32_CTIM15},
291+
{IO_42, CTIMER_A4_OUT1, AM_HAL_PIN_42_CTIM16},
292+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
293+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
294+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
295+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
296+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
297+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
298+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
299+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
300+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
301+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
302+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
303+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
304+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
305+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
306+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
307+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
308+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
309+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
310+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
311+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
312+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
313+
{IO_6, CTIMER_B2_OUT1, AM_HAL_PIN_6_CTIM10},
314+
271315
{NC, NC, 0}
272316
};

targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@
2828
#include "objects_spi.h"
2929
#include "objects_i2c.h"
3030
#include "objects_adc.h"
31+
#include "objects_pwm.h"
3132

3233
#endif
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2025 Jamie Smith
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#ifndef OBJECTS_PWM_H
19+
#define OBJECTS_PWM_H
20+
21+
#include "am_hal_ctimer.h"
22+
23+
#ifdef __cplusplus
24+
extern "C" {
25+
#endif
26+
27+
// This MCU has 8 CTIMER modules, each of which contains two segments. The two segments are functionally independent
28+
// except that the B segment can optionally be combined with the A segment for a 32-bit counter (which we don't use).
29+
// Each segment has two independent compare outputs, meaning that we have a total of 32 possible PWM outputs.
30+
31+
// PWM name is composed of the CTIMER number, whether it's an A or B segment, and whether this is the first or second
32+
// output from it.
33+
#define APOLLO3_PWM_NAME(ctimerNum, aOrB, outputNum) ((ctimerNum << 2) | (aOrB << 1) | outputNum)
34+
35+
typedef enum {
36+
CTIMER_A0_OUT1 = APOLLO3_PWM_NAME(0, 0, 0),
37+
CTIMER_A0_OUT2 = APOLLO3_PWM_NAME(0, 0, 1),
38+
39+
CTIMER_A1_OUT1 = APOLLO3_PWM_NAME(1, 0, 0),
40+
CTIMER_A1_OUT2 = APOLLO3_PWM_NAME(1, 0, 1),
41+
42+
CTIMER_A2_OUT1 = APOLLO3_PWM_NAME(2, 0, 0),
43+
CTIMER_A2_OUT2 = APOLLO3_PWM_NAME(2, 0, 1),
44+
45+
CTIMER_A3_OUT1 = APOLLO3_PWM_NAME(3, 0, 0),
46+
CTIMER_A3_OUT2 = APOLLO3_PWM_NAME(3, 0, 1),
47+
48+
CTIMER_A4_OUT1 = APOLLO3_PWM_NAME(4, 0, 0),
49+
CTIMER_A4_OUT2 = APOLLO3_PWM_NAME(4, 0, 1),
50+
51+
CTIMER_A5_OUT1 = APOLLO3_PWM_NAME(5, 0, 0),
52+
CTIMER_A5_OUT2 = APOLLO3_PWM_NAME(5, 0, 1),
53+
54+
CTIMER_A6_OUT1 = APOLLO3_PWM_NAME(6, 0, 0),
55+
CTIMER_A6_OUT2 = APOLLO3_PWM_NAME(6, 0, 1),
56+
57+
CTIMER_A7_OUT1 = APOLLO3_PWM_NAME(7, 0, 0),
58+
CTIMER_A7_OUT2 = APOLLO3_PWM_NAME(7, 0, 1),
59+
60+
CTIMER_B0_OUT1 = APOLLO3_PWM_NAME(0, 1, 0),
61+
CTIMER_B0_OUT2 = APOLLO3_PWM_NAME(0, 1, 1),
62+
63+
CTIMER_B1_OUT1 = APOLLO3_PWM_NAME(1, 1, 0),
64+
CTIMER_B1_OUT2 = APOLLO3_PWM_NAME(1, 1, 1),
65+
66+
CTIMER_B2_OUT1 = APOLLO3_PWM_NAME(2, 1, 0),
67+
CTIMER_B2_OUT2 = APOLLO3_PWM_NAME(2, 1, 1),
68+
69+
CTIMER_B3_OUT1 = APOLLO3_PWM_NAME(3, 1, 0),
70+
CTIMER_B3_OUT2 = APOLLO3_PWM_NAME(3, 1, 1),
71+
72+
CTIMER_B4_OUT1 = APOLLO3_PWM_NAME(4, 1, 0),
73+
CTIMER_B4_OUT2 = APOLLO3_PWM_NAME(4, 1, 1),
74+
75+
CTIMER_B5_OUT1 = APOLLO3_PWM_NAME(5, 1, 0),
76+
CTIMER_B5_OUT2 = APOLLO3_PWM_NAME(5, 1, 1),
77+
78+
CTIMER_B6_OUT1 = APOLLO3_PWM_NAME(6, 1, 0),
79+
CTIMER_B6_OUT2 = APOLLO3_PWM_NAME(6, 1, 1),
80+
81+
CTIMER_B7_OUT1 = APOLLO3_PWM_NAME(7, 1, 0),
82+
CTIMER_B7_OUT2 = APOLLO3_PWM_NAME(7, 1, 1),
83+
} PWMName;
84+
85+
// Get the CTIMER number of a PWM
86+
#define APOLLO3_PWMNAME_GET_CTIMER(pwmName) (pwmName >> 2)
87+
88+
// Convert from PWM name to AM_HAL_CTIMER_TIMERA/AM_HAL_CTIMER_TIMERB macro
89+
#define APOLLO3_PWMNAME_GET_SEGMENT(pwmName) (pwmName & 0b10 ? AM_HAL_CTIMER_TIMERB : AM_HAL_CTIMER_TIMERA)
90+
91+
// Convert from PWM name to AM_HAL_CTIMER_OUTPUT_NORMAL/AM_HAL_CTIMER_OUTPUT_SECONDARY enum value
92+
#define APOLLO3_PWMNAME_GET_OUTPUT(pwmName) (pwmName & 0b1 ? AM_HAL_CTIMER_OUTPUT_SECONDARY : AM_HAL_CTIMER_OUTPUT_NORMAL)
93+
94+
struct pwmout_s
95+
{
96+
// PWM name that this channel is using
97+
PWMName pwmName;
98+
};
99+
100+
#ifdef __cplusplus
101+
}
102+
#endif
103+
104+
#endif

0 commit comments

Comments
 (0)