Skip to content

Commit

Permalink
pmc: Dummy ADC read on startup
Browse files Browse the repository at this point in the history
pmc: Disable floating point ADC read functions at compile time
pmc: Fix signed/unsigned integer temperature compensation
pmc: Remove floating point math from SERCOM functions
pmc: Remove floating point math from WDT functions

Signed-off-by: João Silva <jgc3silva@gmail.com>
  • Loading branch information
vankxr committed Apr 24, 2024
1 parent 446c2b2 commit 0173f36
Show file tree
Hide file tree
Showing 8 changed files with 405 additions and 360 deletions.
213 changes: 114 additions & 99 deletions software/pmc/src/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,17 @@ void adc_init()
ADC_REGS->ADC_REFCTRL = ADC_REFCTRL_REFCOMP_Msk | ADC_REFCTRL_REFSEL_INT1V;
ADC_REGS->ADC_CTRLB = ADC_CTRLB_PRESCALER_DIV4 | ADC_CTRLB_RESSEL_12BIT;
ADC_REGS->ADC_CTRLA = ADC_CTRLA_ENABLE_Msk;
ADC_REGS->ADC_INPUTCTRL = ADC_INPUTCTRL_GAIN_1X | ADC_INPUTCTRL_MUXNEG_IOGND | ADC_INPUTCTRL_MUXPOS_BANDGAP;
ADC_REGS->ADC_SAMPCTRL = ADC_SAMPCTRL_SAMPLEN(0x3F);

while(ADC_REGS->ADC_STATUS & ADC_STATUS_SYNCBUSY_Msk);

// Do a dummy read
ADC_REGS->ADC_SWTRIG = ADC_SWTRIG_START_Msk;

while(!(ADC_REGS->ADC_INTFLAG & ADC_INTFLAG_RESRDY_Msk));

REG_DISCARD(&(ADC_REGS->ADC_RESULT));
}

static uint16_t adc_read_iovdd()
Expand All @@ -43,19 +52,6 @@ static uint16_t adc_read_iovdd()

