Skip to content

Commit

Permalink
[driver] Add GpioSampler for IO analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
salkinium committed Jul 31, 2020
1 parent 339cbc7 commit 9d8bbfa
Show file tree
Hide file tree
Showing 7 changed files with 434 additions and 7 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,54 +198,55 @@ can easily configure them for you specific needs.
<td align="center">FT245</td>
</tr><tr>
<td align="center">FT6X06</td>
<td align="center">GPIO-SAMPLER</td>
<td align="center">HCLAx</td>
<td align="center">HD44780</td>
<td align="center">HMC58x</td>
<td align="center">HMC6343</td>
<td align="center">HX711</td>
</tr><tr>
<td align="center">HX711</td>
<td align="center">I2C-EEPROM</td>
<td align="center">ITG3200</td>
<td align="center">L3GD20</td>
<td align="center">LAWICEL</td>
<td align="center">LIS302DL</td>
<td align="center">LIS3DSH</td>
</tr><tr>
<td align="center">LIS3DSH</td>
<td align="center">LIS3MDL</td>
<td align="center">LM75</td>
<td align="center">LP503X</td>
<td align="center">LSM303A</td>
<td align="center">LSM6DS33</td>
<td align="center">LTC2984</td>
</tr><tr>
<td align="center">LTC2984</td>
<td align="center">MAX6966</td>
<td align="center">MAX7219</td>
<td align="center">MCP23X17</td>
<td align="center">MCP2515</td>
<td align="center">NOKIA5110</td>
<td align="center">NRF24</td>
</tr><tr>
<td align="center">NRF24</td>
<td align="center">TFT-DISPLAY</td>
<td align="center">PAT9125EL</td>
<td align="center">PCA8574</td>
<td align="center">PCA9535</td>
<td align="center">PCA9548A</td>
<td align="center">PCA9685</td>
</tr><tr>
<td align="center">PCA9685</td>
<td align="center">SIEMENS-S65</td>
<td align="center">SIEMENS-S75</td>
<td align="center">SK6812</td>
<td align="center">SK9822</td>
<td align="center">SSD1306</td>
<td align="center">SX1276</td>
</tr><tr>
<td align="center">SX1276</td>
<td align="center">TCS3414</td>
<td align="center">TCS3472</td>
<td align="center">TLC594X</td>
<td align="center">TMP102</td>
<td align="center">TMP175</td>
<td align="center">VL53L0</td>
</tr><tr>
<td align="center">VL53L0</td>
<td align="center">VL6180</td>
<td align="center">WS2812</td>
</tr>
Expand Down
126 changes: 126 additions & 0 deletions src/modm/driver/gpio/gpio_sampler.cpp.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2018, Niklas Hauser
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#include "gpio_sampler.hpp"
#include <modm/architecture/interface/interrupt.hpp>
#include <modm/platform.hpp>
#include <modm/debug/logger.hpp>

using IrqHandler = void(*)();
%% if vectors_location == "rom"
modm_fastdata
IrqHandler exti_vectors[{{ extis | length }}] = {nullptr};

%% for vector in extis
MODM_ISR({{ vector }})
{
exti_vectors[{{ loop.index0 }}]();
}
%% endfor
%% endif

const IRQn_Type
irq_map[{{ extis | length }}] =
{
%% for vector in extis
{{ vector }}_IRQn,
%% endfor
};

namespace modm
{

modm_fastdata
void *GpioSampler::context{nullptr};

void
GpioSampler::reset(Interrupt vector)
{
const size_t index = int(vector);
NVIC_DisableIRQ(irq_map[index]);
NVIC_SetPriority(irq_map[index], 0);
}

void
GpioSampler::setHandler(Interrupt vector, IrqHandler handler)
{
const size_t index = int(vector);
if (index >= {{ extis | length }}) return;
%% if vectors_location == "ram"
NVIC_SetVector(irq_map[index], (uint32_t) handler);
%% else
exti_vectors[index] = handler;
%% endif
NVIC_EnableIRQ(irq_map[index]);
}

GpioSampler::Channel::Channel()
{}
void
GpioSampler::Channel::allocate(size_t max_samples)
{
max_count = max_samples + 1;
data = new Type[max_samples + 1];
}
GpioSampler::Channel::~Channel()
{
delete[] data;
}

void
GpioSampler::Channel::reset()
{
count = 0;
}

void
GpioSampler::Channel::dump() const
{
for (size_t ii=0; ii<count; ii++) {
Type d = diff(ii);
MODM_LOG_DEBUG.printf("%3u %9ld %6ld (%ldus)\n", ii, (*this)[ii], d, int32_t(int64_t(d * 1000000) / modm::platform::fcpu));
}
MODM_LOG_DEBUG << modm::endl;
}

void
GpioSampler::Channel::add(Type time)
{
if (count < max_count) data[count++] = time;
}

const GpioSampler::Type&
GpioSampler::Channel::operator[](size_t index) const
{
return data[(index < count) ? index : (count - 1)];
}

bool
GpioSampler::Channel::read(size_t index) const
{
return ((*this)[index] > 0);
}

GpioSampler::Type
GpioSampler::Channel::diff(size_t index) const
{
if (index == 0) return 0;
Type s0 = (*this)[index - 1];
Type s1 = (*this)[index];
// abs
uint32_t t0 = (s0 > 0) ? s0 : -s0;
uint32_t t1 = (s1 > 0) ? s1 : -s1;
// Fix overflow issues
if (t1 < t0) t1 |= (1ul << 31);
return t1 - t0;
}

} // namespace modm::platform
111 changes: 111 additions & 0 deletions src/modm/driver/gpio/gpio_sampler.hpp.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (c) 2018, Niklas Hauser
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef MODM_TEST_LOGIC_ANALYZER_SAMPLER_HPP
#define MODM_TEST_LOGIC_ANALYZER_SAMPLER_HPP

