fixes and start of ADC. Not really working yet
This commit is contained in:
@@ -7,7 +7,6 @@
|
||||
|
||||
#define OW_INTERNAL
|
||||
#include "_ow_internal.h"
|
||||
#include "_ow_init.h"
|
||||
|
||||
/** Allocate data structure and set defaults */
|
||||
error_t OW_preInit(Unit *unit)
|
||||
|
||||
@@ -27,9 +27,6 @@ struct priv {
|
||||
struct ow_search_state searchState;
|
||||
};
|
||||
|
||||
/** Allocate data structure and set defaults */
|
||||
error_t OW_preInit(Unit *unit);
|
||||
|
||||
/** Load from a binary buffer stored in Flash */
|
||||
void OW_loadBinary(Unit *unit, PayloadParser *pp);
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "_ow_search.h"
|
||||
#include "_ow_internal.h"
|
||||
#include "_ow_low_level.h"
|
||||
#include "_ow_checksum.h"
|
||||
#include "_ow_commands.h"
|
||||
|
||||
void ow_search_init(Unit *unit, uint8_t command, bool test_checksums)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#define OW_INTERNAL
|
||||
#include "_ow_internal.h"
|
||||
#include "_ow_settings.h"
|
||||
|
||||
/** Load from a binary buffer stored in Flash */
|
||||
void OW_loadBinary(Unit *unit, PayloadParser *pp)
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
// 1WIRE master
|
||||
#define OW_INTERNAL
|
||||
#include "_ow_internal.h"
|
||||
#include "_ow_init.h"
|
||||
#include "_ow_settings.h"
|
||||
#include "_ow_low_level.h"
|
||||
|
||||
/**
|
||||
|
||||
+222
-3
@@ -8,29 +8,241 @@
|
||||
#define ADC_INTERNAL
|
||||
#include "_adc_internal.h"
|
||||
|
||||
const uint32_t LL_ADC_SAMPLETIMES[] = {
|
||||
LL_ADC_SAMPLINGTIME_1CYCLE_5,
|
||||
LL_ADC_SAMPLINGTIME_7CYCLES_5,
|
||||
LL_ADC_SAMPLINGTIME_13CYCLES_5,
|
||||
LL_ADC_SAMPLINGTIME_28CYCLES_5,
|
||||
LL_ADC_SAMPLINGTIME_41CYCLES_5,
|
||||
LL_ADC_SAMPLINGTIME_55CYCLES_5,
|
||||
LL_ADC_SAMPLINGTIME_71CYCLES_5,
|
||||
LL_ADC_SAMPLINGTIME_239CYCLES_5,
|
||||
};
|
||||
|
||||
|
||||
/** Allocate data structure and set defaults */
|
||||
error_t UADC_preInit(Unit *unit)
|
||||
{
|
||||
struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv));
|
||||
if (priv == NULL) return E_OUT_OF_MEM;
|
||||
|
||||
//
|
||||
priv->channels = 1; // PA0
|
||||
priv->enable_tsense = false;
|
||||
priv->enable_vref = false;
|
||||
priv->sample_time = 0b010; // 13.5c
|
||||
priv->frequency = 4; //1000
|
||||
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
static void UADC_DMA_Handler(void *arg)
|
||||
{
|
||||
Unit *unit = arg;
|
||||
|
||||
dbg("ADC DMA ISR hit");
|
||||
assert_param(unit);
|
||||
struct priv *priv = unit->data;
|
||||
assert_param(priv);
|
||||
|
||||
const uint32_t isrsnapshot = priv->DMAx->ISR;
|
||||
|
||||
if (LL_DMA_IsActiveFlag_G(isrsnapshot, priv->dma_chnum)) {
|
||||
bool tc = LL_DMA_IsActiveFlag_TC(isrsnapshot, priv->dma_chnum);
|
||||
bool ht = LL_DMA_IsActiveFlag_HT(isrsnapshot, priv->dma_chnum);
|
||||
|
||||
// Here we have to either copy it somewhere else, or notify another thread (queue?)
|
||||
// that the data is ready for reading
|
||||
|
||||
if (ht) {
|
||||
uint16_t start = 0;
|
||||
uint16_t end = (uint16_t) (priv->dma_buffer_size / 2);
|
||||
// TODO handle first half
|
||||
LL_DMA_ClearFlag_HT(priv->DMAx, priv->dma_chnum);
|
||||
}
|
||||
|
||||
if (tc) {
|
||||
uint16_t start = (uint16_t) (priv->dma_buffer_size / 2);
|
||||
uint16_t end = (uint16_t) priv->dma_buffer_size;
|
||||
// TODO handle second half
|
||||
LL_DMA_ClearFlag_TC(priv->DMAx, priv->dma_chnum);
|
||||
}
|
||||
|
||||
if (LL_DMA_IsActiveFlag_TE(isrsnapshot, priv->dma_chnum)) {
|
||||
// this shouldn't happen - error
|
||||
dbg("ADC DMA TE!");
|
||||
LL_DMA_ClearFlag_TE(priv->DMAx, priv->dma_chnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Finalize unit set-up */
|
||||
error_t UADC_init(Unit *unit)
|
||||
{
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
//
|
||||
// Written for F072 which has only one ADC
|
||||
|
||||
TRY(rsc_claim(unit, R_ADC1));
|
||||
TRY(rsc_claim(unit, R_DMA1_1));
|
||||
TRY(rsc_claim(unit, R_TIM15));
|
||||
|
||||
priv->DMAx = DMA1;
|
||||
priv->DMA_CHx = DMA1_Channel1;
|
||||
priv->dma_chnum = 1;
|
||||
priv->ADCx = ADC1;
|
||||
priv->ADCx_Common = ADC1_COMMON;
|
||||
priv->TIMx = TIM15;
|
||||
|
||||
// ----------------------- CONFIGURE PINS --------------------------
|
||||
{
|
||||
// Claim and configure all analog pins
|
||||
priv->nb_channels = 0;
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
if (priv->channels & (1 << i)) {
|
||||
char c;
|
||||
uint8_t num;
|
||||
if (i <= 7) {
|
||||
c = 'A';
|
||||
num = i;
|
||||
}
|
||||
else if (i <= 9) {
|
||||
c = 'B';
|
||||
num = (uint8_t) (i - 8);
|
||||
}
|
||||
else {
|
||||
c = 'C';
|
||||
num = (uint8_t) (i - 10);
|
||||
}
|
||||
|
||||
TRY(rsc_claim_pin(unit, c, num));
|
||||
uint32_t ll_pin = hw_pin2ll(num, &suc);
|
||||
GPIO_TypeDef *port = hw_port2periph(c, &suc);
|
||||
assert_param(suc);
|
||||
|
||||
LL_GPIO_SetPinPull(port, ll_pin, LL_GPIO_PULL_NO);
|
||||
LL_GPIO_SetPinMode(port, ll_pin, LL_GPIO_MODE_ANALOG);
|
||||
priv->nb_channels++;
|
||||
}
|
||||
}
|
||||
if (priv->enable_tsense) priv->nb_channels++;
|
||||
if (priv->enable_vref) priv->nb_channels++;
|
||||
|
||||
if (priv->nb_channels == 0) {
|
||||
dbg("!! Need at least 1 channel");
|
||||
return E_BAD_CONFIG;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------- ENABLE CLOCKS --------------------------
|
||||
{
|
||||
// enable peripherals clock
|
||||
hw_periph_clock_enable(priv->ADCx);
|
||||
hw_periph_clock_enable(priv->TIMx);
|
||||
}
|
||||
|
||||
// ------------------- CONFIGURE THE TIMER --------------------------
|
||||
dbg("Setting up TIMER");
|
||||
{
|
||||
// Find suitable timer values
|
||||
uint16_t presc;
|
||||
uint32_t count;
|
||||
float real_freq;
|
||||
if (!solve_timer(PLAT_APB1_HZ, priv->frequency, true, &presc, &count,
|
||||
&real_freq)) {
|
||||
dbg("Failed to resolve timer params.");
|
||||
return E_BAD_VALUE;
|
||||
}
|
||||
dbg("Frequency error %d ppm, presc %d, count %d",
|
||||
(int) lrintf(1000000.0f * ((real_freq - priv->frequency) / (float)priv->frequency)), (int) presc, (int) count);
|
||||
|
||||
LL_TIM_SetPrescaler(priv->TIMx, (uint32_t) (presc - 1));
|
||||
LL_TIM_SetAutoReload(priv->TIMx, count - 1);
|
||||
LL_TIM_EnableARRPreload(priv->TIMx);
|
||||
LL_TIM_EnableUpdateEvent(priv->TIMx);
|
||||
LL_TIM_GenerateEvent_UPDATE(priv->TIMx); // load the prescaller value
|
||||
}
|
||||
|
||||
// --------------------- CONFIGURE THE ADC ---------------------------
|
||||
dbg("Setting up ADC");
|
||||
{
|
||||
// Calibrate the ADC
|
||||
dbg("Wait for calib");
|
||||
LL_ADC_StartCalibration(priv->ADCx);
|
||||
while (LL_ADC_IsCalibrationOnGoing(priv->ADCx)) {}
|
||||
dbg("ADC calibrated.");
|
||||
|
||||
uint32_t mask = 0;
|
||||
if (priv->enable_vref) mask |= LL_ADC_PATH_INTERNAL_VREFINT;
|
||||
if (priv->enable_tsense) mask |= LL_ADC_PATH_INTERNAL_TEMPSENSOR;
|
||||
LL_ADC_SetCommonPathInternalCh(priv->ADCx_Common, mask);
|
||||
LL_ADC_SetDataAlignment(priv->ADCx, LL_ADC_DATA_ALIGN_RIGHT);
|
||||
LL_ADC_SetResolution(priv->ADCx, LL_ADC_RESOLUTION_12B);
|
||||
LL_ADC_REG_SetDMATransfer(priv->ADCx, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
|
||||
|
||||
// configure channels
|
||||
LL_ADC_REG_SetSequencerChannels(priv->ADCx, priv->channels);
|
||||
if (priv->enable_tsense) LL_ADC_REG_SetSequencerChAdd(priv->ADCx, LL_ADC_CHANNEL_TEMPSENSOR);
|
||||
if (priv->enable_vref) LL_ADC_REG_SetSequencerChAdd(priv->ADCx, LL_ADC_CHANNEL_VREFINT);
|
||||
|
||||
LL_ADC_REG_SetTriggerSource(priv->ADCx, LL_ADC_REG_TRIG_EXT_TIM15_TRGO);
|
||||
|
||||
LL_ADC_SetSamplingTimeCommonChannels(priv->ADCx, LL_ADC_SAMPLETIMES[priv->sample_time]);
|
||||
|
||||
LL_ADC_Enable(priv->ADCx);
|
||||
}
|
||||
|
||||
// --------------------- CONFIGURE DMA -------------------------------
|
||||
dbg("Setting up DMA");
|
||||
{
|
||||
// The length must be a 2*multiple of the number of channels
|
||||
// this is a horrible way to do it but will work
|
||||
uint16_t itemcount = (uint16_t) (priv->nb_channels * (uint16_t) (UADC_DMA_MAX_BUF_LEN / (2 * priv->nb_channels)));
|
||||
priv->dma_buffer_size = (uint16_t) (itemcount * 2);
|
||||
dbg("DMA item count is %d (%d bytes)", itemcount, priv->dma_buffer_size);
|
||||
|
||||
priv->dma_buffer = malloc_ck(priv->dma_buffer_size);
|
||||
if (NULL == priv->dma_buffer) return E_OUT_OF_MEM;
|
||||
assert_param(((uint32_t) priv->dma_buffer & 3) == 0); // must be aligned
|
||||
|
||||
{
|
||||
LL_DMA_InitTypeDef init;
|
||||
LL_DMA_StructInit(&init);
|
||||
init.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
|
||||
|
||||
init.Mode = LL_DMA_MODE_CIRCULAR;
|
||||
init.NbData = itemcount;
|
||||
|
||||
init.PeriphOrM2MSrcAddress = (uint32_t) &priv->ADCx->DR;
|
||||
init.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD;
|
||||
init.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
|
||||
init.MemoryOrM2MDstAddress = (uint32_t) priv->dma_buffer;
|
||||
init.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD;
|
||||
init.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||
|
||||
assert_param(SUCCESS == LL_DMA_Init(priv->DMAx, priv->dma_chnum, &init));
|
||||
|
||||
irqd_attach(priv->DMA_CHx, UADC_DMA_Handler, unit);
|
||||
// Interrupt on transfer 1/2 and complete
|
||||
// We will capture the first and second half and send it while the other half is being filled.
|
||||
LL_DMA_EnableIT_HT(priv->DMAx, priv->dma_chnum);
|
||||
LL_DMA_EnableIT_TC(priv->DMAx, priv->dma_chnum);
|
||||
}
|
||||
|
||||
LL_DMA_EnableChannel(priv->DMAx, priv->dma_chnum);
|
||||
}
|
||||
|
||||
dbg("ADC inited, starting the timer ...");
|
||||
|
||||
// FIXME - temporary demo - counter start...
|
||||
LL_TIM_EnableCounter(priv->TIMx);
|
||||
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Tear down the unit */
|
||||
void UADC_deInit(Unit *unit)
|
||||
{
|
||||
@@ -38,7 +250,14 @@ void UADC_deInit(Unit *unit)
|
||||
|
||||
// de-init peripherals
|
||||
if (unit->status == E_SUCCESS ) {
|
||||
//
|
||||
//LL_ADC_DeInit(priv->ADCx);
|
||||
LL_ADC_CommonDeInit(priv->ADCx_Common);
|
||||
LL_TIM_DeInit(priv->TIMx);
|
||||
|
||||
irqd_detach(priv->DMAx, UADC_DMA_Handler);
|
||||
LL_DMA_DeInit(priv->DMAx, priv->dma_chnum);
|
||||
|
||||
free_ck(priv->dma_buffer);
|
||||
}
|
||||
|
||||
// Release all resources, deinit pins
|
||||
|
||||
@@ -14,10 +14,32 @@
|
||||
/** Private data structure */
|
||||
struct priv {
|
||||
// settings
|
||||
uint16_t channels; //!< bit flags (will be recorded in order 0-15)
|
||||
bool enable_tsense; //!< append a signal from the temperature channel (voltage proportional to Tj)
|
||||
bool enable_vref; //!< append a signal from the internal voltage reference
|
||||
uint8_t sample_time; //!< 0-7 (corresponds to 1.5-239.5 cycles) - time for the sampling capacitor to charge
|
||||
uint32_t frequency; //!< Timer frequency in Hz. Note: not all frequencies can be achieved accurately
|
||||
|
||||
// TODO averaging (maybe a separate component?)
|
||||
// TODO threshold watchdog with hysteresis (maybe a separate component?)
|
||||
// TODO trigger level, edge direction, hold-off, pre-trigger buffer (extract from the DMA buffer)
|
||||
|
||||
// internal state
|
||||
ADC_TypeDef *ADCx;
|
||||
ADC_Common_TypeDef *ADCx_Common;
|
||||
TIM_TypeDef *TIMx;
|
||||
DMA_TypeDef *DMAx;
|
||||
uint8_t dma_chnum;
|
||||
DMA_Channel_TypeDef *DMA_CHx;
|
||||
uint16_t *dma_buffer;
|
||||
uint8_t nb_channels; // nr of enabled adc channels
|
||||
uint16_t dma_buffer_size; // real number of bytes
|
||||
};
|
||||
|
||||
// max size of the DMA buffer. The actual buffer size will be adjusted to accommodate
|
||||
// an even number of sample groups (sets of channels)
|
||||
#define UADC_DMA_MAX_BUF_LEN 512
|
||||
|
||||
/** Allocate data structure and set defaults */
|
||||
error_t UADC_preInit(Unit *unit);
|
||||
|
||||
|
||||
@@ -16,7 +16,11 @@ void UADC_loadBinary(Unit *unit, PayloadParser *pp)
|
||||
uint8_t version = pp_u8(pp);
|
||||
(void)version;
|
||||
|
||||
//
|
||||
priv->channels = pp_u16(pp);
|
||||
priv->enable_tsense = pp_bool(pp);
|
||||
priv->enable_vref = pp_bool(pp);
|
||||
priv->sample_time = pp_u8(pp);
|
||||
priv->frequency = pp_u32(pp);
|
||||
}
|
||||
|
||||
/** Write to a binary buffer for storing in Flash */
|
||||
@@ -26,7 +30,11 @@ void UADC_writeBinary(Unit *unit, PayloadBuilder *pb)
|
||||
|
||||
pb_u8(pb, 0); // version
|
||||
|
||||
//
|
||||
pb_u16(pb, priv->channels);
|
||||
pb_bool(pb, priv->enable_tsense);
|
||||
pb_bool(pb, priv->enable_vref);
|
||||
pb_u8(pb, priv->sample_time);
|
||||
pb_u32(pb, priv->frequency);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@@ -37,8 +45,21 @@ error_t UADC_loadIni(Unit *unit, const char *key, const char *value)
|
||||
bool suc = true;
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
if (false) {
|
||||
//
|
||||
if (streq(key, "channels")) {
|
||||
priv->channels = parse_pinmask(value, &suc);
|
||||
}
|
||||
else if (streq(key, "enable_tsense")) {
|
||||
priv->enable_tsense = str_parse_yn(value, &suc);
|
||||
}
|
||||
else if (streq(key, "enable_vref")) {
|
||||
priv->enable_vref = str_parse_yn(value, &suc);
|
||||
}
|
||||
else if (streq(key, "sample_time")) {
|
||||
priv->sample_time = (uint8_t) avr_atoi(value);
|
||||
if (priv->sample_time > 7) return E_BAD_VALUE;
|
||||
}
|
||||
else if (streq(key, "frequency")) {
|
||||
priv->frequency = (uint32_t) avr_atoi(value);
|
||||
}
|
||||
else {
|
||||
return E_BAD_KEY;
|
||||
@@ -53,6 +74,20 @@ void UADC_writeIni(Unit *unit, IniWriter *iw)
|
||||
{
|
||||
struct priv *priv = unit->data;
|
||||
|
||||
//
|
||||
iw_comment(iw, "Enabled channels, comma separated");
|
||||
iw_comment(iw, "0-7 = A0-A7, 8-9 = B0-B1, 10-15 = C0-C5");
|
||||
iw_entry(iw, "channels", "%s", pinmask2str_up(priv->channels, unit_tmp512));
|
||||
|
||||
iw_comment(iw, "Enable Tsense channel");
|
||||
iw_entry(iw, "enable_tsense", str_yn(priv->enable_tsense));
|
||||
|
||||
iw_comment(iw, "Enable Vref channel");
|
||||
iw_entry(iw, "enable_vref", str_yn(priv->enable_tsense));
|
||||
|
||||
iw_comment(iw, "Sampling time (0-7)");
|
||||
iw_entry(iw, "sample_time", "%d", (int)priv->sample_time);
|
||||
|
||||
iw_comment(iw, "Sampling frequency (Hz)");
|
||||
iw_entry(iw, "frequency", "%d", (int)priv->frequency);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
enum TplCmd_ {
|
||||
//
|
||||
CMD_DUMMY,
|
||||
};
|
||||
|
||||
/** Handle a request message */
|
||||
@@ -28,7 +28,7 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
|
||||
/** Unit template */
|
||||
const UnitDriver UNIT_ADC = {
|
||||
.name = "ADC",
|
||||
.description = "Template unit",
|
||||
.description = "Analog inputs",
|
||||
// Settings
|
||||
.preInit = UADC_preInit,
|
||||
.cfgLoadBinary = UADC_loadBinary,
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
#define DIN_INTERNAL
|
||||
#include "_din_internal.h"
|
||||
#include "_din_init.h"
|
||||
#include "_din_exti.h"
|
||||
|
||||
/** Allocate data structure and set defaults */
|
||||
error_t DIn_preInit(Unit *unit)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#define DIN_INTERNAL
|
||||
#include "_din_internal.h"
|
||||
#include "_din_settings.h"
|
||||
|
||||
/** Load from a binary buffer stored in Flash */
|
||||
void DIn_loadBinary(Unit *unit, PayloadParser *pp)
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
#define DIN_INTERNAL
|
||||
#include "_din_internal.h"
|
||||
#include "_din_settings.h"
|
||||
#include "_din_init.h"
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#define DOUT_INTERNAL
|
||||
#include "_dout_internal.h"
|
||||
#include "_dout_init.h"
|
||||
|
||||
/** Allocate data structure and set defaults */
|
||||
error_t DOut_preInit(Unit *unit)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#define DOUT_INTERNAL
|
||||
#include "_dout_internal.h"
|
||||
#include "_dout_settings.h"
|
||||
|
||||
/** Load from a binary buffer stored in Flash */
|
||||
void DOut_loadBinary(Unit *unit, PayloadParser *pp)
|
||||
|
||||
@@ -118,8 +118,8 @@ error_t UI2C_init(Unit *unit)
|
||||
TRY(rsc_claim_pin(unit, portname, pin_sda));
|
||||
TRY(rsc_claim_pin(unit, portname, pin_scl));
|
||||
|
||||
hw_configure_gpio_af(portname, pin_sda, af_i2c);
|
||||
hw_configure_gpio_af(portname, pin_scl, af_i2c);
|
||||
TRY(hw_configure_gpio_af(portname, pin_sda, af_i2c));
|
||||
TRY(hw_configure_gpio_af(portname, pin_scl, af_i2c));
|
||||
|
||||
hw_periph_clock_enable(priv->periph);
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#define I2C_INTERNAL
|
||||
#include "_i2c_internal.h"
|
||||
#include "_i2c_settings.h"
|
||||
|
||||
/** Load from a binary buffer stored in Flash */
|
||||
void UI2C_loadBinary(Unit *unit, PayloadParser *pp)
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
error_t Npx_preInit(Unit *unit)
|
||||
{
|
||||
struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv));
|
||||
if (priv == NULL)
|
||||
if (priv == NULL) return E_OUT_OF_MEM;
|
||||
|
||||
// some defaults
|
||||
priv->pin_number = 0;
|
||||
// some defaults
|
||||
priv->pin_number = 0;
|
||||
priv->port_name = 'A';
|
||||
priv->pixels = 1;
|
||||
|
||||
|
||||
@@ -132,9 +132,9 @@ error_t USPI_init(Unit *unit)
|
||||
TRY(rsc_claim_pin(unit, spi_portname, pin_miso));
|
||||
TRY(rsc_claim_pin(unit, spi_portname, pin_sck));
|
||||
|
||||
hw_configure_gpio_af(spi_portname, pin_mosi, af_spi);
|
||||
hw_configure_gpio_af(spi_portname, pin_miso, af_spi);
|
||||
hw_configure_gpio_af(spi_portname, pin_sck, af_spi);
|
||||
TRY(hw_configure_gpio_af(spi_portname, pin_mosi, af_spi));
|
||||
TRY(hw_configure_gpio_af(spi_portname, pin_miso, af_spi));
|
||||
TRY(hw_configure_gpio_af(spi_portname, pin_sck, af_spi));
|
||||
|
||||
// configure SSN GPIOs
|
||||
{
|
||||
|
||||
@@ -112,7 +112,7 @@ static void bw_dump(struct bulk_write *bulk, const uint8_t *chunk, uint32_t len)
|
||||
}
|
||||
|
||||
dbg("\r\nBulk write at %d, len %d", (int)bulk->offset, (int)len);
|
||||
PUTSN((const char *) chunk, len);
|
||||
PUTSN((const char *) chunk, (uint16_t) len);
|
||||
PUTS("\r\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -190,7 +190,6 @@ error_t UUSART_SetupDMAs(Unit *unit)
|
||||
LL_DMA_EnableChannel(priv->dma, priv->dma_rx_chnum);
|
||||
LL_DMA_EnableChannel(priv->dma, priv->dma_tx_chnum);
|
||||
|
||||
// TODO also set up usart timeout interrupt that grabs whatever is in the DMA buffer and sends it
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -205,7 +204,7 @@ static void UUSART_DMA_RxHandler(void *arg)
|
||||
struct priv *priv = unit->data;
|
||||
assert_param(priv);
|
||||
|
||||
uint32_t isrsnapshot = priv->dma->ISR;
|
||||
const uint32_t isrsnapshot = priv->dma->ISR;
|
||||
|
||||
if (LL_DMA_IsActiveFlag_G(isrsnapshot, priv->dma_rx_chnum)) {
|
||||
bool tc = LL_DMA_IsActiveFlag_TC(isrsnapshot, priv->dma_rx_chnum);
|
||||
@@ -228,6 +227,7 @@ static void UUSART_DMA_RxHandler(void *arg)
|
||||
|
||||
if (LL_DMA_IsActiveFlag_TE(isrsnapshot, priv->dma_rx_chnum)) {
|
||||
// this shouldn't happen
|
||||
dbg("USART DMA TE!");
|
||||
LL_DMA_ClearFlag_TE(priv->dma, priv->dma_rx_chnum);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//
|
||||
// Created by MightyPork on 2018/01/14.
|
||||
//
|
||||
#include <platform/irq_dispatcher.h>
|
||||
#include "platform.h"
|
||||
#include "unit_base.h"
|
||||
|
||||
@@ -25,7 +24,7 @@ error_t UUSART_preInit(Unit *unit)
|
||||
priv->baudrate = 115200;
|
||||
priv->parity = 0; //!< 0-none, 1-odd, 2-even
|
||||
priv->stopbits = 1; //!< 0-half, 1-one, 2-1.5, 3-two
|
||||
priv->direction = 3; // RXTX
|
||||
priv->direction = UUSART_DIRECTION_RXTX; // RXTX
|
||||
|
||||
priv->hw_flow_control = false;
|
||||
priv->clock_output = false;
|
||||
@@ -205,7 +204,7 @@ static inline error_t UUSART_configPins(Unit *unit)
|
||||
if (pins_wanted[i]) {
|
||||
if (mappings[i].port == 0) return E_BAD_CONFIG;
|
||||
TRY(rsc_claim_pin(unit, mappings[i].port, mappings[i].pin));
|
||||
hw_configure_gpio_af(mappings[i].port, mappings[i].pin, mappings[i].af);
|
||||
TRY(hw_configure_gpio_af(mappings[i].port, mappings[i].pin, mappings[i].af));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,9 +251,9 @@ error_t UUSART_init(Unit *unit)
|
||||
: LL_USART_STOPBITS_2);
|
||||
|
||||
LL_USART_SetTransferDirection(priv->periph,
|
||||
priv->direction == 1 ? LL_USART_DIRECTION_RX :
|
||||
priv->direction == 2 ? LL_USART_DIRECTION_TX
|
||||
: LL_USART_DIRECTION_TX_RX);
|
||||
(priv->direction == UUSART_DIRECTION_RX) ? LL_USART_DIRECTION_RX :
|
||||
(priv->direction == UUSART_DIRECTION_TX) ? LL_USART_DIRECTION_TX
|
||||
: LL_USART_DIRECTION_TX_RX);
|
||||
|
||||
LL_USART_SetHWFlowCtrl(priv->periph,
|
||||
priv->hw_flow_control == 0 ? LL_USART_HWCONTROL_NONE :
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
#define UUSART_RXBUF_LEN 128
|
||||
#define UUSART_TXBUF_LEN 128
|
||||
|
||||
#define UUSART_DIRECTION_RX 1
|
||||
#define UUSART_DIRECTION_TX 2
|
||||
#define UUSART_DIRECTION_RXTX 3
|
||||
|
||||
/** Private data structure */
|
||||
struct priv {
|
||||
uint8_t periph_num; //!< 1-6
|
||||
|
||||
@@ -104,9 +104,9 @@ error_t UUSART_loadIni(Unit *unit, const char *key, const char *value)
|
||||
}
|
||||
else if (streq(key, "direction")) {
|
||||
priv->direction = (uint8_t) str_parse_3(value,
|
||||
"RX", 1,
|
||||
"TX", 2,
|
||||
"RXTX", 3, &suc);
|
||||
"RX", UUSART_DIRECTION_RX,
|
||||
"TX", UUSART_DIRECTION_TX,
|
||||
"RXTX", UUSART_DIRECTION_RXTX, &suc);
|
||||
}
|
||||
else if (streq(key, "hw-flow-control")) {
|
||||
priv->hw_flow_control = (uint8_t) str_parse_4(value,
|
||||
|
||||
Reference in New Issue
Block a user