return usResult;
}
uint32_t adc_get_iovdd()
{
uint16_t usResult = adc_read_iovdd();

return (uint32_t)usResult * 1000UL * 4UL / 4095UL;
}
float adc_getf_iovdd()
{
uint16_t usResult = adc_read_iovdd();
static const float fCorr = 1000.f / 4095.f * 4.f;

return (float)usResult * fCorr;
}
static uint16_t adc_read_corevdd()
{
ADC_REGS->ADC_INPUTCTRL = ADC_INPUTCTRL_GAIN_1X | ADC_INPUTCTRL_MUXNEG_GND | ADC_INPUTCTRL_MUXPOS_SCALEDCOREVCC;
Expand All @@ -71,19 +67,6 @@ static uint16_t adc_read_corevdd()

return usResult;
}
uint32_t adc_get_corevdd()
{
uint16_t usResult = adc_read_corevdd();

return (uint32_t)usResult * 1000UL * 4UL / 4095UL;
}
float adc_getf_corevdd()
{
uint16_t usResult = adc_read_corevdd();
static const float fCorr = 1000.f / 4095.f * 4.f;

return (float)usResult * fCorr;
}
static uint16_t adc_read_vbus()
{
ADC_REGS->ADC_INPUTCTRL = ADC_INPUTCTRL_GAIN_1X | ADC_INPUTCTRL_MUXNEG_GND | ADC_INPUTCTRL_MUXPOS(ADC_VBUS_VSENSE_CHAN);
Expand All @@ -99,19 +82,6 @@ static uint16_t adc_read_vbus()

return usResult;
}
uint32_t adc_get_vbus()
{
uint16_t usResult = adc_read_vbus();

return (uint64_t)usResult * 1000UL * (ADC_VBUS_VSENSE_DIV_RT + ADC_VBUS_VSENSE_DIV_RB) / (ADC_VBUS_VSENSE_DIV_RB * 4095UL);
}
float adc_getf_vbus()
{
uint16_t usResult = adc_read_vbus();
static const float fCorr = 1000.f / 4095.f / ADC_VBUS_VSENSE_DIV;

return (float)usResult * fCorr;
}
static uint16_t adc_read_vin()
{
ADC_REGS->ADC_INPUTCTRL = ADC_INPUTCTRL_GAIN_1X | ADC_INPUTCTRL_MUXNEG_GND | ADC_INPUTCTRL_MUXPOS(ADC_VIN_VSENSE_CHAN);
Expand All @@ -127,19 +97,6 @@ static uint16_t adc_read_vin()

return usResult;
}
uint32_t adc_get_vin()
{
uint16_t usResult = adc_read_vin();

return (uint64_t)usResult * 1000UL * (ADC_VIN_VSENSE_DIV_RT + ADC_VIN_VSENSE_DIV_RB) / (ADC_VIN_VSENSE_DIV_RB * 4095UL);
}
float adc_getf_vin()
{
uint16_t usResult = adc_read_vin();
static const float fCorr = 1000.f / 4095.f / ADC_VIN_VSENSE_DIV;

return (float)usResult * fCorr;
}
static uint16_t adc_read_12v0()
{
ADC_REGS->ADC_INPUTCTRL = ADC_INPUTCTRL_GAIN_1X | ADC_INPUTCTRL_MUXNEG_GND | ADC_INPUTCTRL_MUXPOS(ADC_12V0_VSENSE_CHAN);
Expand All @@ -155,19 +112,6 @@ static uint16_t adc_read_12v0()

return usResult;
}
uint32_t adc_get_12v0()
{
uint16_t usResult = adc_read_12v0();

return (uint64_t)usResult * 1000UL * (ADC_12V0_VSENSE_DIV_RT + ADC_12V0_VSENSE_DIV_RB) / (ADC_12V0_VSENSE_DIV_RB * 4095UL);
}
float adc_getf_12v0()
{
uint16_t usResult = adc_read_12v0();
static const float fCorr = 1000.f / 4095.f / ADC_12V0_VSENSE_DIV;

return (float)usResult * fCorr;
}
static uint16_t adc_read_vext()
{
ADC_REGS->ADC_INPUTCTRL = ADC_INPUTCTRL_GAIN_1X | ADC_INPUTCTRL_MUXNEG_GND | ADC_INPUTCTRL_MUXPOS(ADC_VEXT_VSENSE_CHAN);
Expand All @@ -183,19 +127,6 @@ static uint16_t adc_read_vext()

return usResult;
}
uint32_t adc_get_vext()
{
uint16_t usResult = adc_read_vext();

return (uint64_t)usResult * 1000UL * (ADC_VEXT_VSENSE_DIV_RT + ADC_VEXT_VSENSE_DIV_RB) / (ADC_VEXT_VSENSE_DIV_RB * 4095UL);
}
float adc_getf_vext()
{
uint16_t usResult = adc_read_vext();
static const float fCorr = 1000.f / 4095.f / ADC_VEXT_VSENSE_DIV;

return (float)usResult * fCorr;
}

static uint16_t adc_read_temperature()
{
Expand All @@ -212,51 +143,134 @@ static uint16_t adc_read_temperature()

return usResult;
}
uint32_t adc_get_temperature()

uint32_t adc_get_iovdd()
{
uint16_t usResult = adc_read_iovdd();

return (uint32_t)usResult * 1000UL * 4UL / 4095UL;
}
uint32_t adc_get_corevdd()
{
uint16_t usResult = adc_read_corevdd();

return (uint32_t)usResult * 1000UL * 4UL / 4095UL;
}
uint32_t adc_get_vbus()
{
uint16_t usResult = adc_read_vbus();

return (uint64_t)usResult * 1000UL * (ADC_VBUS_VSENSE_DIV_RT + ADC_VBUS_VSENSE_DIV_RB) / (ADC_VBUS_VSENSE_DIV_RB * 4095UL);
}
uint32_t adc_get_vin()
{
uint16_t usResult = adc_read_vin();

return (uint64_t)usResult * 1000UL * (ADC_VIN_VSENSE_DIV_RT + ADC_VIN_VSENSE_DIV_RB) / (ADC_VIN_VSENSE_DIV_RB * 4095UL);
}
uint32_t adc_get_12v0()
{
uint16_t usResult = adc_read_12v0();

return (uint64_t)usResult * 1000UL * (ADC_12V0_VSENSE_DIV_RT + ADC_12V0_VSENSE_DIV_RB) / (ADC_12V0_VSENSE_DIV_RB * 4095UL);
}
uint32_t adc_get_vext()
{
uint16_t usResult = adc_read_vext();

return (uint64_t)usResult * 1000UL * (ADC_VEXT_VSENSE_DIV_RT + ADC_VEXT_VSENSE_DIV_RB) / (ADC_VEXT_VSENSE_DIV_RB * 4095UL);
}

