Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds IO board target for the L432KC nucleo #489

Merged
merged 16 commits into from
Dec 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ namespace openlcb
/// - the generated cdi.xml will include this data
/// - the Simple Node Ident Info Protocol will return this data
/// - the ACDI memory space will contain this data.
extern const SimpleNodeStaticValues SNIP_STATIC_DATA = {
4, "OpenMRN", "Test IO Board - STM32F303RE Nucleo",
"STM32F091RC-Nucleo", "1.01"};
extern const SimpleNodeStaticValues SNIP_STATIC_DATA = {4, "OpenMRN", //
"Test IO Board - STM32L432KC Nucleo", //
"STM32L432KC-Nucleo", //
"1.01"};

#define NUM_OUTPUTS 1
#define NUM_INPUTS 1
#define NUM_OUTPUTS 5
#define NUM_INPUTS 4

/// Declares a repeated group of a given base group and number of repeats. The
/// ProducerConfig and ConsumerConfig groups represent the configuration layout
Expand All @@ -38,7 +39,7 @@ using AllProducers = RepeatedGroup<ProducerConfig, NUM_INPUTS>;

/// Modify this value every time the EEPROM needs to be cleared on the node
/// after an update.
static constexpr uint16_t CANONICAL_VERSION = 0x184a;
static constexpr uint16_t CANONICAL_VERSION = 0x1844;

/// Defines the main segment in the configuration CDI. This is laid out at
/// origin 128 to give space for the ACDI user data at the beginning.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@

// These preprocessor symbols are used to select which physical connections
// will be enabled in the main(). See @ref appl_main below.
#define SNIFF_ON_SERIAL
//#define SNIFF_ON_SERIAL
//#define SNIFF_ON_USB
//#define HAVE_PHYSICAL_CAN_PORT
#define HAVE_PHYSICAL_CAN_PORT

// Changes the default behavior by adding a newline after each gridconnect
// packet. Makes it easier for debugging the raw device.
Expand Down Expand Up @@ -81,13 +81,45 @@ extern const char *const openlcb::CONFIG_FILENAME = "/dev/eeprom";
// The size of the memory space to export over the above device.
extern const size_t openlcb::CONFIG_FILE_SIZE =
cfg.seg().size() + cfg.seg().offset();
static_assert(openlcb::CONFIG_FILE_SIZE <= 300, "Need to adjust eeprom size");
static_assert(openlcb::CONFIG_FILE_SIZE <= 512, "Need to adjust eeprom size");
// The SNIP user-changeable information in also stored in the above eeprom
// device. In general this could come from different eeprom segments, but it is
// simpler to keep them together.
extern const char *const openlcb::SNIP_DYNAMIC_FILENAME =
openlcb::CONFIG_FILENAME;

// Object that handles factory reset for our config setup.
class CustomFactoryReset : public DefaultConfigUpdateListener {
public:
void factory_reset(int fd) override
{
// Resets user names.
cfg.userinfo().name().write(fd, "Default user name");
cfg.userinfo().description().write(fd, "Default user description");
// Makes the IO pin descriptions with default value.
cfg.seg().consumers().entry<0>().description().write(fd, "LD3");
cfg.seg().consumers().entry<1>().description().write(fd, "D3");
cfg.seg().consumers().entry<2>().description().write(fd, "D4");
cfg.seg().consumers().entry<3>().description().write(fd, "D5");
cfg.seg().consumers().entry<4>().description().write(fd, "D6");

cfg.seg().producers().entry<0>().description().write(fd, "A0");
cfg.seg().producers().entry<1>().description().write(fd, "A1");
cfg.seg().producers().entry<2>().description().write(fd, "A2");
cfg.seg().producers().entry<3>().description().write(fd, "A3");
for (unsigned i = 0; i < cfg.seg().producers().num_repeats(); ++i) {
cfg.seg().producers().entry(i).debounce().write(fd, 3);
}
}

UpdateAction apply_configuration(
int fd, bool initial_load, BarrierNotifiable *done) override {
done->notify();
// Nothing to do; we don't read the configuration.
return UPDATED;
}
} g_custom_factory_reset;

