Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OwnTech
Power API
Core
Commits
6cf292ed
Commit
6cf292ed
authored
Mar 08, 2022
by
Clément Foucher
Browse files
Extract ADC configuration functions as an independent module.
parent
2618dd27
Changes
26
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
6cf292ed
...
...
@@ -25,20 +25,19 @@ The hierarchy of the project is as follows:
```
owntech_power_api
└─ boards
| └─ nucleo_g474re.json
└─ src
| └─ main.cpp
| └─ owntech.ini
└─ zephyr
| └─ d
t
s
| └─
boar
ds
| └─ modules
| └─ [...]
└─ LICENSE
└─ README.md
└─ [...]
```
You will want to work in the
`src`
folder, other folders and files are used to configure the underlying Zephyr OS.
You will want to work in the
`src`
folder, other folders and files are used to configure the underlying Zephyr OS
and PlatformIO
.
Power users may want to tweak them too. Is so, please checkout the
[
Zephyr documentation
](
https://docs.zephyrproject.org/latest/
)
.
In the
`src`
folder, the file
`main.cpp`
is the entry point of the application.
...
...
@@ -50,3 +49,4 @@ The file `owntech.ini` is used to configure the Power API Libraries you want to
To enable a Power API Library, edit the
`src/owntech.ini`
file.
In this file, you'll find various commented libraries references.
Simply uncomment a line to enable the corresponding library.
You can also add any PlatformIO library in this file.
zephyr/modules/owntech_adc_driver/zephyr/CMakeLists.txt
0 → 100644
View file @
6cf292ed
if
(
CONFIG_OWNTECH_ADC_DRIVER
)
# 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/adc_channels.c
./src/adc_core.c
./src/adc_helper.c
./public_api/adc.c
)
endif
()
zephyr/modules/owntech_adc_driver/zephyr/Kconfig
0 → 100644
View file @
6cf292ed
config OWNTECH_ADC_DRIVER
bool "Enable OwnTech ADC driver for STM32"
default y
depends on !ADC
zephyr/modules/owntech_adc_driver/zephyr/module.yml
0 → 100644
View file @
6cf292ed
name
:
owntech_adc_driver
build
:
cmake
:
zephyr
kconfig
:
zephyr/Kconfig
zephyr/modules/owntech_
data_acquisition/zephyr/adc
/adc.c
→
zephyr/modules/owntech_
adc_driver/zephyr/public_api
/adc.c
View file @
6cf292ed
...
...
@@ -24,15 +24,15 @@
*/
// Stdlib
#include <stdint.h>
// STM32 LL
#include <stm32g4xx_ll_adc.h>
// OwnTech API
#include "adc_channels.h"
#include "adc_core.h"
#include "../src/adc_channels.h"
#include "../src/adc_core.h"
// Current file header
#include "adc.h"
/////
...
...
@@ -81,7 +81,9 @@ void adc_start()
for
(
uint8_t
i
=
0
;
i
<
3
;
i
++
)
{
if
(
enabled_channels_count
[
i
]
>
0
)
{
adc_core_enable
(
i
+
1
);
}
}
/////
...
...
@@ -89,7 +91,9 @@ void adc_start()
for
(
uint8_t
i
=
0
;
i
<
3
;
i
++
)
{
if
(
enabled_channels_count
[
i
]
>
0
)
{
adc_channels_configure
(
i
+
1
);
}
}
/////
...
...
@@ -97,13 +101,17 @@ void adc_start()
for
(
uint8_t
i
=
0
;
i
<
3
;
i
++
)
{
if
(
enabled_channels_count
[
i
]
>
0
)
{
adc_core_configure_dma_mode
(
i
+
1
);
}
}
for
(
uint8_t
i
=
0
;
i
<
3
;
i
++
)
{
if
(
(
enabled_channels_count
[
i
]
>
0
)
&&
(
adc_trigger_sources
[
i
]
!=
0
)
)
{
adc_core_configure_trigger_source
(
i
+
1
,
LL_ADC_REG_TRIG_EXT_RISING
,
adc_trigger_sources
[
i
]);
}
}
/////
...
...
@@ -111,7 +119,9 @@ void adc_start()
for
(
uint8_t
i
=
0
;
i
<
3
;
i
++
)
{
if
(
enabled_channels_count
[
i
]
>
0
)
{
adc_core_start
(
i
+
1
);
}
}
}
...
...
@@ -119,3 +129,8 @@ const char* adc_get_channel_name(uint8_t adc_number, uint8_t channel_rank)
{
return
adc_channels_get_channel_name
(
adc_number
,
channel_rank
);
}
uint8_t
adc_get_enabled_channels_count
(
uint8_t
adc_num
)
{
return
adc_channels_get_enabled_channels_count
(
adc_num
);
}
zephyr/modules/owntech_
data_acquisition/zephyr/adc
/adc.h
→
zephyr/modules/owntech_
adc_driver/zephyr/public_api
/adc.h
View file @
6cf292ed
...
...
@@ -31,11 +31,6 @@
*
* To use this driver, first call adc_init(), then call
* required configuration functions, then call adc_start().
*
* This file is the entry point of the ADC management.
* Only this header file provides public functions for the
* ADC. No other header from this folder should be included
* in files outside this folder.
*/
...
...
@@ -43,6 +38,7 @@
#define ADC_H_
// Stdlib
#include <stdint.h>
...
...
@@ -95,6 +91,13 @@ void adc_configure_trigger_source(uint8_t adc_number, uint32_t trigger_source);
*/
int8_t
adc_configure_adc_channels
(
uint8_t
adc_number
,
const
char
*
channel_list
[],
uint8_t
channel_count
);
/**
* Get the number of enabled channels for an ADC.
* @param adc_num Number of the ADC
* @return Number of enabled channels in this ADC.
*/
uint8_t
adc_get_enabled_channels_count
(
uint8_t
adc_num
);
/**
* @brief Starts all configured ADCs.
*/
...
...
zephyr/modules/owntech_
data_acquisition
/zephyr/public_api/
data_acquisition
_error_codes.h
→
zephyr/modules/owntech_
adc_driver
/zephyr/public_api/
adc
_error_codes.h
View file @
6cf292ed
...
...
@@ -30,8 +30,6 @@
#define NOERROR 0
#define ECHANNOTFOUND -1
#define EALREADYSTARTED -2
#define ECHANUNCONF -3
#endif // DATAACQUISITONERRORCODES_H_
zephyr/modules/owntech_
data_acquisition
/zephyr/
ad
c/adc_channels.c
→
zephyr/modules/owntech_
adc_driver
/zephyr/
sr
c/adc_channels.c
View file @
6cf292ed
...
...
@@ -40,7 +40,7 @@
// OwnTech API
#include "adc_helper.h"
#include "
data_acquisition
_error_codes.h"
#include "
adc
_error_codes.h"
/////
...
...
zephyr/modules/owntech_
data_acquisition
/zephyr/
ad
c/adc_channels.h
→
zephyr/modules/owntech_
adc_driver
/zephyr/
sr
c/adc_channels.h
View file @
6cf292ed
File moved
zephyr/modules/owntech_
data_acquisition
/zephyr/
ad
c/adc_core.c
→
zephyr/modules/owntech_
adc_driver
/zephyr/
sr
c/adc_core.c
View file @
6cf292ed
File moved
zephyr/modules/owntech_
data_acquisition
/zephyr/
ad
c/adc_core.h
→
zephyr/modules/owntech_
adc_driver
/zephyr/
sr
c/adc_core.h
View file @
6cf292ed
File moved
zephyr/modules/owntech_
data_acquisition
/zephyr/
ad
c/adc_helper.c
→
zephyr/modules/owntech_
adc_driver
/zephyr/
sr
c/adc_helper.c
View file @
6cf292ed
File moved
zephyr/modules/owntech_
data_acquisition
/zephyr/
ad
c/adc_helper.h
→
zephyr/modules/owntech_
adc_driver
/zephyr/
sr
c/adc_helper.h
View file @
6cf292ed
File moved
zephyr/modules/owntech_data_acquisition/zephyr/CMakeLists.txt
View file @
6cf292ed
...
...
@@ -7,10 +7,6 @@ if(CONFIG_OWNTECH_DATA_ACQUISITION)
# Select source files to be compiled
zephyr_library_sources
(
./adc/adc.c
./adc/adc_channels.c
./adc/adc_core.c
./adc/adc_helper.c
./dma/dma.c
./data_dispatch/data_dispatch.c
./data_conversion/data_conversion.c
...
...
zephyr/modules/owntech_data_acquisition/zephyr/Kconfig
View file @
6cf292ed
...
...
@@ -2,4 +2,4 @@ config OWNTECH_DATA_ACQUISITION
bool "Enable OwnTech data acquisition using ADCs"
default y
select DMA
depends on
!ADC
depends on
OWNTECH_ADC_DRIVER
zephyr/modules/owntech_data_acquisition/zephyr/data_dispatch/data_dispatch.c
View file @
6cf292ed
/*
* Copyright (c) 2021 LAAS-CNRS
* Copyright (c) 2021
-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
...
...
@@ -18,6 +18,8 @@
*/
/**
* @date 2022
*
* @author Clément Foucher <clement.foucher@laas.fr>
*/
...
...
@@ -30,7 +32,7 @@
#include <zephyr.h>
// OwnTech API
#include "
../adc/adc_channels
.h"
#include "
adc
.h"
/////
...
...
@@ -105,7 +107,7 @@ void data_dispatch_init(uint8_t adc_count)
for
(
int
adc_index
=
0
;
adc_index
<
number_of_adcs
;
adc_index
++
)
{
enabled_channels_count
[
adc_index
]
=
adc_
channels_
get_enabled_channels_count
(
adc_index
+
1
);
enabled_channels_count
[
adc_index
]
=
adc_get_enabled_channels_count
(
adc_index
+
1
);
if
(
enabled_channels_count
[
adc_index
]
>
0
)
{
// Prepare arrays for each channel
...
...
zephyr/modules/owntech_data_acquisition/zephyr/dma/dma.c
View file @
6cf292ed
/*
* Copyright (c) 2021 LAAS-CNRS
* Copyright (c) 2021
-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
...
...
@@ -18,6 +18,10 @@
*/
/**
* @date 2022
*
* @author Clément Foucher <clement.foucher@laas.fr>
*
* @brief DMA configuration for OwnTech application.
* One DMA channel is assigned per ADC. For each ADC, the DMA
* has a buffer sized 2*(number of enabled channels in ADC),
...
...
@@ -26,8 +30,6 @@
* is available to data dispatch.
* DMA 1 is used for all acquisitions, with channel i
* acquiring values from ADC i.
*
* @author Clément Foucher <clement.foucher@laas.fr>
*/
...
...
@@ -42,8 +44,8 @@
#include <stm32g4xx_ll_dma.h>
// OwnTech API
#include "adc.h"
#include "../data_dispatch/data_dispatch.h"
#include "../adc/adc_channels.h"
/////
...
...
@@ -113,7 +115,7 @@ static void _dma_callback(const struct device* dev, void* user_data, uint32_t ch
static
void
_dma_channel_init
(
uint8_t
adc_num
,
uint32_t
source_address
,
uint32_t
source_trigger
)
{
// Prepare buffers
uint8_t
enabled_channels
=
adc_
channels_
get_enabled_channels_count
(
adc_num
);
uint8_t
enabled_channels
=
adc_get_enabled_channels_count
(
adc_num
);
size_t
dma_buffer_size
=
enabled_channels
*
sizeof
(
uint16_t
)
*
2
;
uint8_t
adc_index
=
adc_num
-
1
;
...
...
@@ -160,7 +162,7 @@ void dma_configure_and_start(uint8_t adc_count)
for
(
uint8_t
adc_index
=
0
;
adc_index
<
adc_count
;
adc_index
++
)
{
uint8_t
adc_num
=
adc_index
+
1
;
if
(
adc_
channels_
get_enabled_channels_count
(
adc_num
)
>
0
)
if
(
adc_get_enabled_channels_count
(
adc_num
)
>
0
)
{
_dma_channel_init
(
adc_num
,
source_registers
[
adc_index
],
source_triggers
[
adc_index
]);
dma_start
(
dma1
,
adc_num
);
...
...
zephyr/modules/owntech_data_acquisition/zephyr/public_api/DataAcquisition.cpp
View file @
6cf292ed
...
...
@@ -19,6 +19,7 @@
/**
* @date 2022
*
* @author Clément Foucher <clement.foucher@laas.fr>
* @author Luiz Villa <luiz.villa@laas.fr>
*/
...
...
@@ -27,15 +28,11 @@
// Stdlib
#include <string.h>
// STM32 LL
#include <stm32g4xx_ll_adc.h>
// OwnTech Power API
#include "
../adc/
adc.h"
#include "adc.h"
#include "../dma/dma.h"
#include "../data_dispatch/data_dispatch.h"
#include "../data_conversion/data_conversion.h"
#include "data_acquisition_error_codes.h"
// Current class header
#include "DataAcquisition.h"
...
...
@@ -50,10 +47,6 @@ DataAcquisition dataAcquisition;
/////
// Initialize static members
uint8_t
DataAcquisition
::
initialized
=
0
;
uint8_t
DataAcquisition
::
channels_configured
=
0
;
uint8_t
DataAcquisition
::
started
=
0
;
DataAcquisition
::
channel_assignment_t
DataAcquisition
::
v1_low_assignement
=
{
0
};
DataAcquisition
::
channel_assignment_t
DataAcquisition
::
v2_low_assignement
=
{
0
};
DataAcquisition
::
channel_assignment_t
DataAcquisition
::
v_high_assignement
=
{
0
};
...
...
@@ -64,22 +57,7 @@ DataAcquisition::channel_assignment_t DataAcquisition::temp_sensor_assignement =
/////
// Private members
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
);
}
}
// Public static configuration functions
void
DataAcquisition
::
setChannnelAssignment
(
uint8_t
adc_number
,
const
char
*
channel_name
,
uint8_t
channel_rank
)
{
...
...
@@ -120,184 +98,45 @@ void DataAcquisition::setChannnelAssignment(uint8_t adc_number, const char* cha
}
}
/////
// Public static configuration functions
int8_t
DataAcquisition
::
configureAdc12DualMode
(
uint8_t
dual_mode
)
{
/////
// Guard
if
(
started
==
1
)
{
return
EALREADYSTARTED
;
}
/////
// Make sure module is initialized
if
(
initialized
==
0
)
{
initialize
();
}
/////
// Proceed
adc_set_dual_mode
(
dual_mode
);
return
NOERROR
;
}
int8_t
DataAcquisition
::
configureAdcChannels
(
uint8_t
adc_number
,
const
char
*
channel_list
[],
uint8_t
channel_count
)
{
/////
// Guard
if
(
started
==
1
)
{
return
EALREADYSTARTED
;
}
/////
// Make sure module is initialized
if
(
initialized
==
0
)
{
initialize
();
}
/////
// Proceed
int8_t
result
=
adc_configure_adc_channels
(
adc_number
,
channel_list
,
channel_count
);
if
(
result
!=
0
)
{
return
result
;
}
for
(
int
rank
=
0
;
rank
<
channel_count
;
rank
++
)
{
setChannnelAssignment
(
adc_number
,
channel_list
[
rank
],
rank
);
}
channels_configured
=
1
;
return
NOERROR
;
}
int8_t
DataAcquisition
::
configureAdcTriggerSource
(
uint8_t
adc_number
,
adc_src_t
trigger_source
)
void
DataAcquisition
::
start
()
{
/////
// Guard
uint8_t
number_of_adcs
=
2
;
if
(
started
=
=
1
)
for
(
uint8_t
adc_num
=
1
;
adc_num
<=
number_of_adcs
;
adc_num
++
)
{
return
EALREADYSTARTED
;
}
uint8_t
channel_rank
=
0
;
while
(
1
)
{
const
char
*
channel_name
=
adc_get_channel_name
(
adc_num
,
channel_rank
);
if
(
channel_name
!=
NULL
)
{
setChannnelAssignment
(
adc_num
,
channel_name
,
channel_rank
);
channel_rank
++
;
}
else
{
break
;
}
}
/////
// Make sure module is initialized
if
(
initialized
==
0
)
{
initialize
();
}
/////
// 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
,
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
()
{
/////
// Guards
if
(
channels_configured
==
0
)
{
return
ECHANUNCONF
;
}
else
if
(
started
==
1
)
{
return
EALREADYSTARTED
;
}
/////
// Proceed
// DMAs
dma_configure_and_start
(
2
);
dma_configure_and_start
(
number_of_adcs
);
// Initialize data dispatch
data_dispatch_init
(
2
);
data_dispatch_init
(
number_of_adcs
);
// Launch ADC conversion
adc_start
();
started
=
1
;
return
NOERROR
;
}
/////
// Public static accessors
const
char
*
DataAcquisition
::
getChannelName
(
uint8_t
adc_number
,
uint8_t
channel_rank
)
{
return
adc_get_channel_name
(
adc_number
,
channel_rank
);
}
uint16_t
*
DataAcquisition
::
getV1LowRawValues
(
uint32_t
&
number_of_values_acquired
)
{
return
data_dispatch_get_acquired_values
(
v1_low_assignement
.
adc_number
,
v1_low_assignement
.
channel_rank
,
&
number_of_values_acquired
);
...
...
zephyr/modules/owntech_data_acquisition/zephyr/public_api/DataAcquisition.h
View file @
6cf292ed
...
...
@@ -19,6 +19,7 @@
/**
* @date 2022
*
* @author Clément Foucher <clement.foucher@laas.fr>
*/
...
...
@@ -34,13 +35,6 @@
#include <arm_math.h>
/////
// Public enums
typedef
enum
{
hrtim1
,
software
}
adc_src_t
;
/////
...
...
@@ -48,116 +42,30 @@ typedef enum
class
DataAcquisition
{
private:
/**
* This function initializes the Data Acquisition module.
*/
static
void
initialize
();
/**
* This function is used to indicate to the DataAcquisition module
* what the underlying ADC channel configuration is.
*
* @param adc_number ADC number
* @param channel_name Channel name
* @param channel_rannk Channel rank