#include <stdint.h>
#include <stddef.h>
#include <modm/platform/device.hpp>

namespace modm
{

class GpioSampler
{
public:
using Type = int32_t;

class Channel
{
friend class GpioSampler;
size_t max_count = 0;
volatile size_t count = 0;
Type *data = nullptr;
Channel();
void allocate(size_t max_samples);
void add(Type time);
void reset();

public:
~Channel();

inline size_t max() const { return max_count; }
inline size_t size() const { return count; }

void dump() const;

Type diff(size_t index) const;
bool read(size_t index) const;

const Type& operator[](size_t index) const;

inline const Type* begin() const { return data; }
inline const Type* end() const { return &data[count]; }
};

template<size_t channels>
class Handle
{
friend class GpioSampler;
using CleanupHandler = void(*)();
using StartHandler = void(*)(Handle<channels> &);

const CleanupHandler cleanup;
const StartHandler start;
Channel data[channels];

Handle(size_t max_samples, StartHandler start, CleanupHandler cleanup);
void set_start_time(const Type *start);
public:
static constexpr size_t Channels = channels;

public:
~Handle();

void
restart();

const Channel&
operator[](size_t channel) const;
};

template< class... Gpios >
static auto Create(size_t max_samples);

protected:
static void *context;

enum class
Interrupt : uint8_t
{
%% for vector in extis
{{ vector | capitalize }} = {{ loop.index0 }},
%% endfor
};

template< size_t channels, size_t pin_count, uint8_t pin, class Gpio, class... Gpios >
static void sampleGpio(Channel *data, Type time);
template< size_t channels, size_t pin_count, uint8_t pin >
static void sampleGpio(Channel *, Type) {}

static void reset(Interrupt vector);
static void setHandler(Interrupt vector, void(*handler)());
static inline Type getTime() {
return Type(DWT->CYCCNT & ~(1ul << 31));
}
};

} // namespace modm

#include "gpio_sampler_impl.hpp"

#endif // MODM_TEST_LOGIC_ANALYZER_SAMPLER_HPP
58 changes: 58 additions & 0 deletions src/modm/driver/gpio/gpio_sampler.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2018, Niklas Hauser
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from collections import OrderedDict

def init(module):
module.parent = ":driver"
module.name = "gpio_sampler"


def prepare(module, options):
if options[":target"].identifier["platform"] != "stm32":
return False

core = options[":target"].get_driver("core:cortex-m*")
# Cortex-M0 doesn't have the DWT->CYCCNT and Cortex-M7 support is broken
if not core or "m0" in core["type"] or "m7" in core["type"]:
return False

module.depends(
":platform:gpio",
":platform:core",
":architecture:interrupt")
return True


def build(env):
exti_vectors = [v["name"] for v in env[":target"].get_driver("core")["vector"] if "EXTI" in v["name"]]
# These are all exti possible vectors: 0, 0_1, 1, 15_10, 2, 2_3, 2_TSC, 3, 4, 4_15, 9_5
extimap = {
"0": [0], "1": [1], "2": [2], "3": [3], "4": [4],
"0_1": [0,1],
"2_TSC": [2],
"2_3": [2,3],
"4_15": [4,5,6,7,8,9,10,11,12,13,14,15],
"9_5": [5,6,7,8,9],
"15_10": [10,11,12,13,14,15],
}
extis = OrderedDict()
for v in sorted(exti_vectors):
extis[v] = extimap[v[4:]]

env.substitutions = {
"extis": extis,
"vectors_location": env.get(":platform:core:vector_table_location", "rom")
}
env.outbasepath = "modm/src/modm/driver"
env.template("gpio_sampler.cpp.in")
env.template("gpio_sampler.hpp.in")
env.template("gpio_sampler_impl.hpp.in")
Loading

0 comments on commit 9d8bbfa

Please sign in to comment.