Skip to content
Snippets Groups Projects

ADC driver:

Merged Clément Foucher requested to merge cfoucher/core:adc_rework into main
24 files
+ 760
753
Compare changes
  • Side-by-side
  • Inline
Files
24
/*
* Copyright (c) 2021-2022 LAAS-CNRS
* Copyright (c) 2021-2023 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,7 +18,7 @@
*/
/**
* @date 2022
* @date 2023
*
* @author Clément Foucher <clement.foucher@laas.fr>
*/
@@ -28,7 +28,6 @@
#include <stm32_ll_adc.h>
// Current module private functions
#include "../src/adc_channels.h"
#include "../src/adc_core.h"
// Current file header
@@ -39,153 +38,203 @@
// Constants
#define NUMBER_OF_ADCS 4
#define NUMBER_OF_CHANNELS_PER_ADC 16
/////
// Local variables
static uint32_t adc_trigger_sources[NUMBER_OF_ADCS] = {0};
static uint32_t adc_discontinuous_mode[NUMBER_OF_ADCS] = {0};
static adc_ev_src_t adc_trigger_sources[NUMBER_OF_ADCS] = {software};
static uint32_t adc_discontinuous_mode[NUMBER_OF_ADCS] = {0};
static uint32_t enabled_channels_count[NUMBER_OF_ADCS] = {0};
static bool enable_dma[NUMBER_OF_ADCS] = {false};
static uint32_t enabled_channels[NUMBER_OF_ADCS][NUMBER_OF_CHANNELS_PER_ADC] = {0};
/////
// Public API
void adc_init()
void adc_configure_trigger_source(uint8_t adc_number, adc_ev_src_t trigger_source)
{
adc_core_init();
adc_channels_init();
if ( (adc_number == 0) || (adc_number > NUMBER_OF_ADCS) )
return;
adc_trigger_sources[adc_number-1] = trigger_source;
}
void adc_set_dual_mode(uint8_t dual_mode)
void adc_configure_discontinuous_mode(uint8_t adc_number, uint32_t discontinuous_count)
{
adc_core_set_dual_mode(dual_mode);
if ( (adc_number == 0) || (adc_number > NUMBER_OF_ADCS) )
return;
adc_discontinuous_mode[adc_number-1] = discontinuous_count;
}
void adc_configure_trigger_source(uint8_t adc_number, adc_ev_src_t trigger_source)
void adc_add_channel(uint8_t adc_number, uint8_t channel)
{
/////
// Convert to LL constants
if ( (adc_number == 0) || (adc_number > NUMBER_OF_ADCS) )
return;
uint32_t trig;
switch (trigger_source)
{
case hrtim_ev1:
trig = LL_ADC_REG_TRIG_EXT_HRTIM_TRG1;
break;
case hrtim_ev2:
trig = LL_ADC_REG_TRIG_EXT_HRTIM_TRG2;
break;
case hrtim_ev3:
trig = LL_ADC_REG_TRIG_EXT_HRTIM_TRG3;
break;
case hrtim_ev4:
trig = LL_ADC_REG_TRIG_EXT_HRTIM_TRG4;
break;
case software:
default:
trig = LL_ADC_REG_TRIG_SOFTWARE;
break;
}
uint8_t adc_index = adc_number-1;
// Only store configuration: it must be applied after ADC enable
if ( (adc_number > 0) && (adc_number <= NUMBER_OF_ADCS) )
{
adc_trigger_sources[adc_number-1] = trig;
}
if (enabled_channels_count[adc_index] == NUMBER_OF_CHANNELS_PER_ADC)
return;
enabled_channels[adc_index][enabled_channels_count[adc_index]] = channel;
enabled_channels_count[adc_index]++;
}
void adc_configure_discontinuous_mode(uint8_t adc_number, uint32_t dicontinuous_count)
void adc_remove_channel(uint8_t adc_number, uint8_t channel)
{
// Only store configuration: it must be applied after ADC enable
if ( (adc_number > 0) && (adc_number <= NUMBER_OF_ADCS) )
if ( (adc_number == 0) || (adc_number > NUMBER_OF_ADCS) )
return;
uint8_t adc_index = adc_number-1;
for (int i = 0 ; i < NUMBER_OF_CHANNELS_PER_ADC ; i++)
{
adc_discontinuous_mode[adc_number-1] = dicontinuous_count;
if (enabled_channels[adc_index][i] == channel)
{
for (int j = i ; j < NUMBER_OF_CHANNELS_PER_ADC-1 ; j++)
{
enabled_channels[adc_index][i] = enabled_channels[adc_index][i+1];
}
enabled_channels[adc_index][NUMBER_OF_CHANNELS_PER_ADC-1] = 0;
enabled_channels_count[adc_index]--;
break;
}
}
}
int8_t adc_configure_adc_channels(uint8_t adc_number, const char* channel_list[], uint8_t channel_count)
void adc_configure_use_dma(uint8_t adc_number, bool use_dma)
{
return adc_channnels_configure_adc_channels(adc_number, channel_list, channel_count);
if ( (adc_number == 0) || (adc_number > NUMBER_OF_ADCS) )
return;
enable_dma[adc_number-1] = use_dma;
}
void adc_start()
{
uint8_t enabled_channels_count[NUMBER_OF_ADCS];
/////
// Initialize ADCs
for (uint8_t i = 0 ; i < NUMBER_OF_ADCS ; i++)
{
enabled_channels_count[i] = adc_channels_get_enabled_channels_count(i+1);
}
adc_core_init();
/////
// Pre-enable configuration
// Nothing here for now.
// If some channels have to be set as differential,
// or ADCs have to be set as dual mode,
// this shoud be done here.
/////
// Enable ADCs
for (uint8_t i = 0 ; i < NUMBER_OF_ADCS ; i++)
for (int i = 1 ; i <= NUMBER_OF_ADCS ; i++)
{
if (enabled_channels_count[i] > 0)
{
adc_core_enable(i+1);
}
adc_core_enable(i);
}
/////
// Configure ADCs channels
for (uint8_t i = 0 ; i < NUMBER_OF_ADCS ; i++)
// Post-enable configuration
for (uint8_t adc_num = 1 ; adc_num <= NUMBER_OF_ADCS ; adc_num++)
{
if (enabled_channels_count[i] > 0)
uint8_t adc_index = adc_num-1;
if (enabled_channels_count[adc_index] > 0)
{
adc_channels_configure(i+1);
for (int channel_index = 0 ; channel_index < NUMBER_OF_CHANNELS_PER_ADC ; channel_index++)
{
if (enabled_channels[adc_index][channel_index] == 0)
break;
adc_core_configure_channel(adc_num, enabled_channels[adc_index][channel_index], channel_index+1);
}
}
}
/////
// Configure ADCs
for (uint8_t i = 0 ; i < NUMBER_OF_ADCS ; i++)
for (uint8_t adc_num = 1 ; adc_num <= NUMBER_OF_ADCS ; adc_num++)
{
if (enabled_channels_count[i] > 0)
uint8_t adc_index = adc_num-1;
if (enabled_channels_count[adc_index] > 0)
{
adc_core_configure_dma_mode(i+1);
adc_core_configure_dma_mode(adc_num, enable_dma[adc_index]);
}
}
for (uint8_t i = 0 ; i < NUMBER_OF_ADCS ; i++)
for (uint8_t adc_num = 1 ; adc_num <= NUMBER_OF_ADCS ; adc_num++)
{
if ( (enabled_channels_count[i] > 0) && (adc_discontinuous_mode[i] != 0) )
uint8_t adc_index = adc_num-1;
if (enabled_channels_count[adc_index] > 0)
{
adc_core_configure_discontinuous_mode(i+1, adc_discontinuous_mode[i]);
adc_core_configure_discontinuous_mode(adc_num, adc_discontinuous_mode[adc_index]);
}
}
for (uint8_t i = 0 ; i < NUMBER_OF_ADCS ; i++)
for (uint8_t adc_num = 1 ; adc_num <= NUMBER_OF_ADCS ; adc_num++)
{
if ( (enabled_channels_count[i] > 0) && (adc_trigger_sources[i] != 0) )
uint8_t adc_index = adc_num-1;
if (enabled_channels_count[adc_index] > 0)
{
adc_core_configure_trigger_source(i+1, LL_ADC_REG_TRIG_EXT_RISING, adc_trigger_sources[i]);
// Convert to LL constants
uint32_t trig;
switch (adc_trigger_sources[adc_index])
{
case hrtim_ev1:
trig = LL_ADC_REG_TRIG_EXT_HRTIM_TRG1;
break;
case hrtim_ev2:
trig = LL_ADC_REG_TRIG_EXT_HRTIM_TRG2;
break;
case hrtim_ev3:
trig = LL_ADC_REG_TRIG_EXT_HRTIM_TRG3;
break;
case hrtim_ev4:
trig = LL_ADC_REG_TRIG_EXT_HRTIM_TRG4;
break;
case software:
default:
trig = LL_ADC_REG_TRIG_SOFTWARE;
break;
}
adc_core_configure_trigger_source(adc_num, LL_ADC_REG_TRIG_EXT_RISING, trig);
}
}
/////
// Finally, start ADCs
for (uint8_t i = 0 ; i < NUMBER_OF_ADCS ; i++)
// Start ADCs
for (uint8_t adc_num = 1 ; adc_num <= NUMBER_OF_ADCS ; adc_num++)
{
if (enabled_channels_count[i] > 0)
uint8_t adc_index = adc_num-1;
if (enabled_channels_count[adc_index] > 0)
{
adc_core_start(i+1);
adc_core_start(adc_num, enabled_channels_count[adc_index]);
}
}
}
const char* adc_get_channel_name(uint8_t adc_number, uint8_t channel_rank)
void adc_stop()
{
return adc_channels_get_channel_name(adc_number, channel_rank);
for (uint8_t adc_num = 1 ; adc_num <= NUMBER_OF_ADCS ; adc_num++)
{
uint8_t adc_index = adc_num-1;
if (enabled_channels_count[adc_index] > 0)
{
adc_core_stop(adc_num);
}
}
}
uint8_t adc_get_enabled_channels_count(uint8_t adc_num)
void adc_trigger_software_conversion(uint8_t adc_number)
{
return adc_channels_get_enabled_channels_count(adc_num);
adc_core_start(adc_number, 1);
}
void adc_software_trigger_conversion(uint8_t adc_number)
{
adc_core_start(adc_number);
}
\ No newline at end of file
Loading