Skip to content

Commit 823d9f6

Browse files
committed
[rp2040] review
1 parent 38cc993 commit 823d9f6

File tree

6 files changed

+129
-61
lines changed

6 files changed

+129
-61
lines changed

src/modm/platform/clock/rp/module.lb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ def build(env):
3131
properties["target"] = target = device.identifier
3232
properties["partname"] = device.partname
3333
properties["core"] = core = device.get_driver("core")["type"]
34-
properties["xosc_freq"] = env.get("")
3534

3635
env.substitutions = properties
3736
env.outbasepath = "modm/src/modm/platform/clock"

src/modm/platform/dma/rp/dma.hpp.in

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -114,24 +114,9 @@ class DmaController : public DmaBase
114114
static constexpr uint32_t value = val;
115115
};
116116
public:
117-
118-
/**
119-
* Enable the DMA controller
120-
*/
121-
static void
122-
enable()
123-
{
124-
125-
}
126117
/**
127-
* Disable the DMA controller
118+
* Start multiple channels simultaneously
128119
*/
129-
static void
130-
disable()
131-
{
132-
133-
}
134-
135120
template <class ...Channels>
136121
static inline void start() {
137122
dma_hw->multi_channel_trigger = bit_or<Channels::mask...>::value;
@@ -338,6 +323,30 @@ public:
338323
static inline bool isBusy() {
339324
return !!(dma_hw->ch[idx].al1_ctrl & DMA_CH0_CTRL_TRIG_BUSY_BITS);
340325
}
326+
327+
static inline bool isCompleted() {
328+
return !isBusy();
329+
}
330+
331+
static inline void startWrite(const void* src,std::size_t count)
332+
{
333+
dma_hw->ch[idx].read_addr = (uint32_t)src;
334+
dma_hw->ch[idx].al1_transfer_count_trig = count;
335+
}
336+
337+
static inline void startRead(void* dst,std::size_t count)
338+
{
339+
dma_hw->ch[idx].write_addr = (uint32_t)dst;
340+
dma_hw->ch[idx].al1_transfer_count_trig = count;
341+
}
342+
343+
template <class OtherChannel>
344+
static inline void chainTo()
345+
{
346+
hw_write_masked(&dma_hw->ch[idx].al1_ctrl,
347+
(OtherChannel::idx << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB),
348+
DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS);
349+
}
341350
private:
342351

343352
};

src/modm/platform/spi/rp/spi_master.hpp.in

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,19 @@ protected:
6161
// Don't leave overrun flag set
6262
spi{{ id }}_hw->icr = SPI_SSPICR_RORIC_BITS;
6363
}
64+
/*
65+
* Find smallest prescale value which puts output frequency in range of
66+
* post-divide. Prescale is an even number from 2 to 254 inclusive.
67+
*/
68+
template <uint32_t freq_in, baudrate_t baudrate>
69+
constexpr static uint32_t calcPrescale() {
70+
uint32_t prescale;
71+
for (prescale = 2; prescale <= 254; prescale += 2) {
72+
if (freq_in < (prescale + 2) * 256 * (uint64_t) baudrate)
73+
break;
74+
}
75+
return prescale;
76+
}
6477
public:
6578
template< class... Signals >
6679
static void
@@ -92,29 +105,25 @@ public:
92105
SPI_SSPCR0_SPH_BITS);
93106
}
94107

