Skip to content

Commit f5cdf6a

Browse files
mcbridejcsalkinium
authored andcommitted
[sam] Add driver for SAMG timer channels
1 parent c868f59 commit f5cdf6a

File tree

8 files changed

+600
-2
lines changed

8 files changed

+600
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ Please [discover modm's peripheral drivers for your specific device][discover].
449449
<td align="center">✅</td>
450450
<td align="center">✅</td>
451451
<td align="center">○</td>
452-
<td align="center"></td>
452+
<td align="center"></td>
453453
<td align="center">○</td>
454454
<td align="center">○</td>
455455
<td align="center">○</td>
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright (c) 2021, Jeff McBride
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
11+
#include <modm/board.hpp>
12+
#include <modm/io/iostream.hpp>
13+
#include <modm/platform.hpp>
14+
15+
using namespace modm::platform;
16+
using namespace modm::literals;
17+
18+
MODM_ISR(TC3)
19+
{
20+
// Clear pending interrupts by reading them
21+
(void)TimerChannel3::getInterruptFlags();
22+
23+
static bool flag = false;
24+
if (flag)
25+
{
26+
TimerChannel0::setTiobEffects(TimerChannel0::TioEffect::Clear,
27+
TimerChannel0::TioEffect::Set);
28+
} else
29+
{
30+
TimerChannel0::setTiobEffects(TimerChannel0::TioEffect::Set,
31+
TimerChannel0::TioEffect::Clear);
32+
}
33+
flag = !flag;
34+
}
35+
36+
int
37+
main()
38+
{
39+
/*
40+
* This example uses channel 0 to generate two output waveforms, and channel3
41+
* to create a periodic IRQ which swaps the polarity on the TIOB output.
42+
*
43+
* Note:
44+
* On the SAMG55, the waveform outputs on the second module (TC1, TimerChannel[3-5])
45+
* are not connected to external pins.
46+
*/
47+
Board::initialize();
48+
49+
TimerChannel0::initialize();
50+
TimerChannel0::connect<GpioA0::Tioa, GpioA1::Tiob>();
51+
52+
TimerChannel0::setClockSource(TimerChannel0::ClockSource::MckDiv2);
53+
TimerChannel0::setWaveformMode(true);
54+
// Setup timer to count up, and trigger reset on Rc match
55+
TimerChannel0::setWaveformSelection(TimerChannel0::WavSel::Up_Rc);
56+
57+
// Setup TioA to set on RA match, and clear on RC match
58+
TimerChannel0::setTioaEffects(TimerChannel0::TioEffect::Set, TimerChannel0::TioEffect::Clear);
59+
// Setup TioB to clear on RB match, and set on RC match
60+
TimerChannel0::setTiobEffects(TimerChannel0::TioEffect::Clear, TimerChannel0::TioEffect::Set);
61+
62+
// Change external event source, so that TIOB can be used as an output
63+
TimerChannel0::setExtEventSource(TimerChannel0::ExtEventSource::Xc0);
64+
65+
TimerChannel0::setRegA(10000);
66+
TimerChannel0::setRegB(5000);
67+
TimerChannel0::setRegC(15000);
68+
69+
TimerChannel0::enable();
70+
TimerChannel0::start();
71+
72+
// Setup TC3 irq to swap TIOB polarity periodically
73+
// Period = 128 * 10000 / 120MHz = ~10.6ms
74+
TimerChannel3::initialize();
75+
TimerChannel3::setClockSource(TimerChannel0::ClockSource::MckDiv128);
76+
TimerChannel3::setRegC(10000);
77+
TimerChannel3::setWaveformMode(true);
78+
TimerChannel3::setWaveformSelection(TimerChannel0::WavSel::Up_Rc);
79+
TimerChannel3::enableInterruptVector(true);
80+
TimerChannel3::enableInterrupt(TimerChannel3::Interrupt::RcCompare);
81+
TimerChannel3::enable();
82+
TimerChannel3::start();
83+
84+
while (true)
85+
;
86+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
# Configure for ATSAMG55-XPRO dev board
3+
source [find interface/cmsis-dap.cfg]
4+
5+
set CHIPNAME ATSAMG55J19
6+
source [find target/at91samg5x.cfg]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<library>
2+
<extends>modm:samg55-xplained-pro</extends>
3+
<options>
4+
<option name="modm:build:build.path">../../../build/samg55_xplained_pro/timer</option>
5+
<option name="modm:build:openocd.cfg">openocd.cfg</option>
6+
</options>
7+
<modules>
8+
<module>modm:build:scons</module>
9+
<module>modm:platform:timer:0</module>
10+
<module>modm:platform:timer:1</module>
11+
<module>modm:platform:timer:2</module>
12+
<module>modm:platform:timer:3</module>
13+
</modules>
14+
</library>

src/modm/board/samg55_xplained_pro/board.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,16 @@ struct SystemClock
2727

2828
static constexpr uint32_t Frequency = PllAMult * SlowClkFreqHz; // CPU core frequency
2929
static constexpr uint32_t Usb = PllBMult * SlowClkFreqHz;
30-
static constexpr uint32_t Mck = Frequency; // Master clock, used by most peripherals
30+
static constexpr uint32_t Mck = Frequency; // Master clock: default used by most peripherals
31+
// Programmable clocks: optionally used by certain peripherals
32+
static constexpr uint32_t Pck0 = Mck;
33+
static constexpr uint32_t Pck1 = Mck;
34+
static constexpr uint32_t Pck2 = Mck;
35+
static constexpr uint32_t Pck3 = Mck;
36+
static constexpr uint32_t Pck4 = Mck;
37+
static constexpr uint32_t Pck5 = Mck;
38+
static constexpr uint32_t Pck6 = Mck;
39+
static constexpr uint32_t Pck7 = Mck;
3140

3241
static bool inline
3342
enable()
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Copyright (c) 2021, Jeff McBride
5+
#
6+
# This file is part of the modm project.
7+
#
8+
# This Source Code Form is subject to the terms of the Mozilla Public
9+
# License, v. 2.0. If a copy of the MPL was not distributed with this
10+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
11+
# -----------------------------------------------------------------------------
12+
13+
props = {}
14+
class Instance(Module):
15+
def __init__(self, driver, instance, channel):
16+
self.driver = driver
17+
self.instance = int(instance)
18+
self.channel = channel
19+
self.vectors = None
20+
21+
def init(self, module):
22+
module.name = str(self.instance)
23+
module.description = "Instance {}".format(self.instance)
24+
25+
def prepare(self, module, options):
26+
return True
27+
28+
def build(self, env):
29+
global props
30+
props["id"] = self.instance
31+
props["module"] = int(self.instance / 3)
32+
props["channel"] = self.channel
33+
34+
env.substitutions = props
35+
env.outbasepath = "modm/src/modm/platform/timer"
36+
env.template("timer_channel.hpp.in", "timer_channel_{}.hpp".format(self.instance))
37+
38+
def init(module):
39+
module.name = ":platform:timer"
40+
module.description = "Timers (TC)"
41+
42+
def prepare(module, options):
43+
device = options[":target"]
44+
if not device.has_driver("tc:samg*"):
45+
return False
46+
47+
module.depends(
48+
":cmsis:device",
49+
":platform:gpio")
50+
51+
timers = device.get_all_drivers("tc:samg*")
52+
for driver in timers:
53+
for instance in driver["instance"]:
54+
instance = int(instance)
55+
# Each TC instance has 3 channels, and we create an independent driver for each
56+
for channel in range(3):
57+
module.add_submodule(Instance(driver, instance*3+channel, channel))
58+
59+
global props
60+
device = options[":target"]
61+
props["target"] = device.identifier
62+
63+
return True
64+
65+
def build(env):
66+
env.outbasepath = "modm/src/modm/platform/timer"
67+
env.copy("timer_channel_base.hpp")

0 commit comments

Comments
 (0)