Initial WIP ADC support.

Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
Yilin Sun 2023-03-16 09:42:03 +08:00
parent 4bf56bf36c
commit a2eb84f757
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
3 changed files with 129 additions and 1 deletions

View File

@ -65,6 +65,7 @@ set(TARGET_SOURCES
"src/app_aux_ctrl.c"
"src/app_mrb_repl.c"
"src/app_syscalls.c"
"src/mrb_machine_impl/mrb_machine_adc_impl.c"
"src/mrb_machine_impl/mrb_machine_gpio_impl.c"
"src/main.c"
)

@ -1 +1 @@
Subproject commit 12b520e7873432d7135f9de86330c000f8464873
Subproject commit 7f0aca015ec2bcad7d08d912163f135bdb238149

View File

@ -0,0 +1,127 @@
#include <stdio.h>
/* Board */
#include "board.h"
/* SDK drivers */
#include "fsl_anactrl.h"
#include "fsl_clock.h"
#include "fsl_gpio.h"
#include "fsl_iocon.h"
#include "fsl_lpadc.h"
#include "fsl_power.h"
/* FreeRTOS */
#include "FreeRTOS.h"
#include "semphr.h"
/* Gem private */
#include "machine-adc/src/adc.h"
#define ADC_IMPL_PORT(x) (x / 32)
#define ADC_IMPL_PIN(x) (x % 32)
#define ADC_EXT_CHANNEL_COUNT 10
#define ADC_TEMP_CHANNEL 26
/* CH0A, CH0B, CH1A, CH1B, ... CH4A, CH4B */
const static uint32_t s_adc_pin_table[ADC_EXT_CHANNEL_COUNT] = {
23, 16, 10, 11, 15, 12, 31, 32, 40, 41,
};
static bool s_adc_initialized = false;
static SemaphoreHandle_t s_adc_semaphore = NULL;
static void mrb_machine_adc_impl_init_peripheral(void) {
CLOCK_SetClkDiv(kCLOCK_DivAdcAsyncClk, 8, true);
CLOCK_AttachClk(kMAIN_CLK_to_ADC_CLK);
POWER_DisablePD(kPDRUNCFG_PD_LDOGPADC);
ANACTRL_Init(ANACTRL);
ANACTRL_EnableVref1V(ANACTRL, true);
lpadc_config_t adc_cfg;
LPADC_GetDefaultConfig(&adc_cfg);
adc_cfg.enableAnalogPreliminary = true;
adc_cfg.referenceVoltageSource = kLPADC_ReferenceVoltageAlt2;
adc_cfg.conversionAverageMode = kLPADC_ConversionAverage128;
LPADC_Init(ADC0, &adc_cfg);
LPADC_DoOffsetCalibration(ADC0);
LPADC_DoAutoCalibration(ADC0);
}
int mrb_machine_adc_impl_config(uint32_t pin) {
if (!s_adc_initialized) {
mrb_machine_adc_impl_init_peripheral();
s_adc_semaphore = xSemaphoreCreateBinary();
if (s_adc_semaphore == NULL) {
return -1;
}
s_adc_initialized = true;
}
uint32_t iocon_mode = IOCON_PIO_ASW(1);
/* Configure IOCON only if this is an external channel */
if (pin < ADC_EXT_CHANNEL_COUNT) {
IOCON_PinMuxSet(IOCON, ADC_IMPL_PORT(s_adc_pin_table[pin]), ADC_IMPL_PIN(s_adc_pin_table[pin]), iocon_mode);
}
return 0;
}
int mrb_machine_adc_impl_read(uint32_t pin) {
lpadc_conv_command_config_t conv_cfg;
lpadc_conv_trigger_config_t trig_cfg;
LPADC_GetDefaultConvCommandConfig(&conv_cfg);
LPADC_GetDefaultConvTriggerConfig(&trig_cfg);
conv_cfg.conversionResolutionMode = kLPADC_ConversionResolutionHigh;
if (pin < ADC_EXT_CHANNEL_COUNT) {
/* This is an external channel, Positive and negative pair shares the same channel */
lpadc_sample_channel_mode_t mode;
if ((pin % 2) == 0) {
mode = kLPADC_SampleChannelSingleEndSideA;
} else {
mode = kLPADC_SampleChannelSingleEndSideB;
}
conv_cfg.channelNumber = pin / 2;
conv_cfg.sampleChannelMode = mode;
} else if (pin == ADC_TEMP_CHANNEL) { /* Temperature channel requires differential sampling */
conv_cfg.channelNumber = pin;
conv_cfg.sampleChannelMode = kLPADC_SampleChannelDiffBothSide;
} else { /* Other internal channels */
conv_cfg.channelNumber = pin;
conv_cfg.sampleChannelMode = kLPADC_SampleChannelSingleEndSideA;
}
trig_cfg.targetCommandId = 15;
trig_cfg.enableHardwareTrigger = false;
LPADC_SetConvCommandConfig(ADC0, 15, &conv_cfg);
LPADC_SetConvTriggerConfig(ADC0, 0U, &trig_cfg);
LPADC_EnableInterrupts(ADC0, kLPADC_FIFO0WatermarkInterruptEnable);
EnableIRQ(ADC0_IRQn);
return 0;
}
void ADC0_IRQHandler(void) {
BaseType_t higher_priority_woken = pdFALSE;
xSemaphoreGiveFromISR(s_adc_semaphore, &higher_priority_woken);
if (higher_priority_woken) {
portYIELD_FROM_ISR(higher_priority_woken);
}
}