95-
template< class SystemClock, baudrate_t baudrate >
108+
template< class SystemClock, baudrate_t baudrate, percent_t tolerance=pct(5)>
96109
static uint32_t setBaudrate() {
97110
constexpr uint32_t freq_in = SystemClock::PeriFrequency;
98-
uint32_t prescale,postdiv;
99-
// Find smallest prescale value which puts output frequency in range of
100-
// post-divide. Prescale is an even number from 2 to 254 inclusive.
101-
for (prescale = 2; prescale <= 254; prescale += 2) {
102-
if (freq_in < (prescale + 2) * 256 * (uint64_t) baudrate)
103-
break;
104-
}
105-
//atatic_assert(prescale <= 254); // Frequency too low
111+
constexpr uint32_t prescale = calcPrescale<freq_in,baudrate>();
112+
static_assert(prescale <= 254, "Frequency too low");
113+
static_assert(freq_in / prescale <= 256 * (uint64_t) baudrate, "Failed calc prescale");
106114

107-
// Find largest post-divide which makes output <= baudrate. Post-divide is
115+
// Find largest post-divide which makes output closest to baudrate. Post-divide is
108116
// an integer in the range 1 to 256 inclusive.
109-
for (postdiv = 256; postdiv > 1; --postdiv) {
110-
if (freq_in / (prescale * (postdiv - 1)) > baudrate)
111-
break;
112-
}
117+
constexpr uint32_t postdiv = Prescaler::from_range(freq_in / prescale, baudrate, 1, 256).prescaler;
118+
119+
constexpr uint32_t result_baudrate = freq_in / (prescale * postdiv);
120+
121+
assertBaudrateInTolerance< result_baudrate, baudrate, tolerance >();
113122

114123
spi{{ id }}_hw->cpsr = prescale;
115124
hw_write_masked(&spi{{ id }}_hw->cr0, (postdiv - 1) << SPI_SSPCR0_SCR_LSB, SPI_SSPCR0_SCR_BITS);
116125

117-
return freq_in / (prescale * postdiv);
126+
return result_baudrate;
118127
}
119128

120129
// start documentation inherited
@@ -124,7 +133,7 @@ public:
124133
reset();
125134
unreset();
126135

127-
setBaudrate<SystemClock,baudrate>();
136+
setBaudrate<SystemClock,baudrate,tolerance>();
128137
setFormat(8,DataMode::Mode0,DataOrder::MsbFirst);
129138
// Set master mode
130139
hw_clear_bits(&spi{{ id }}_hw->cr1, SPI_SSPCR1_MS_BITS);

src/modm/platform/spi/rp/spi_master_dma.hpp.in

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,19 @@ public:
7575
static modm::ResumableResult<void>
7676
transfer(const uint8_t *tx, uint8_t *rx, std::size_t length);
7777

78+
static void
79+
startTransfer(const uint8_t *tx, uint8_t *rx, std::size_t length);
80+
81+
template <class Wait>
82+
static void waitCompleted(Wait wait);
83+
static void waitCompleted() {
84+
waitCompleted([](){__NOP();});
85+
}
7886
private:
7987

8088
// needed for transfers where no RX or TX buffers are given
8189
static inline uint8_t dmaDummy { 0 };
8290
};
8391

8492
} // namespace modm::platform
85-
#define MODM_RP_SPI_MASTER{{ id }}_DMA_HPP
8693
#include "spi_master_{{ id }}_dma_impl.hpp"

src/modm/platform/spi/rp/spi_master_dma_impl.hpp.in

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
99
*/
1010
// ----------------------------------------------------------------------------
11-
12-
#ifndef MODM_RP_SPI_MASTER{{ id }}_DMA_HPP
13-
# error "Don't include this file directly, use 'spi_master_{{ id }}_dma.hpp' instead!"
14-
#endif
11+
#pragma once
12+
#include "spi_master_{{ id }}_dma.hpp"
1513

1614
template <class DmaChannelRx, class DmaChannelTx>
1715
template <class SystemClock, modm::baudrate_t baudrate, modm::percent_t tolerance>
@@ -48,6 +46,72 @@ modm::platform::SpiMaster{{ id }}_Dma<DmaChannelRx, DmaChannelTx>::transfer(uint
4846
return SpiMaster{{ id }}::transfer(data);
4947
}
5048