int32_t adc_get_temperature()
{
static uint8_t ubCalibInit = 0;
static uint32_t ulRoomTemp;
static uint32_t ulRoom1V0;
static uint32_t ulRoomVoltage;
static uint32_t ulHotTemp;
static uint32_t ulHot1V0;
static uint32_t ulHotVoltage;
static int32_t lRoomTemp;
static int32_t lRoom1V0;
static int32_t lRoomVoltage;
static int32_t lHotTemp;
static int32_t lHot1V0;
static int32_t lHotVoltage;

if(!ubCalibInit)
{
uint8_t ubRoomTempInt = (TEMP_LOG_FUSES_REGS->FUSES_TEMP_LOG_WORD_0 & FUSES_TEMP_LOG_WORD_0_NVMCTRL_ROOM_TEMP_VAL_INT_Msk) >> FUSES_TEMP_LOG_WORD_0_NVMCTRL_ROOM_TEMP_VAL_INT_Pos;
uint8_t ubRoomTempDec = (TEMP_LOG_FUSES_REGS->FUSES_TEMP_LOG_WORD_0 & FUSES_TEMP_LOG_WORD_0_NVMCTRL_ROOM_TEMP_VAL_DEC_Msk) >> FUSES_TEMP_LOG_WORD_0_NVMCTRL_ROOM_TEMP_VAL_DEC_Pos;
ulRoomTemp = (uint32_t)ubRoomTempInt * 1000UL + (uint32_t)ubRoomTempDec * 100UL;
lRoomTemp = (uint32_t)ubRoomTempInt * 1000UL + (uint32_t)ubRoomTempDec * 100UL;

int8_t bRoom1V0 = (TEMP_LOG_FUSES_REGS->FUSES_TEMP_LOG_WORD_0 & FUSES_TEMP_LOG_WORD_0_NVMCTRL_ROOM_INT1V_VAL_Msk) >> FUSES_TEMP_LOG_WORD_0_NVMCTRL_ROOM_INT1V_VAL_Pos;
ulRoom1V0 = 1000UL - bRoom1V0;
lRoom1V0 = 1000UL - bRoom1V0;

uint16_t usRoomADCCode = (TEMP_LOG_FUSES_REGS->FUSES_TEMP_LOG_WORD_1 & FUSES_TEMP_LOG_WORD_1_NVMCTRL_ROOM_ADC_VAL_Msk) >> FUSES_TEMP_LOG_WORD_1_NVMCTRL_ROOM_ADC_VAL_Pos;
ulRoomVoltage = (uint32_t)usRoomADCCode * ulRoom1V0 / 4095UL;
lRoomVoltage = (uint32_t)usRoomADCCode * lRoom1V0 / 4095UL;

uint8_t ubHotTempInt = (TEMP_LOG_FUSES_REGS->FUSES_TEMP_LOG_WORD_0 & FUSES_TEMP_LOG_WORD_0_NVMCTRL_HOT_TEMP_VAL_INT_Msk) >> FUSES_TEMP_LOG_WORD_0_NVMCTRL_HOT_TEMP_VAL_INT_Pos;
uint8_t ubHotTempDec = (TEMP_LOG_FUSES_REGS->FUSES_TEMP_LOG_WORD_0 & FUSES_TEMP_LOG_WORD_0_NVMCTRL_HOT_TEMP_VAL_DEC_Msk) >> FUSES_TEMP_LOG_WORD_0_NVMCTRL_HOT_TEMP_VAL_DEC_Pos;
ulHotTemp = (uint32_t)ubHotTempInt * 1000UL + (uint32_t)ubHotTempDec * 100UL;
lHotTemp = (uint32_t)ubHotTempInt * 1000UL + (uint32_t)ubHotTempDec * 100UL;

int8_t bHot1V0 = (TEMP_LOG_FUSES_REGS->FUSES_TEMP_LOG_WORD_1 & FUSES_TEMP_LOG_WORD_1_NVMCTRL_HOT_INT1V_VAL_Msk) >> FUSES_TEMP_LOG_WORD_1_NVMCTRL_HOT_INT1V_VAL_Pos;
ulHot1V0 = 1000UL - bHot1V0;
lHot1V0 = 1000UL - bHot1V0;

uint16_t usHotADCCode = (TEMP_LOG_FUSES_REGS->FUSES_TEMP_LOG_WORD_1 & FUSES_TEMP_LOG_WORD_1_NVMCTRL_HOT_ADC_VAL_Msk) >> FUSES_TEMP_LOG_WORD_1_NVMCTRL_HOT_ADC_VAL_Pos;
ulHotVoltage = (uint32_t)usHotADCCode * ulHot1V0 / 4095UL;
lHotVoltage = (uint32_t)usHotADCCode * lHot1V0 / 4095UL;

ubCalibInit = 1;
}

uint16_t usResult = adc_read_temperature();
int32_t lResult = (int32_t)adc_read_temperature();

int32_t lCoarseVoltage = lResult * 1000UL / 4095UL;
int32_t lCoarseTemp = (lCoarseVoltage - lRoomVoltage) * (lHotTemp - lRoomTemp) / (lHotVoltage - lRoomVoltage) + lRoomTemp;
int32_t l1V0 = (lHot1V0 - lRoom1V0) * (lCoarseTemp - lRoomTemp) / (lHotTemp - lRoomTemp) + lRoom1V0;
int32_t lFineVoltage = lResult * l1V0 / 4095UL;
int32_t lFineTemp = (lFineVoltage - lRoomVoltage) * (lHotTemp - lRoomTemp) / (lHotVoltage - lRoomVoltage) + lRoomTemp;

return lFineTemp;
}

