Commit b8a73032 authored by Clément Foucher's avatar Clément Foucher
Browse files

Integrate hardware configuration as a module.

parent f86ebf35
description: CAN Standby Switch
description: GPIO-controllable device
compatible: "can-standby-switch"
compatible: "gpio-device"
child-binding:
description: CAN Stanby GPIO node
description: GPIO node
properties:
can-standby-gpios:
gpios:
type: phandle-array
required: true
label:
......
description: Neutral-Ground Switch
compatible: "ngnd-switch"
child-binding:
description: Neutral-Ground GPIO node
properties:
ngnd-gpios:
type: phandle-array
required: true
label:
required: true
type: string
description: Human readable string describing the device (used as device_get_binding() argument)
......@@ -6,10 +6,10 @@
/ {
can-standby-switch {
compatible = "can-standby-switch";
compatible = "gpio-device";
label = "CAN_STANDBY";
can-standby-gpio-pin {
can-standby-gpios = <&gpiob 10 GPIO_ACTIVE_HIGH>;
gpios = <&gpiob 10 GPIO_ACTIVE_HIGH>;
label = "CAN Standby output";
};
};
......
......@@ -6,10 +6,10 @@
/ {
ngnd: ngnd-switch {
compatible = "ngnd-switch";
compatible = "gpio-device";
label = "NGND";
ngnd-gpio-pin {
ngnd-gpios = <&gpiob 11 GPIO_ACTIVE_HIGH>;
gpios = <&gpiob 11 GPIO_ACTIVE_HIGH>;
label = "Neutral to GND shunt";
};
};
......
......@@ -7,54 +7,6 @@
/ {
soc {
pinctrl: pin-controller@48000000 {
hrtim1_cha1_pa8: hrtim1_cha1_pa8 {
pinmux = <STM32_PINMUX('A', 8, AF13)>;
};
hrtim1_cha2_pa9: hrtim1_cha2_pa9 {
pinmux = <STM32_PINMUX('A', 9, AF13)>;
};
hrtim1_chb1_pa10: hrtim1_chb1_pa10 {
pinmux = <STM32_PINMUX('A', 10, AF13)>;
};
hrtim1_chb2_pa11: hrtim1_chb2_pa11 {
pinmux = <STM32_PINMUX('A', 11, AF13)>;
};
hrtim1_chc1_pb12: hrtim1_chc1_pb12 {
pinmux = <STM32_PINMUX('B', 12, AF13)>;
};
hrtim1_chc2_pb13: hrtim1_chc2_pb13 {
pinmux = <STM32_PINMUX('B', 13, AF13)>;
};
hrtim1_chd1_pb14: hrtim1_chd1_pb14 {
pinmux = <STM32_PINMUX('B', 14, AF13)>;
};
hrtim1_chd2_pb15: hrtim1_chd2_pb15 {
pinmux = <STM32_PINMUX('B', 15, AF13)>;
};
hrtim1_che1_pc8: hrtim1_che1_pc8 {
pinmux = <STM32_PINMUX('C', 8, AF3)>;
};
hrtim1_che2_pc9: hrtim1_che2_pc9 {
pinmux = <STM32_PINMUX('C', 9, AF3)>;
};
hrtim1_chf1_pc6: hrtim1_chf1_pc6 {
pinmux = <STM32_PINMUX('C', 6, AF13)>;
};
hrtim1_chf2_pc7: hrtim1_chf2_pc7 {
pinmux = <STM32_PINMUX('C', 7, AF13)>;
};
tim4_etr_pb3: tim4_etr_pb3 {
pinmux = <STM32_PINMUX('B', 3, AF2)>;
};
......
......@@ -6,6 +6,5 @@ if(CONFIG_OWNTECH_DAC_DRIVER)
# Select source files to be compiled
zephyr_library_sources(
./src/stm32_dac_driver.c
./src/owntech_dac_configure.c
)
endif()
config OWNTECH_DAC_DRIVER
bool "Enable OwnTech DAC driver"
default y
depends on !DAC
......@@ -64,10 +64,10 @@ typedef struct
uint32_t step_data;
} dac_function_config_t;
typedef struct
typedef enum
{
uint32_t pin_connect;
uint32_t pin_buffer_enable;
dac_pin_internal,
dac_pin_external
} dac_pin_config_t;
......@@ -78,7 +78,7 @@ typedef void (*dac_api_setconstvalue) (const struct device* dev, uint8_t channel
typedef void (*dac_api_setfunction) (const struct device* dev, uint8_t channel, const dac_function_config_t* config);
typedef void (*dac_api_fn_upd_reset) (const struct device* dev, uint8_t channel, uint32_t reset_data);
typedef void (*dac_api_fn_upd_step) (const struct device* dev, uint8_t channel, uint32_t step_data);
typedef void (*dac_api_pinconfigure) (const struct device* dev, uint8_t channel, const dac_pin_config_t* config);
typedef void (*dac_api_pinconfigure) (const struct device* dev, uint8_t channel, dac_pin_config_t config);
typedef void (*dac_api_start) (const struct device* dev, uint8_t channel);
typedef void (*dac_api_stop) (const struct device* dev, uint8_t channel);
......@@ -121,7 +121,7 @@ static inline void dac_function_update_step(const struct device* dev, uint8_t ch
api->fn_upd_step(dev, channel, step_data);
}
static inline void dac_pin_configure(const struct device* dev, uint8_t channel, const dac_pin_config_t* pin_config)
static inline void dac_pin_configure(const struct device* dev, uint8_t channel, dac_pin_config_t pin_config)
{
const struct dac_driver_api* api = (const struct dac_driver_api*)(dev->api);
......@@ -145,7 +145,6 @@ static inline void dac_stop(const struct device* dev, uint8_t channel)
/////
// Owntech-specific config
void owntech_dac_dac2_constant_init();
void owntech_dac_dac1_dac3_current_mode_init();
......
......@@ -183,14 +183,21 @@ static void dac_stm32_function_update_step(const struct device* dev, uint8_t cha
}
}
static void dac_stm32_pin_configure(const struct device* dev, uint8_t channel, const dac_pin_config_t* pin_config)
static void dac_stm32_pin_configure(const struct device* dev, uint8_t channel, dac_pin_config_t pin_config)
{
struct stm32_dac_driver_data* data = (struct stm32_dac_driver_data*)dev->data;
DAC_TypeDef* dac_dev = data->dac_struct;
uint8_t dac_channel = __LL_DAC_DECIMAL_NB_TO_CHANNEL(channel);
LL_DAC_ConfigOutput(dac_dev, dac_channel, LL_DAC_OUTPUT_MODE_NORMAL, pin_config->pin_buffer_enable, pin_config->pin_connect);
if (pin_config == dac_pin_internal)
{
LL_DAC_ConfigOutput(dac_dev, dac_channel, LL_DAC_OUTPUT_MODE_NORMAL, LL_DAC_OUTPUT_BUFFER_DISABLE, LL_DAC_OUTPUT_CONNECT_INTERNAL);
}
else if (pin_config == dac_pin_external)
{
LL_DAC_ConfigOutput(dac_dev, dac_channel, LL_DAC_OUTPUT_MODE_NORMAL, LL_DAC_OUTPUT_BUFFER_ENABLE, LL_DAC_OUTPUT_CONNECT_GPIO);
}
}
static void dac_stm32_start(const struct device* dev, uint8_t channel)
......
......@@ -50,7 +50,6 @@ typedef enum
dac_mode_function
} dac_mode_t;
struct stm32_dac_driver_data
{
DAC_TypeDef* dac_struct;
......@@ -70,7 +69,7 @@ static void dac_stm32_set_const_value(const struct device* dev, uint8_t channel,
static void dac_stm32_set_function(const struct device* dev, uint8_t channel, const dac_function_config_t* function_config);
static void dac_stm32_function_update_reset(const struct device* dev, uint8_t channel, uint32_t reset_data);
static void dac_stm32_function_update_step(const struct device* dev, uint8_t channel, uint32_t step_data);
static void dac_stm32_pin_configure(const struct device* dev, uint8_t channel, const dac_pin_config_t* pin_config);
static void dac_stm32_pin_configure(const struct device* dev, uint8_t channel, dac_pin_config_t pin_config);
static void dac_stm32_start(const struct device* dev, uint8_t channel);
static void dac_stm32_stop(const struct device* dev, uint8_t channel);
......
if(CONFIG_OWNTECH_DATA_ACQUISITION)
# Select directory to add to the include path
zephyr_include_directories(./public_api)
# Define the current folder as a Zephyr library
zephyr_library()
# Select source files to be compiled
zephyr_library_sources(
./adc/adc.c
./adc/adc_channels.c
......
config OWNTECH_DATA_ACQUISITION
bool "Enable OwnTech data acquisition using ADCs"
default y
select DMA
depends on !ADC
......@@ -27,6 +27,9 @@
// Stdlib
#include <string.h>
// STM32 LL
#include <stm32g4xx_ll_adc.h>
// OwnTech Power API
#include "../adc/adc.h"
#include "../dma/dma.h"
......@@ -67,8 +70,14 @@ void DataAcquisition::initialize()
{
if (initialized == 0)
{
// Initialize the ADCs
adc_init();
initialized = 1;
// Perform default configration
configureAdcTriggerSource(1, hrtim1);
configureAdcTriggerSource(2, hrtim1);
configureAdcTriggerSource(3, software);
}
}
......@@ -115,7 +124,7 @@ void DataAcquisition::setChannnelAssignment(uint8_t adc_number, const char* cha
/////
// Public static configuration functions
int8_t DataAcquisition::setAdc12DualMode(uint8_t dual_mode)
int8_t DataAcquisition::configureAdc12DualMode(uint8_t dual_mode)
{
/////
// Guard
......@@ -179,7 +188,7 @@ int8_t DataAcquisition::configureAdcChannels(uint8_t adc_number, const char* cha
return NOERROR;
}
int8_t DataAcquisition::configureAdcTriggerSource(uint8_t adc_number, uint32_t trigger_source)
int8_t DataAcquisition::configureAdcTriggerSource(uint8_t adc_number, adc_src_t trigger_source)
{
/////
// Guard
......@@ -199,12 +208,55 @@ int8_t DataAcquisition::configureAdcTriggerSource(uint8_t adc_number, uint32_t t
/////
// Proceed
uint32_t trig;
switch (trigger_source)
{
case hrtim1:
trig = LL_ADC_REG_TRIG_EXT_HRTIM_TRG1;
break;
case software:
default:
trig = LL_ADC_REG_TRIG_SOFTWARE;
break;
}
adc_configure_trigger_source(adc_number, trigger_source);
adc_configure_trigger_source(adc_number, trig);
return NOERROR;
}
int8_t DataAcquisition::configureAdcDefaultAllMeasurements()
{
uint8_t init_status;
uint8_t number_of_channels_adc1 = 3;
uint8_t number_of_channels_adc2 = 3;
const char* adc1_channels[] =
{
"V1_LOW",
"V2_LOW",
"V_HIGH"
};
const char* adc2_channels[] =
{
"I1_LOW",
"I2_LOW",
"I_HIGH"
};
init_status = dataAcquisition.configureAdcChannels(1, adc1_channels, number_of_channels_adc1);
if (init_status != NOERROR)
{
return init_status;
}
init_status = dataAcquisition.configureAdcChannels(2, adc2_channels, number_of_channels_adc2);
return NOERROR;
}
int8_t DataAcquisition::start()
{
......
......@@ -34,6 +34,15 @@
#include <arm_math.h>
/////
// Public enums
typedef enum
{
hrtim1,
software
} adc_src_t;
/////
// Static class definition
......@@ -56,21 +65,23 @@ public:
/**
* Use this function to set ADC 1 and ADC 2 in dual mode.
* By default, ADC 1 and 2 are not in dual mode.
*
* This function must be called BEFORE DataAcquisition::start().
* This function must be called BEFORE dataAcquisition.start().
*
* @param dual_mode Status of the dual mode: true to enable,
* false to disable. false by default.
* @param dual_mode Status of the dual mode:
* true to enable,
* false to disable.
* @return 0 is everything went well,
* EALREADYSTARTED if the module has already been started.
*/
static int8_t setAdc12DualMode(uint8_t dual_mode);
static int8_t configureAdc12DualMode(uint8_t dual_mode);
/**
* This function is used to configure the channels to be
* enabled on a given ADC.
*
* This function must be called BEFORE DataAcquisition::start().
* This function must be called BEFORE dataAcquisition.start().
*
* @param adc_number Number of the ADC on which channel configuration is
* to be done.
......@@ -88,19 +99,32 @@ public:
static int8_t configureAdcChannels(uint8_t adc_number, const char* channel_list[], uint8_t channel_count);
/**
* This function is used to configure the trigger source of an ADC.
*
* This function must be called BEFORE DataAcquisition::start().
* This function is used to change the trigger source of an ADC.
* By default, triggger source for ADC 1 and ADC 2 is on HRTIM1,
* and ADC 3 is software-triggered.
*
* TODO: Use an enumeration instead of LL constants for source.
* This function must be called BEFORE dataAcquisition.start().
*
* @param adc_number Number of the ADC to configure
* @param trigger_source Source of the trigger as defined
* in stm32gxx_ll_adc.h (LL_ADC_REG_TRIG_***)
* @param trigger_source Source of the trigger
* @return 0 is everything went well,
* EALREADYSTARTED if the module has already been started.
*/
static int8_t configureAdcTriggerSource(uint8_t adc_number, adc_src_t trigger_source);
/**
* This function is used to configure all ADC channels in default configuration.
* Channels will be attributed as follows:
* ADC1 - V1_LOW ADC2 - I1_LOW
* V2_LOW I2_LOW
* V_HIGH I_HIGH
*
* This function must be called BEFORE dataAcquisition.start().
*
* @return 0 is everything went well,
* EALREADYSTARTED if the module has already been started.
*/
static int8_t configureAdcTriggerSource(uint8_t adc_number, uint32_t trigger_source);
static int8_t configureAdcDefaultAllMeasurements();
/**
* This functions starts the acquisition chain. It must be called
......
if(CONFIG_OWNTECH_VREFBUF_DRIVER)
if(CONFIG_OWNTECH_HARDWARE_CONFIGURATION)
# Select directory to add to the include path
zephyr_include_directories(./public_api)
# Define the current folder as a Zephyr library
zephyr_library()
# Select source files to be compiled
zephyr_library_sources(
./src/vrefbuf_driver.c
src/hardware_auto_configuration.cpp
src/dac_configuration.cpp
src/ngnd_configuration.cpp
src/led_configuration.cpp
src/timer_configuration.cpp
public_api/HardwareConfiguration.cpp
)
endif()
config OWNTECH_HARDWARE_CONFIGURATION
bool "Enable OwnTech hardware configuration module"
default y
depends on OWNTECH_DAC_DRIVER
depends on OWNTECH_NGND_DRIVER
depends on OWNTECH_TIMER_DRIVER
name: owntech_vrefbuf_driver
name: owntech_hardware_configuration
build:
cmake: zephyr
kconfig: zephyr/Kconfig
/*
* Copyright (c) 2022 LAAS-CNRS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGLPV2.1
*/
/**
* @date 2022
* @author Clément Foucher <clement.foucher@laas.fr>
*/
// OwnTech headers
#include "../src/dac_configuration.h"
#include "../src/ngnd_configuration.h"
#include "../src/led_configuration.h"
#include "../src/timer_configuration.h"
// Current class header
#include "HardwareConfiguration.h"
/////
// Public object to interact with the class
HardwareConfiguration hwConfig;
/////
// Public static configuration functions
/////
// DAC
void HardwareConfiguration::initDac1Dac3CurrentMode()
{
dac_config_dac1_dac3_current_mode_init();
}
/////
// NGND
void HardwareConfiguration::setNgndOn()
{
ngnd_config_on();
}
void HardwareConfiguration::setNgndOff()
{
ngnd_config_off();
}
/////
// LED
void HardwareConfiguration::setLedOn()
{
led_config_on();
}
void HardwareConfiguration::setLedOff()
{
led_config_off();
}
void HardwareConfiguration::setLedToggle()
{
led_config_toggle();
}
// Incremental encoder
void HardwareConfiguration::startLoggingIncrementalEncoder()
{
timer_incremental_encoder_tim4_start();
}
uint32_t HardwareConfiguration::getIncrementalEncoderValue()
{
return timer_incremental_encoder_tim4_get_step();
}
/*
* Copyright (c) 2022 LAAS-CNRS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGLPV2.1
*/
/**
* @date 2022
* @author Clément Foucher <clement.foucher@laas.fr>
*/
#ifndef HARDWARECONFIGURATION_H_
#define HARDWARECONFIGURATION_H_
#include <stdint.h>
/////
// Static class definition
class HardwareConfiguration
{
public:
// DAC
void initDac1Dac3CurrentMode();
// NGND
void setNgndOn();
void setNgndOff();
// LED
vo