49+
template <class DmaChannelRx, class DmaChannelTx>
50+
void
51+
modm::platform::SpiMaster{{ id }}_Dma<DmaChannelRx, DmaChannelTx>::startTransfer(const uint8_t *tx,
52+
uint8_t *rx, std::size_t length)
53+
{
54+
if ( (!rx && !tx) || length == 0) {
55+
return;
56+
}
57+
if constexpr (Dma::RxChannel::mask == 0) {
58+
rx = nullptr;
59+
enableDreq(Dma::DreqTx);
60+
} else {
61+
enableDreq((tx ? Dma::DreqTx : 0)|(rx ? Dma::DreqRx : 0));
62+
}
63+
64+
if (tx) {
65+
Dma::TxChannel::setReadAddress(uint32_t(tx));
66+
Dma::TxChannel::setReadIncrementMode(true);
67+
} else {
68+
Dma::TxChannel::setReadAddress(uint32_t(&dmaDummy));
69+
Dma::TxChannel::setReadIncrementMode(false);
70+
}
71+
Dma::TxChannel::setDataLength(length);
72+
if constexpr (Dma::RxChannel::mask == 0) {
73+
Dma::TxChannel::start();
74+
} else {
75+
if (rx) {
76+
Dma::RxChannel::setWriteAddress(uint32_t(rx));
77+
Dma::RxChannel::setWriteIncrementMode(true);
78+
} else {
79+
Dma::RxChannel::setWriteAddress(uint32_t(&dmaDummy));
80+
Dma::RxChannel::setWriteIncrementMode(false);
81+
}
82+
Dma::RxChannel::setDataLength(length);
83+
::modm::platform::Dma::template start<typename Dma::RxChannel,typename Dma::TxChannel>();
84+
}
85+
86+
}
87+
88+
template <class DmaChannelRx, class DmaChannelTx>
89+
template <class Wait>
90+
void
91+
modm::platform::SpiMaster{{ id }}_Dma<DmaChannelRx, DmaChannelTx>::waitCompleted(Wait wait)
92+
{
93+
while (Dma::TxChannel::isBusy() or Dma::RxChannel::isBusy())
94+
wait();
95+
while (!txFifoEmpty() or isBusy())
96+
wait();
97+
if constexpr (Dma::RxChannel::mask == 0) {
98+
// Drain RX FIFO, then wait for shifting to finish (which may be *after*
99+
// TX FIFO drains), then drain RX FIFO again
100+
while (!rxFifoEmpty())
101+
(void)read();
102+
while (isBusy())
103+
wait();
104+
while (!rxFifoEmpty())
105+
(void)read();
106+
107+
// Don't leave overrun flag set
108+
spi{{ id }}_hw->icr = SPI_SSPICR_RORIC_BITS;
109+
} else {
110+
while (!rxFifoEmpty() or isBusy())
111+
wait();
112+
}
113+
}
114+
51115
template <class DmaChannelRx, class DmaChannelTx>
52116
modm::ResumableResult<void>
53117
modm::platform::SpiMaster{{ id }}_Dma<DmaChannelRx, DmaChannelTx>::transfer(const uint8_t *tx,
@@ -56,7 +120,7 @@ modm::platform::SpiMaster{{ id }}_Dma<DmaChannelRx, DmaChannelTx>::transfer(cons
56120
if ( (!rx && !tx) || length == 0) {
57121
return {modm::rf::Stop};
58122
}
59-
if (Dma::RxChannel::mask == 0) rx = nullptr;
123+
if constexpr (Dma::RxChannel::mask == 0) rx = nullptr;
60124
// this is a manually implemented "fast resumable function"
61125
// there is no context or nesting protection, since we don't need it.
62126
// there are only two states encoded into 1 bit (Bit1 of state):
@@ -69,27 +133,7 @@ modm::platform::SpiMaster{{ id }}_Dma<DmaChannelRx, DmaChannelTx>::transfer(cons
69133
case 0:
70134
// we will only visit this state once
71135
state |= Bit1;
72-
enableDreq((tx ? Dma::DreqTx : 0)|(rx ? Dma::DreqRx : 0));
73-
74-
if (tx) {
75-
Dma::TxChannel::setReadAddress(uint32_t(tx));
76-
Dma::TxChannel::setReadIncrementMode(true);
77-
} else {
78-
Dma::TxChannel::setReadAddress(uint32_t(&dmaDummy));
79-
Dma::TxChannel::setReadIncrementMode(false);
80-
}
81-
Dma::TxChannel::setDataLength(length);
82-
if (rx) {
83-
Dma::RxChannel::setWriteAddress(uint32_t(rx));
84-
Dma::RxChannel::setWriteIncrementMode(true);
85-
Dma::RxChannel::setDataLength(length);
86-
}
87-
88-
if (rx) {
89-
::modm::platform::Dma::template start<typename Dma::RxChannel,typename Dma::TxChannel>();
90-
} else {
91-
Dma::TxChannel::start();
92-
}
136+
startTransfer(tx,rx,length);
93137

94138
[[fallthrough]];
95139

src/modm/processing/fiber/scheduler.hpp.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ protected:
138138
static inline void
139139
registerFiber(Fiber* fiber,size_t core)
140140
{
141+
multicore::SystemSpinLockGuard g;
141142
if (core != multicore::Core::getNum())
142143
{
143-
multicore::SystemSpinLockGuard g;
144144
lookup[core]->registerFiber(fiber);
145145
return;
146146
}

0 commit comments

Comments
 (0)