// Instantiates the actual producer and consumer objects for the given GPIO
// pins from above. The ConfiguredConsumer class takes care of most of the
// complicated setup and operation requirements. We need to give it the virtual
Expand All @@ -99,16 +131,35 @@ extern const char *const openlcb::SNIP_DYNAMIC_FILENAME =
// own GPIO pin.
openlcb::ConfiguredConsumer consumer_green(
stack.node(), cfg.seg().consumers().entry<0>(), LED_GREEN_Pin());
openlcb::ConfiguredConsumer consumer_d3(
stack.node(), cfg.seg().consumers().entry<1>(), OUT_D3_Pin());
openlcb::ConfiguredConsumer consumer_d4(
stack.node(), cfg.seg().consumers().entry<2>(), OUT_D4_Pin());
openlcb::ConfiguredConsumer consumer_d5(
stack.node(), cfg.seg().consumers().entry<3>(), OUT_D5_Pin());
openlcb::ConfiguredConsumer consumer_d6(
stack.node(), cfg.seg().consumers().entry<4>(), OUT_D6_Pin());

// Similar syntax for the producers.
openlcb::ConfiguredProducer producer_sw1(
stack.node(), cfg.seg().producers().entry<0>(), SW_USER_Pin());
openlcb::ConfiguredProducer producer_a0(
stack.node(), cfg.seg().producers().entry<0>(), IN_A0_Pin());
openlcb::ConfiguredProducer producer_a1(
stack.node(), cfg.seg().producers().entry<1>(), IN_A1_Pin());
openlcb::ConfiguredProducer producer_a2(
stack.node(), cfg.seg().producers().entry<2>(), IN_A2_Pin());
openlcb::ConfiguredProducer producer_a3(
stack.node(), cfg.seg().producers().entry<3>(), IN_A3_Pin());

// The producers need to be polled repeatedly for changes and to execute the
// debouncing algorithm. This class instantiates a refreshloop and adds the two
// producers to it.
openlcb::RefreshLoop loop(
stack.node(), {producer_sw1.polling()});
openlcb::RefreshLoop loop(stack.node(),
{
producer_a0.polling(), //
producer_a1.polling(), //
producer_a2.polling(), //
producer_a3.polling() //
});

/** Entry point to application.
* @param argc number of command line arguments
Expand Down
3 changes: 2 additions & 1 deletion boards/st-stm32l432kc-nucleo/HwInit.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ static Stm32Uart uart0("/dev/ser0", USART2, USART2_IRQn);
static Stm32Can can0("/dev/can0");

/** EEPROM emulation driver. The file size might be made bigger. */
//static Stm32EEPROMEmulation eeprom0("/dev/eeprom", 512);
static Stm32EEPROMEmulation eeprom0("/dev/eeprom", 512);

const size_t EEPROMEmulation::SECTOR_SIZE = 2048;
const bool EEPROMEmulation::SHADOW_IN_RAM = true;

extern "C" {

Expand Down
15 changes: 14 additions & 1 deletion boards/st-stm32l432kc-nucleo/hardware.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,20 @@

GPIO_PIN(LED_GREEN_RAW, LedPin, B, 3);

typedef GpioInitializer<LED_GREEN_RAW_Pin> GpioInit;
GPIO_PIN(IN_A0, GpioInputPU, A, 0);
GPIO_PIN(IN_A1, GpioInputPU, A, 1);
GPIO_PIN(IN_A2, GpioInputPU, A, 3);
GPIO_PIN(IN_A3, GpioInputPU, A, 4);

GPIO_PIN(OUT_D3, GpioOutputSafeLow, B, 0);
GPIO_PIN(OUT_D4, GpioOutputSafeLow, B, 7);
GPIO_PIN(OUT_D5, GpioOutputSafeLow, B, 6);
GPIO_PIN(OUT_D6, GpioOutputSafeLow, B, 1);

typedef GpioInitializer<LED_GREEN_RAW_Pin, //
IN_A0_Pin, IN_A1_Pin, IN_A2_Pin, IN_A3_Pin, //
OUT_D3_Pin, OUT_D4_Pin, OUT_D5_Pin, OUT_D6_Pin>
GpioInit;

typedef LED_GREEN_RAW_Pin BLINKER_RAW_Pin;
typedef BLINKER_Pin LED_GREEN_Pin;
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,6 @@ CXXSRCS += Stm32Can.cxx \
Stm32Uart.cxx \
Stm32SPI.cxx \
Stm32I2C.cxx \
Stm32EEPROMEmulation.cxx \


# does not work yet
# Stm32EEPROMEmulation.cxx

Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,5 @@ CXXSRCS += Stm32Can.cxx \
Stm32Uart.cxx \
Stm32SPI.cxx \
Stm32I2C.cxx \


# does not work yet
# Stm32EEPROMEmulation.cxx
Stm32EEPROMEmulation.cxx \