Skip to content

Commit

Permalink
[example] Add delay measurement example
Browse files Browse the repository at this point in the history
  • Loading branch information
salkinium committed Jun 13, 2021
1 parent 91cdf5c commit 72087a5
Showing 1 changed file with 90 additions and 2 deletions.
92 changes: 90 additions & 2 deletions examples/nucleo_f303k8/blink/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,104 @@

using namespace Board;


namespace modm
{

inline void
delay_ns_inl(uint32_t ns)
{
volatile uint32_t cycles;
// ns_per_loop = nanoseconds per cycle times cycles per loop ({{loop}} cycles)
asm volatile (
".syntax unified \n\t"
".align 4 \n\t"
"muls.n %[ovhd], %[ovhd], %[dnpl] \n\t" // multiply the overhead cycles with the ns per cycle: 1-2 cycles on cm3, up to 32 cycles on cm0
"subs.n %[cyc], %[cyc], %[ovhd] \n\t" // subtract the overhead in ns from the input: 1 cycle
"1: subs.n %[cyc], %[cyc], %[dnpl] \n\t" // subtract the ns per loop from the input: 1 cycle
"bpl.n 1b" // keep doing that while result is still positive: 2 cycles (when taken)
: [cyc] "=l" (cycles) : "0" (ns), [dnpl] "l" (platform::delay_ns_per_loop), [ovhd] "l" (2));
}

}

void run_delay_inl(uint32_t ns)
{
__DSB(); __ISB();
GpioA4::toggle();
const uint32_t start = DWT->CYCCNT;
modm::delay_ns_inl(ns);
const uint32_t stop = DWT->CYCCNT;
GpioA4::toggle();
const uint32_t cycles = (stop - start);
const uint32_t expected = uint64_t(SystemCoreClock) * ns / 1'000'000'000ull;
const uint32_t real = cycles * 1'000'000'000ull / SystemCoreClock;
MODM_LOG_INFO.printf("%7lu | %5lu | %5lu | %7lu %c\n",
ns, expected, cycles, real, (cycles < (expected*1.1f) ? ' ' : 'x')) << modm::flush;
}

void run_delay(uint32_t ns)
{
__DSB(); __ISB();
GpioA4::toggle();
const uint32_t start = DWT->CYCCNT;
modm::delay_ns(ns);
const uint32_t stop = DWT->CYCCNT;
GpioA4::toggle();
const uint32_t cycles = (stop - start);
const uint32_t expected = uint64_t(SystemCoreClock) * ns / 1'000'000'000ull;
const uint32_t real = cycles * 1'000'000'000ull / SystemCoreClock;
MODM_LOG_INFO.printf("%7lu | %5lu | %5lu | %7lu %c\n",
ns, expected, cycles, real, (cycles < (expected*1.1f) ? ' ' : 'x')) << modm::flush;
}

int
main()
{
Board::initialize();
GpioA4::setOutput();

MODM_LOG_INFO << "\n\ndelay_ns in RAM, 3 cycles per loop\n\n";
MODM_LOG_INFO << " delay | expect | cycles | real \n";

run_delay(1);
run_delay(5);
run_delay(10);
run_delay(50);
run_delay(100);
run_delay(200);
run_delay(400);
run_delay(600);
run_delay(800);
run_delay(1000);
run_delay(1500);
run_delay(2000);
run_delay(10'000);
run_delay(100'000);
run_delay(1'000'000);

MODM_LOG_INFO << "\n\ndelay_ns inlined in Flash, 6 cycles per loop\n\n";
MODM_LOG_INFO << " delay | expect | cycles | real \n";
modm::platform::delay_ns_per_loop = std::round(6000/64);

run_delay_inl(1);
run_delay_inl(5);
run_delay_inl(10);
run_delay_inl(50);
run_delay_inl(100);
run_delay_inl(200);
run_delay_inl(400);
run_delay_inl(600);
run_delay_inl(800);
run_delay_inl(1000);
run_delay_inl(1500);
run_delay_inl(2000);
run_delay_inl(10'000);
run_delay_inl(100'000);
run_delay_inl(1'000'000);

while (true)
{
GpioA4::toggle();
modm::delay_ns(100000);
}

return 0;
Expand Down

0 comments on commit 72087a5

Please sign in to comment.