uint32_t ulCoarseVoltage = (uint32_t)usResult * 1000UL / 4095UL;
uint32_t ulCoarseTemp = (ulCoarseVoltage - ulRoomVoltage) * (ulHotTemp - ulRoomTemp) / (ulHotVoltage - ulRoomVoltage) + ulRoomTemp;
uint32_t ul1V0 = (ulHot1V0 - ulRoom1V0) * (ulCoarseTemp - ulRoomTemp) / (ulHotTemp - ulRoomTemp) + ulRoom1V0;
uint32_t ulFineVoltage = (uint32_t)usResult * ul1V0 / 4095UL;
uint32_t ulFineTemp = (ulFineVoltage - ulRoomVoltage) * (ulHotTemp - ulRoomTemp) / (ulHotVoltage - ulRoomVoltage) + ulRoomTemp;
#ifndef ADC_DISABLE_FLOAT
float adc_getf_iovdd()
{
uint16_t usResult = adc_read_iovdd();
static const float fCorr = 1000.f / 4095.f * 4.f;

return (float)usResult * fCorr;
}
float adc_getf_corevdd()
{
uint16_t usResult = adc_read_corevdd();
static const float fCorr = 1000.f / 4095.f * 4.f;

return (float)usResult * fCorr;
}
float adc_getf_vbus()
{
uint16_t usResult = adc_read_vbus();
static const float fCorr = 1000.f / 4095.f / ADC_VBUS_VSENSE_DIV;

return (float)usResult * fCorr;
}
float adc_getf_vin()
{
uint16_t usResult = adc_read_vin();
static const float fCorr = 1000.f / 4095.f / ADC_VIN_VSENSE_DIV;

return ulFineTemp;
return (float)usResult * fCorr;
}
float adc_getf_12v0()
{
uint16_t usResult = adc_read_12v0();
static const float fCorr = 1000.f / 4095.f / ADC_12V0_VSENSE_DIV;

return (float)usResult * fCorr;
}
float adc_getf_vext()
{
uint16_t usResult = adc_read_vext();
static const float fCorr = 1000.f / 4095.f / ADC_VEXT_VSENSE_DIV;

return (float)usResult * fCorr;
}

float adc_getf_temperature()
{
static uint8_t ubCalibInit = 0;
Expand Down Expand Up @@ -301,4 +315,5 @@ float adc_getf_temperature()
float fFineTemp = (fFineVoltage - fRoomVoltage) * (fHotTemp - fRoomTemp) / (fHotVoltage - fRoomVoltage) + fRoomTemp;

return fFineTemp;
}
}
#endif
18 changes: 12 additions & 6 deletions software/pmc/src/include/adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,28 @@
#define ADC_12V0_VSENSE_CHAN 4 // PA04
#define ADC_VEXT_VSENSE_CHAN 5 // PA05

#define ADC_DISABLE_FLOAT 1

void adc_init();

uint32_t adc_get_iovdd();
float adc_getf_iovdd();
uint32_t adc_get_corevdd();
float adc_getf_corevdd();
uint32_t adc_get_vbus();
float adc_getf_vbus();
uint32_t adc_get_vin();
float adc_getf_vin();
uint32_t adc_get_12v0();
float adc_getf_12v0();
uint32_t adc_get_vext();

int32_t adc_get_temperature();

#ifndef ADC_DISABLE_FLOAT
float adc_getf_iovdd();
float adc_getf_corevdd();
float adc_getf_vbus();
float adc_getf_vin();
float adc_getf_12v0();
float adc_getf_vext();

uint32_t adc_get_temperature();
float adc_getf_temperature();
#endif

#endif // __ADC_H__
14 changes: 8 additions & 6 deletions software/pmc/src/include/sercom.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
#include "utils.h"
#include "atomic.h"

#define SERCOM_I2C_NORMAL 0
#define SERCOM_I2C_FAST 1
#define SERCOM_I2C_NORMAL 100000 // Hz
#define SERCOM_I2C_FAST 400000 // Hz

#define SERCOM_I2C_TRISE_DEFAULT 100 // ns

#define SERCOM_I2C_RESTART 0
#define SERCOM_I2C_STOP 1
Expand All @@ -31,7 +33,7 @@ typedef uint8_t (* sercom_i2c_slave_rx_data_isr_t)(uint8_t);
#define SERCOM0_FIFO_SIZE 256 // Only relevant when in UART mode

#ifdef SERCOM0_MODE_I2C_MASTER
void sercom0_i2c_master_init(uint8_t ubMode);
void sercom0_i2c_master_init(uint32_t ulSCLFreq, uint32_t ulTRise);
uint8_t sercom0_i2c_master_transmit(uint8_t ubAddress, uint8_t *pubSrc, uint32_t ulCount, uint8_t ubStop);
static inline uint8_t sercom0_i2c_master_write(uint8_t ubAddress, uint8_t *pubSrc, uint32_t ulCount, uint8_t ubStop)
{
Expand Down Expand Up @@ -119,7 +121,7 @@ static inline void sercom0_uart_read(uint8_t *pubDst, uint32_t ulSize)
#define SERCOM1_FIFO_SIZE 256 // Only relevant when in UART mode

#ifdef SERCOM1_MODE_I2C_MASTER
void sercom1_i2c_master_init(uint8_t ubMode);
void sercom1_i2c_master_init(uint32_t ulSCLFreq, uint32_t ulTRise);
uint8_t sercom1_i2c_master_transmit(uint8_t ubAddress, uint8_t *pubSrc, uint32_t ulCount, uint8_t ubStop);
static inline uint8_t sercom1_i2c_master_write(uint8_t ubAddress, uint8_t *pubSrc, uint32_t ulCount, uint8_t ubStop)
{
Expand Down Expand Up @@ -207,7 +209,7 @@ static inline void sercom1_uart_read(uint8_t *pubDst, uint32_t ulSize)
#define SERCOM2_FIFO_SIZE 256 // Only relevant when in UART mode

#ifdef SERCOM2_MODE_I2C_MASTER
void sercom2_i2c_master_init(uint8_t ubMode);
void sercom2_i2c_master_init(uint32_t ulSCLFreq, uint32_t ulTRise);
uint8_t sercom2_i2c_master_transmit(uint8_t ubAddress, uint8_t *pubSrc, uint32_t ulCount, uint8_t ubStop);
static inline uint8_t sercom2_i2c_master_write(uint8_t ubAddress, uint8_t *pubSrc, uint32_t ulCount, uint8_t ubStop)
{
Expand Down Expand Up @@ -295,7 +297,7 @@ static inline void sercom2_uart_read(uint8_t *pubDst, uint32_t ulSize)
#define SERCOM3_FIFO_SIZE 256 // Only relevant when in UART mode

#ifdef SERCOM3_MODE_I2C_MASTER
void sercom3_i2c_master_init(uint8_t ubMode);
void sercom3_i2c_master_init(uint32_t ulSCLFreq, uint32_t ulTRise);
uint8_t sercom3_i2c_master_transmit(uint8_t ubAddress, uint8_t *pubSrc, uint32_t ulCount, uint8_t ubStop);
static inline uint8_t sercom3_i2c_master_write(uint8_t ubAddress, uint8_t *pubSrc, uint32_t ulCount, uint8_t ubStop)
{
Expand Down
Loading

0 comments on commit 0173f36

Please sign in to comment.