1
0
forked from me/IronOS

Working scheduling of ADC 🎉

This commit is contained in:
Ben V. Brown
2022-04-18 19:21:40 +10:00
parent 1d9b4d851e
commit fc1f28f2b8
9 changed files with 362 additions and 371 deletions

View File

@@ -8,42 +8,80 @@
#include "IRQ.h"
#include "Pins.h"
#include "configuration.h"
#include "expMovingAverage.h"
extern "C" {
#include "bflb_platform.h"
#include "bl702_adc.h"
#include "bl702_glb.h"
#include "bl702_pwm.h"
#include "bl702_timer.h"
#include "hal_adc.h"
#include "hal_clock.h"
#include "hal_pwm.h"
#include "hal_timer.h"
}
void ADC0_1_IRQHandler(void) {
// adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC);
// unblock the PID controller thread
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (pidTaskNotification) {
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
}
#define ADC_Filter_Weight 32
expMovingAverage<uint16_t, ADC_Filter_Weight> ADC_Vin;
expMovingAverage<uint16_t, ADC_Filter_Weight> ADC_Temp;
expMovingAverage<uint16_t, ADC_Filter_Weight> ADC_Tip;
void adc_fifo_irq(void) {
}
if (ADC_GetIntStatus(ADC_INT_FIFO_READY) == SET) {
// Read out all entries in the fifo
const uint8_t cnt = ADC_Get_FIFO_Count();
for (uint8_t i = 0; i < cnt; i++) {
const uint32_t reading = ADC_Read_FIFO();
// As per manual, 26 bit reading; lowest 16 are the ADC
uint16_t sample = reading & 0xFFFF;
uint8_t source = (reading >> 21) & 0b11111;
switch (source) {
case TMP36_ADC_CHANNEL:
ADC_Temp.update(sample);
break;
case TIP_TEMP_ADC_CHANNEL:
ADC_Tip.update(sample);
break;
case VIN_ADC_CHANNEL:
ADC_Vin.update(sample);
break;
case 0: // 0 turns up when an invalid reading is taken
break;
default:
// MSG((char *)"ADC Invalid chan %d\r\n", source);
break;
}
}
// MSG((char *)"ADC Reading %d %d %d\r\n", ADC_Temp.average(), ADC_Vin.average(), ADC_Tip.average());
// Clear IRQ
ADC_IntClr(ADC_INT_FIFO_READY);
}
}
const ADC_Chan_Type adc_tip_pos_chans[] = {TIP_TEMP_ADC_CHANNEL};
const ADC_Chan_Type adc_tip_neg_chans[] = {ADC_CHAN_GND};
static_assert(sizeof(adc_tip_pos_chans) == sizeof(adc_tip_neg_chans));
// TODO Do we need to do the stop+start here or can we hot-write the config
void start_adc_tip(void) {
// Reconfigure the ADC to measure the tip temp
// Single channel input mode
// The ADC has a 32 sample FiFo; we set this up to fire and interrupt at 16 samples
// Then using that IRQ to know that sampling is done and can be stored
ADC_Stop();
ADC_Scan_Channel_Config((ADC_Chan_Type *)adc_tip_pos_chans, (ADC_Chan_Type *)adc_tip_neg_chans, 2, ENABLE);
ADC_Start();
}
const ADC_Chan_Type adc_misc_pos_chans[] = {TMP36_ADC_CHANNEL, VIN_ADC_CHANNEL};
const ADC_Chan_Type adc_misc_neg_chans[] = {ADC_CHAN_GND, ADC_CHAN_GND};
static_assert(sizeof(adc_misc_pos_chans) == sizeof(adc_misc_neg_chans));
void start_adc_misc(void) {
// Reconfigure the ADC to measure all other inputs in scan mode when we are not measuring the tip
ADC_Stop();
ADC_Scan_Channel_Config((ADC_Chan_Type *)adc_misc_pos_chans, (ADC_Chan_Type *)adc_misc_neg_chans, 2, ENABLE);
ADC_Start();
}
static bool fastPWM;
@@ -58,12 +96,14 @@ volatile bool lastPeriodWasFast = false;
void timer0_irq_callback(struct device *dev, void *args, uint32_t size, uint32_t state) {
if (state == TIMER_EVENT_COMP0) {
// MSG((char *)"timer event comp0! \r\n");
// We use channel 0 to trigger the ADC, this occurs after the main PWM is done with a delay
// Used to start the ADC
start_adc_tip();
} else if (state == TIMER_EVENT_COMP1) {
// MSG((char *)"timer event comp1! \r\n");
// Channel 1 is end of the main PWM section; so turn off the output PWM
// Used to turn tip off at set point in cycle
} else if (state == TIMER_EVENT_COMP2) {
start_adc_misc();
// This occurs at timer rollover, so if we want to turn on the output PWM; we do so
if (PWMSafetyTimer) {
PWMSafetyTimer--;
@@ -83,7 +123,15 @@ void timer0_irq_callback(struct device *dev, void *args, uint32_t size, uint32_t
// Leave output off
}
}
// MSG((char *)"timer event comp2! \r\n");
// unblock the PID controller thread
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (pidTaskNotification) {
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
MSG((char *)"timer event comp2! \r\n");
}
}
@@ -150,3 +198,10 @@ bool getFUS302IRQLow() {
return false;
// return (RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin));
}
uint16_t getADCHandleTemp(uint8_t sample) { return ADC_Temp.average(); }
uint16_t getADCVin(uint8_t sample) { return ADC_Vin.average(); }
// Returns either average or instant value. When sample is set the samples from the injected ADC are copied to the filter and then the raw reading is returned
uint16_t getTipRawTemp(uint8_t sample) { return ADC_Tip.average(); }

View File

@@ -18,6 +18,7 @@ extern "C" {
#endif
void timer0_irq_callback(struct device *dev, void *args, uint32_t size, uint32_t state);
void adc_fifo_irq(void);
void start_adc_misc(void);
#ifdef __cplusplus
}
#endif

View File

@@ -7,20 +7,22 @@
#ifndef BSP_PINE64_PINS_H_
#define BSP_PINE64_PINS_H_
#include "bl702_adc.h"
#include "hal_gpio.h"
#define KEY_B_Pin GPIO_PIN_25
#define TMP36_INPUT_Pin GPIO_PIN_20
#define TMP36_ADC_CHANNEL
#define TIP_TEMP_Pin GPIO_PIN_19
#define TIP_TEMP_ADC_CHANNEL
#define VIN_Pin GPIO_PIN_18
#define VIN_ADC_CHANNEL
#define OLED_RESET_Pin GPIO_PIN_3
#define KEY_A_Pin GPIO_PIN_28
#define PWM_Out_Pin GPIO_PIN_21
#define SCL_Pin GPIO_PIN_11
#define SDA_Pin GPIO_PIN_10
#define KEY_B_Pin GPIO_PIN_25
#define TMP36_INPUT_Pin GPIO_PIN_20
#define TMP36_ADC_CHANNEL ADC_CHAN10
#define TIP_TEMP_Pin GPIO_PIN_19
#define TIP_TEMP_ADC_CHANNEL ADC_CHAN9
#define VIN_Pin GPIO_PIN_18
#define VIN_ADC_CHANNEL ADC_CHAN8
#define OLED_RESET_Pin GPIO_PIN_3
#define KEY_A_Pin GPIO_PIN_28
#define PWM_Out_Pin GPIO_PIN_21
#define SCL_Pin GPIO_PIN_11
#define SDA_Pin GPIO_PIN_10
// #define USB_DM_Pin GPIO_PIN_8
#define QC_DP_LOW_Pin GPIO_PIN_5

View File

@@ -9,18 +9,7 @@
#include "Debug.h"
#include "FreeRTOSConfig.h"
#include "Pins.h"
extern "C" {
#include "bflb_platform.h"
#include "bl702_adc.h"
#include "bl702_glb.h"
#include "bl702_i2c.h"
#include "bl702_pwm.h"
#include "bl702_timer.h"
#include "hal_adc.h"
#include "hal_clock.h"
#include "hal_pwm.h"
#include "hal_timer.h"
}
#include "IRQ.h"
#include "history.hpp"
#include <string.h>
@@ -37,45 +26,48 @@ void hardware_init() {
// gpio_set_mode(KEY_A_Pin, GPIO_INPUT_PD_MODE);
// gpio_set_mode(KEY_B_Pin, GPIO_INPUT_PD_MODE);
setup_slow_PWM();
setup_adc();
}
void setup_adc(void) {
MSG((char *)"Setting up ADC\r\n");
//
ADC_CFG_Type adc_cfg = {};
ADC_FIFO_Cfg_Type adc_fifo_cfg = {};
CPU_Interrupt_Disable(GPADC_DMA_IRQn);
ADC_IntMask(ADC_INT_ALL, MASK);
adc_cfg.clkDiv = ADC_CLK_DIV_32;
adc_cfg.vref = ADC_VREF_3P2V;
adc_cfg.resWidth = ADC_DATA_WIDTH_16_WITH_128_AVERAGE;
adc_cfg.inputMode = ADC_INPUT_SINGLE_END;
adc_cfg.clkDiv = ADC_CLK_DIV_32;
adc_cfg.vref = ADC_VREF_3P2V;
adc_cfg.resWidth = ADC_DATA_WIDTH_16_WITH_256_AVERAGE;
adc_cfg.inputMode = ADC_INPUT_SINGLE_END;
adc_cfg.v18Sel = ADC_V18_SEL_1P82V;
adc_cfg.v11Sel = ADC_V11_SEL_1P1V;
adc_cfg.gain1 = ADC_PGA_GAIN_1;
adc_cfg.gain2 = ADC_PGA_GAIN_2;
adc_cfg.gain1 = ADC_PGA_GAIN_NONE;
adc_cfg.gain2 = ADC_PGA_GAIN_NONE;
adc_cfg.chopMode = ADC_CHOP_MOD_AZ_PGA_ON;
adc_cfg.biasSel = ADC_BIAS_SEL_MAIN_BANDGAP;
adc_cfg.vcm = ADC_PGA_VCM_1V;
adc_cfg.offsetCalibEn = DISABLE;
adc_cfg.offsetCalibVal = 0;
adc_fifo_cfg.dmaEn = DISABLE;
adc_fifo_cfg.fifoThreshold = ADC_FIFO_THRESHOLD_16;
Interrupt_Handler_Register(GPADC_DMA_IRQn, adc_fifo_irq);
ADC_Disable();
ADC_Enable();
ADC_Reset();
ADC_Init(&adc_cfg);
adc_fifo_cfg.dmaEn = DISABLE;
adc_fifo_cfg.fifoThreshold = ADC_FIFO_THRESHOLD_16;
ADC_FIFO_Cfg(&adc_fifo_cfg);
// Enable FiFo IRQ
MSG((char *)"Int Enable\r\n");
Interrupt_Handler_Register(GPADC_DMA_IRQn, adc_fifo_irq);
ADC_IntMask(ADC_INT_FIFO_READY, UNMASK);
CPU_Interrupt_Enable(GPADC_DMA_IRQn);
MSG((char *)"Start\r\n");
start_adc_misc();
MSG((char *)"Started\r\n");
}
struct device *timer0;
@@ -104,61 +96,6 @@ void setup_slow_PWM() {
}
}
/*
* ADC
* ADC is a bit of a mess as we dont have injected mode sampling to use with timers on this device
* So instead we do this:
*
* Main timer0 runs at 5/10hz and schedules everything
* Its running PWM in the 0-255 range for tip control + sample time at the end of the ADC
* It triggers the ADC at the end of the PWM cycle
*
*
*/
uint16_t getADCHandleTemp(uint8_t sample) {
static history<uint16_t, ADC_FILTER_LEN> filter = {{0}, 0, 0};
if (sample) {
uint32_t sum = 0;
for (uint8_t i = 0; i < ADC_NORM_SAMPLES; i++) {
sum += ADCReadings[i];
}
filter.update(sum);
}
return filter.average() >> 1;
}
uint16_t getADCVin(uint8_t sample) {
static history<uint16_t, ADC_FILTER_LEN> filter = {{0}, 0, 0};
if (sample) {
uint16_t latestADC = 0;
// latestADC += adc_inserted_data_read(ADC1, 0);
// latestADC += adc_inserted_data_read(ADC1, 1);
// latestADC += adc_inserted_data_read(ADC1, 2);
// latestADC += adc_inserted_data_read(ADC1, 3);
latestADC <<= 1;
filter.update(latestADC);
}
return filter.average();
}
// Returns either average or instant value. When sample is set the samples from the injected ADC are copied to the filter and then the raw reading is returned
uint16_t getTipRawTemp(uint8_t sample) {
static history<uint16_t, ADC_FILTER_LEN> filter = {{0}, 0, 0};
if (sample) {
uint16_t latestADC = 0;
// latestADC += adc_inserted_data_read(ADC0, 0);
// latestADC += adc_inserted_data_read(ADC0, 1);
// latestADC += adc_inserted_data_read(ADC0, 2);
// latestADC += adc_inserted_data_read(ADC0, 3);
latestADC <<= 1;
filter.update(latestADC);
return latestADC;
}
return filter.average();
}
void setupFUSBIRQ() {
// #TODO
}

View File

@@ -8,10 +8,24 @@
#ifndef PINE_SETUP_H_
#define PINE_SETUP_H_
#include <stdint.h>
extern "C" {
#include "bflb_platform.h"
#include "bl702_adc.h"
#include "bl702_common.h"
#include "bl702_glb.h"
#include "bl702_i2c.h"
#include "bl702_pwm.h"
#include "bl702_timer.h"
#include "hal_adc.h"
#include "hal_clock.h"
#include "hal_pwm.h"
#include "hal_timer.h"
}
#ifdef __cplusplus
extern "C" {
#endif
uint16_t getADC(uint8_t channel);
void hardware_init();
uint16_t getADCHandleTemp(uint8_t sample);

View File

@@ -21,9 +21,9 @@
*
*/
#include "hal_timer.h"
#include "hal_clock.h"
#include "bl702_glb.h"
#include "bl702_timer.h"
#include "hal_clock.h"
#ifdef BSP_USING_TIMER0
void TIMER0_IRQ(void);
@@ -48,103 +48,102 @@ static timer_device_t timerx_device[TIMER_MAX_INDEX] = {
* @param oflag
* @return int
*/
int timer_open(struct device *dev, uint16_t oflag)
{
timer_device_t *timer_device = (timer_device_t *)dev;
int timer_open(struct device *dev, uint16_t oflag) {
timer_device_t *timer_device = (timer_device_t *)dev;
uint32_t tmpval;
uint32_t compare_count1 = 0;
uint32_t compare_count2 = 0;
uint32_t compare_count3 = 0;
uint32_t reload_val = 0;
uint32_t clkval = 0;
uint32_t unit = 0;
uint32_t tmpval;
uint32_t compare_count1 = 0;
uint32_t compare_count2 = 0;
uint32_t compare_count3 = 0;
uint32_t reload_val = 0;
uint32_t clkval = 0;
uint32_t unit = 0;
/* Disable all interrupt */
TIMER_IntMask(timer_device->id, TIMER_INT_ALL, MASK);
/* Disable timer before config */
TIMER_Disable(timer_device->id);
/* Disable all interrupt */
TIMER_IntMask(timer_device->id, TIMER_INT_ALL, MASK);
/* Disable timer before config */
TIMER_Disable(timer_device->id);
/* Configure timer count mode: preload or free run */
tmpval = BL_RD_WORD(TIMER_BASE + TIMER_TCMR_OFFSET);
tmpval &= (~(1 << (timer_device->id + 1)));
tmpval |= (timer_device->cnt_mode << (timer_device->id + 1));
/* Configure timer count mode: preload or free run */
tmpval = BL_RD_WORD(TIMER_BASE + TIMER_TCMR_OFFSET);
tmpval &= (~(1 << (timer_device->id + 1)));
tmpval |= (timer_device->cnt_mode << (timer_device->id + 1));
BL_WR_WORD(TIMER_BASE + TIMER_TCMR_OFFSET, tmpval);
BL_WR_WORD(TIMER_BASE + TIMER_TCMR_OFFSET, tmpval);
/* Configure timer preload trigger source */
BL_WR_WORD(TIMER_BASE + TIMER_TPLCR2_OFFSET + 4 * timer_device->id, timer_device->trigger);
/* Configure timer preload trigger source */
BL_WR_WORD(TIMER_BASE + TIMER_TPLCR2_OFFSET + 4 * timer_device->id, timer_device->trigger);
if (timer_device->cnt_mode == TIMER_CNT_PRELOAD) {
BL_WR_WORD(TIMER_BASE + TIMER_TPLVR2_OFFSET + 4 * timer_device->id, timer_device->reload);
reload_val = timer_device->reload;
}
if (timer_device->cnt_mode == TIMER_CNT_PRELOAD) {
BL_WR_WORD(TIMER_BASE + TIMER_TPLVR2_OFFSET + 4 * timer_device->id, timer_device->reload);
reload_val = timer_device->reload;
}
if (timer_device->id == TIMER_CH0) {
clkval = peripheral_clock_get(PERIPHERAL_CLOCK_TIMER0);
} else {
clkval = peripheral_clock_get(PERIPHERAL_CLOCK_TIMER1);
}
if (timer_device->id == TIMER_CH0) {
clkval = peripheral_clock_get(PERIPHERAL_CLOCK_TIMER0);
} else {
clkval = peripheral_clock_get(PERIPHERAL_CLOCK_TIMER1);
}
if (clkval % 1000000 == 0) {
unit = 1000000; //1us
} else if (clkval % 100000 == 0) {
unit = 100000; //10us
} else if (clkval % 10000 == 0) {
unit = 10000; //100us
} else if (clkval % 1000 == 0) {
unit = 1000; //1ms
} else if (clkval % 100 == 0) {
unit = 100; //10ms
} else if (clkval % 10 == 0) {
unit = 10; //100ms
} else if (clkval % 1 == 0) {
unit = 1; //s
} else {
}
if (clkval % 1000000 == 0) {
unit = 1000000; // 1us
} else if (clkval % 100000 == 0) {
unit = 100000; // 10us
} else if (clkval % 10000 == 0) {
unit = 10000; // 100us
} else if (clkval % 1000 == 0) {
unit = 1000; // 1ms
} else if (clkval % 100 == 0) {
unit = 100; // 10ms
} else if (clkval % 10 == 0) {
unit = 10; // 100ms
} else if (clkval % 1 == 0) {
unit = 1; // s
} else {
}
compare_count1 = timer_device->timeout1 / (1000000 / unit) * (clkval / unit) + reload_val;
compare_count2 = timer_device->timeout2 / (1000000 / unit) * (clkval / unit) + reload_val;
compare_count3 = timer_device->timeout3 / (1000000 / unit) * (clkval / unit) + reload_val;
compare_count1 = timer_device->timeout1 / (1000000 / unit) * (clkval / unit) + reload_val;
compare_count2 = timer_device->timeout2 / (1000000 / unit) * (clkval / unit) + reload_val;
compare_count3 = timer_device->timeout3 / (1000000 / unit) * (clkval / unit) + reload_val;
/* Configure match compare values */
if ((compare_count1 < 1) || (compare_count2 < 1) || (compare_count3 < 1)) {
return -1;
}
/* Configure match compare values */
if ((compare_count1 < 1) || (compare_count2 < 1) || (compare_count3 < 1)) {
return -1;
}
TIMER_SetCompValue(timer_device->id, TIMER_COMP_ID_0, compare_count1 - 2);
TIMER_SetCompValue(timer_device->id, TIMER_COMP_ID_1, compare_count2 - 2);
TIMER_SetCompValue(timer_device->id, TIMER_COMP_ID_2, compare_count3 - 2);
TIMER_SetCompValue(timer_device->id, TIMER_COMP_ID_0, compare_count1 - 2);
TIMER_SetCompValue(timer_device->id, TIMER_COMP_ID_1, compare_count2 - 2);
TIMER_SetCompValue(timer_device->id, TIMER_COMP_ID_2, compare_count3 - 2);
/* Clear interrupt status*/
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_0);
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_1);
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_2);
/* Clear interrupt status*/
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_0);
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_1);
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_2);
if (oflag & DEVICE_OFLAG_STREAM_TX) {
/* Enable timer match interrupt */
/* Note: if not enable match interrupt, TIMER_GetMatchStatus will not work
and status bit will not set */
TIMER_IntMask(timer_device->id, TIMER_INT_COMP_0, UNMASK);
TIMER_IntMask(timer_device->id, TIMER_INT_COMP_1, UNMASK);
TIMER_IntMask(timer_device->id, TIMER_INT_COMP_2, UNMASK);
}
if (oflag & DEVICE_OFLAG_STREAM_TX) {
/* Enable timer match interrupt */
/* Note: if not enable match interrupt, TIMER_GetMatchStatus will not work
and status bit will not set */
TIMER_IntMask(timer_device->id, TIMER_INT_COMP_0, UNMASK);
TIMER_IntMask(timer_device->id, TIMER_INT_COMP_1, UNMASK);
TIMER_IntMask(timer_device->id, TIMER_INT_COMP_2, UNMASK);
}
if (oflag & DEVICE_OFLAG_INT_TX) {
if (oflag & DEVICE_OFLAG_INT_TX) {
#ifdef BSP_USING_TIMER0
if (timer_device->id == TIMER_CH0) {
Interrupt_Handler_Register(TIMER_CH0_IRQn, TIMER0_IRQ);
}
if (timer_device->id == TIMER_CH0) {
Interrupt_Handler_Register(TIMER_CH0_IRQn, TIMER0_IRQ);
}
#endif
#ifdef BSP_USING_TIMER1
if (timer_device->id == TIMER_CH1) {
Interrupt_Handler_Register(TIMER_CH1_IRQn, TIMER1_IRQ);
}
#endif
if (timer_device->id == TIMER_CH1) {
Interrupt_Handler_Register(TIMER_CH1_IRQn, TIMER1_IRQ);
}
/* Enable timer */
TIMER_Enable(timer_device->id);
return 0;
#endif
}
/* Enable timer */
TIMER_Enable(timer_device->id);
return 0;
}
/**
@@ -153,11 +152,10 @@ int timer_open(struct device *dev, uint16_t oflag)
* @param dev
* @return int
*/
int timer_close(struct device *dev)
{
timer_device_t *timer_device = (timer_device_t *)(dev);
TIMER_Disable(timer_device->id);
return 0;
int timer_close(struct device *dev) {
timer_device_t *timer_device = (timer_device_t *)(dev);
TIMER_Disable(timer_device->id);
return 0;
}
/**
@@ -168,138 +166,133 @@ int timer_close(struct device *dev)
* @param args
* @return int
*/
int timer_control(struct device *dev, int cmd, void *args)
{
timer_device_t *timer_device = (timer_device_t *)dev;
int timer_control(struct device *dev, int cmd, void *args) {
timer_device_t *timer_device = (timer_device_t *)dev;
switch (cmd) {
case DEVICE_CTRL_SET_INT /* constant-expression */: {
uint32_t offset = __builtin_ctz((uint32_t)args);
switch (cmd) {
case DEVICE_CTRL_SET_INT /* constant-expression */: {
uint32_t offset = __builtin_ctz((uint32_t)args);
while (offset < 3) {
if ((uint32_t)args & (1 << offset)) {
TIMER_IntMask(timer_device->id, offset, UNMASK);
}
offset++;
}
if (timer_device->id == TIMER_CH0) {
CPU_Interrupt_Pending_Clear(TIMER_CH0_IRQn);
CPU_Interrupt_Enable(TIMER_CH0_IRQn);
} else if (timer_device->id == TIMER_CH1) {
CPU_Interrupt_Pending_Clear(TIMER_CH1_IRQn);
CPU_Interrupt_Enable(TIMER_CH1_IRQn);
}
break;
}
case DEVICE_CTRL_CLR_INT /* constant-expression */: {
uint32_t offset = __builtin_ctz((uint32_t)args);
while (offset < 3) {
if ((uint32_t)args & (1 << offset)) {
TIMER_IntMask(timer_device->id, offset, MASK);
}
offset++;
}
if (timer_device->id == TIMER_CH0) {
CPU_Interrupt_Disable(TIMER_CH0_IRQn);
} else if (timer_device->id == TIMER_CH1) {
CPU_Interrupt_Disable(TIMER_CH1_IRQn);
}
break;
}
case DEVICE_CTRL_GET_INT /* constant-expression */: {
uint32_t offset = __builtin_ctz((uint32_t)args);
uint32_t intstatus = TIMER_GetMatchStatus(timer_device->id, offset);
/* Clear interrupt status*/
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_0);
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_1);
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_2);
return intstatus;
}
case DEVICE_CTRL_CONFIG /* constant-expression */:
/* code */
break;
case DEVICE_CTRL_RESUME /* constant-expression */: {
/* Enable timer */
TIMER_Enable(timer_device->id);
break;
}
case DEVICE_CTRL_SUSPEND /* constant-expression */: {
TIMER_Disable(timer_device->id);
break;
}
case DEVICE_CTRL_GET_CONFIG:
return TIMER_GetCounterValue(timer_device->id);
default:
break;
}
return 0;
}
int timer_write(struct device *dev, uint32_t pos, const void *buffer, uint32_t size)
{
timer_device_t *timer_device = (timer_device_t *)dev;
timer_timeout_cfg_t *timeout_cfg = (timer_timeout_cfg_t *)buffer;
uint32_t compare_count = 0;
uint32_t reload_val = 0;
uint32_t clkval = 0;
uint32_t unit = 0;
if (size % sizeof(timer_timeout_cfg_t)) {
return -1;
}
/* Disable timer before config */
TIMER_Disable(timer_device->id);
if (timer_device->cnt_mode == TIMER_CNT_PRELOAD) {
reload_val = timer_device->reload;
while (offset < 3) {
if ((uint32_t)args & (1 << offset)) {
TIMER_IntMask(timer_device->id, offset, UNMASK);
}
offset++;
}
if (timer_device->id == TIMER_CH0) {
clkval = peripheral_clock_get(PERIPHERAL_CLOCK_TIMER0);
} else {
clkval = peripheral_clock_get(PERIPHERAL_CLOCK_TIMER1);
CPU_Interrupt_Pending_Clear(TIMER_CH0_IRQn);
CPU_Interrupt_Enable(TIMER_CH0_IRQn);
} else if (timer_device->id == TIMER_CH1) {
CPU_Interrupt_Pending_Clear(TIMER_CH1_IRQn);
CPU_Interrupt_Enable(TIMER_CH1_IRQn);
}
if (clkval % 1000000 == 0) {
unit = 1000000; //1us
} else if (clkval % 100000 == 0) {
unit = 100000; //10us
} else if (clkval % 10000 == 0) {
unit = 10000; //100us
} else if (clkval % 1000 == 0) {
unit = 1000; //1ms
} else if (clkval % 100 == 0) {
unit = 100; //10ms
} else if (clkval % 10 == 0) {
unit = 10; //100ms
} else if (clkval % 1 == 0) {
unit = 1; //s
} else {
}
break;
}
for (uint32_t i = 0; i < size / sizeof(timer_timeout_cfg_t); i++) {
compare_count = timeout_cfg->timeout_val / (1000000 / unit) * (clkval / unit) + reload_val;
case DEVICE_CTRL_CLR_INT /* constant-expression */: {
uint32_t offset = __builtin_ctz((uint32_t)args);
if (compare_count < 1) {
return -1;
}
TIMER_SetCompValue(timer_device->id, timeout_cfg->timeout_id, compare_count - 2);
while (offset < 3) {
if ((uint32_t)args & (1 << offset)) {
TIMER_IntMask(timer_device->id, offset, MASK);
}
offset++;
}
if (timer_device->id == TIMER_CH0) {
CPU_Interrupt_Disable(TIMER_CH0_IRQn);
} else if (timer_device->id == TIMER_CH1) {
CPU_Interrupt_Disable(TIMER_CH1_IRQn);
}
break;
}
case DEVICE_CTRL_GET_INT /* constant-expression */: {
uint32_t offset = __builtin_ctz((uint32_t)args);
uint32_t intstatus = TIMER_GetMatchStatus(timer_device->id, offset);
/* Clear interrupt status*/
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_0);
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_1);
TIMER_ClearIntStatus(timer_device->id, TIMER_COMP_ID_2);
return intstatus;
}
case DEVICE_CTRL_CONFIG /* constant-expression */:
/* code */
break;
case DEVICE_CTRL_RESUME /* constant-expression */: {
/* Enable timer */
TIMER_Enable(timer_device->id);
return 0;
break;
}
case DEVICE_CTRL_SUSPEND /* constant-expression */: {
TIMER_Disable(timer_device->id);
break;
}
case DEVICE_CTRL_GET_CONFIG:
return TIMER_GetCounterValue(timer_device->id);
default:
break;
}
return 0;
}
int timer_read(struct device *dev, uint32_t pos, void *buffer, uint32_t size)
{
return 0;
int timer_write(struct device *dev, uint32_t pos, const void *buffer, uint32_t size) {
timer_device_t *timer_device = (timer_device_t *)dev;
timer_timeout_cfg_t *timeout_cfg = (timer_timeout_cfg_t *)buffer;
uint32_t compare_count = 0;
uint32_t reload_val = 0;
uint32_t clkval = 0;
uint32_t unit = 0;
if (size % sizeof(timer_timeout_cfg_t)) {
return -1;
}
/* Disable timer before config */
TIMER_Disable(timer_device->id);
if (timer_device->cnt_mode == TIMER_CNT_PRELOAD) {
reload_val = timer_device->reload;
}
if (timer_device->id == TIMER_CH0) {
clkval = peripheral_clock_get(PERIPHERAL_CLOCK_TIMER0);
} else {
clkval = peripheral_clock_get(PERIPHERAL_CLOCK_TIMER1);
}
if (clkval % 1000000 == 0) {
unit = 1000000; // 1us
} else if (clkval % 100000 == 0) {
unit = 100000; // 10us
} else if (clkval % 10000 == 0) {
unit = 10000; // 100us
} else if (clkval % 1000 == 0) {
unit = 1000; // 1ms
} else if (clkval % 100 == 0) {
unit = 100; // 10ms
} else if (clkval % 10 == 0) {
unit = 10; // 100ms
} else if (clkval % 1 == 0) {
unit = 1; // s
} else {
}
for (uint32_t i = 0; i < size / sizeof(timer_timeout_cfg_t); i++) {
compare_count = timeout_cfg->timeout_val / (1000000 / unit) * (clkval / unit) + reload_val;
if (compare_count < 1) {
return -1;
}
TIMER_SetCompValue(timer_device->id, timeout_cfg->timeout_id, compare_count - 2);
}
TIMER_Enable(timer_device->id);
return 0;
}
int timer_read(struct device *dev, uint32_t pos, void *buffer, uint32_t size) { return 0; }
/**
* @brief
@@ -308,60 +301,57 @@ int timer_read(struct device *dev, uint32_t pos, void *buffer, uint32_t size)
* @param name
* @return int
*/
int timer_register(enum timer_index_type index, const char *name)
{
struct device *dev;
int timer_register(enum timer_index_type index, const char *name) {
struct device *dev;
if (TIMER_MAX_INDEX == 0) {
return -DEVICE_EINVAL;
}
if (TIMER_MAX_INDEX == 0) {
return -DEVICE_EINVAL;
}
dev = &(timerx_device[index].parent);
dev = &(timerx_device[index].parent);
dev->open = timer_open;
dev->close = timer_close;
dev->control = timer_control;
dev->write = timer_write;
// dev->read = NULL;
dev->open = timer_open;
dev->close = timer_close;
dev->control = timer_control;
dev->write = timer_write;
// dev->read = NULL;
dev->type = DEVICE_CLASS_TIMER;
dev->handle = NULL;
dev->type = DEVICE_CLASS_TIMER;
dev->handle = NULL;
return device_register(dev, name);
return device_register(dev, name);
}
void timer_isr(timer_device_t *handle)
{
uint32_t intId = 0;
uint32_t tmpVal = 0;
uint32_t tmpAddr = 0;
void timer_isr(timer_device_t *handle) {
uint32_t intId = 0;
uint32_t tmpVal = 0;
uint32_t tmpAddr = 0;
if (!handle->parent.callback) {
return;
}
if (!handle->parent.callback) {
return;
}
intId = BL_RD_WORD(TIMER_BASE + TIMER_TMSR2_OFFSET + 4 * handle->id);
tmpAddr = TIMER_BASE + TIMER_TICR2_OFFSET + 4 * handle->id;
tmpVal = BL_RD_WORD(tmpAddr);
intId = BL_RD_WORD(TIMER_BASE + TIMER_TMSR2_OFFSET + 4 * handle->id);
tmpAddr = TIMER_BASE + TIMER_TICR2_OFFSET + 4 * handle->id;
tmpVal = BL_RD_WORD(tmpAddr);
/* Comparator 0 match interrupt */
if (BL_IS_REG_BIT_SET(intId, TIMER_TMSR_0)) {
BL_WR_WORD(tmpAddr, BL_SET_REG_BIT(tmpVal, TIMER_TCLR_0));
handle->parent.callback(&handle->parent, NULL, 0, TIMER_EVENT_COMP0);
/* Comparator 0 match interrupt */
if (BL_IS_REG_BIT_SET(intId, TIMER_TMSR_0)) {
BL_WR_WORD(tmpAddr, BL_SET_REG_BIT(tmpVal, TIMER_TCLR_0));
handle->parent.callback(&handle->parent, NULL, 0, TIMER_EVENT_COMP0);
}
}
/* Comparator 1 match interrupt */
if (BL_IS_REG_BIT_SET(intId, TIMER_TMSR_1)) {
BL_WR_WORD(tmpAddr, BL_SET_REG_BIT(tmpVal, TIMER_TCLR_1));
handle->parent.callback(&handle->parent, NULL, 0, TIMER_EVENT_COMP1);
}
/* Comparator 1 match interrupt */
if (BL_IS_REG_BIT_SET(intId, TIMER_TMSR_1)) {
BL_WR_WORD(tmpAddr, BL_SET_REG_BIT(tmpVal, TIMER_TCLR_1));
handle->parent.callback(&handle->parent, NULL, 0, TIMER_EVENT_COMP1);
}
/* Comparator 2 match interrupt */
if (BL_IS_REG_BIT_SET(intId, TIMER_TMSR_2)) {
BL_WR_WORD(tmpAddr, BL_SET_REG_BIT(tmpVal, TIMER_TCLR_2));
handle->parent.callback(&handle->parent, NULL, 0, TIMER_EVENT_COMP2);
}
/* Comparator 2 match interrupt */
if (BL_IS_REG_BIT_SET(intId, TIMER_TMSR_2)) {
BL_WR_WORD(tmpAddr, BL_SET_REG_BIT(tmpVal, TIMER_TCLR_2));
handle->parent.callback(&handle->parent, NULL, 0, TIMER_EVENT_COMP2);
}
}
#ifdef BSP_USING_TIMER0
@@ -369,10 +359,7 @@ void timer_isr(timer_device_t *handle)
* @brief
*
*/
void TIMER0_IRQ(void)
{
timer_isr(&timerx_device[TIMER0_INDEX]);
}
void TIMER0_IRQ(void) { timer_isr(&timerx_device[TIMER0_INDEX]); }
#endif
@@ -381,9 +368,6 @@ void TIMER0_IRQ(void)
* @brief
*
*/
void TIMER1_IRQ(void)
{
timer_isr(&timerx_device[TIMER1_INDEX]);
}
void TIMER1_IRQ(void) { timer_isr(&timerx_device[TIMER1_INDEX]); }
#endif

View File

@@ -49,7 +49,7 @@
#define BSP_IR_CLOCK_SOURCE ROOT_CLOCK_SOURCE_XCLK
#define BSP_IR_CLOCK_DIV 0
#define BSP_ADC_CLOCK_SOURCE ROOT_CLOCK_SOURCE_XCLK
#define BSP_ADC_CLOCK_DIV 0
#define BSP_ADC_CLOCK_DIV 128
#define BSP_DAC_CLOCK_SOURCE ROOT_CLOCK_SOURCE_AUPLL_24000000_HZ
#define BSP_DAC_CLOCK_DIV 2
#define BSP_CAM_CLOCK_SOURCE ROOT_CLOCK_SOURCE_PLL_96M

View File

@@ -8,7 +8,6 @@
#ifndef INC_EXPMOVINGAVERAGE_H_
#define INC_EXPMOVINGAVERAGE_H_
// max size = 127
template <class T, uint8_t weighting> struct expMovingAverage {
int32_t sum;
void update(T const val) { sum = ((val * weighting) + (sum * (256 - weighting))) / 256; }

View File

@@ -270,7 +270,7 @@ CPUFLAGS= -march=rv32imafc \
-mabi=ilp32f \
-mcmodel=medany -fsigned-char -fno-builtin -nostartfiles \
-DportasmHANDLE_INTERRUPT=FreeRTOS_Interrupt_Handler -DARCH_RISCV -D__RISCV_FEATURE_MVE=0 -DportUSING_MPU_WRAPPERS=0
DEV_LDFLAGS=-nostartfiles --specs=patch.specs
DEV_LDFLAGS=-nostartfiles --specs=patch.specs -DDEBUG
DEV_AFLAGS=
DEV_GLOBAL_DEFS=
#Required to be turned off due to their drivers tripping warnings
@@ -355,7 +355,6 @@ LINKER_FLAGS= -Wl,--gc-sections \
-Wl,--defsym=__FLASH_SIZE__=$(flash_size) \
-Wl,--defsym=__BOOTLDR_SIZE__=$(bootldr_size) \
-Wl,--print-memory-usage \
-flto \
--specs=nosys.specs \
--specs=nano.specs \
$(DEV_LDFLAGS)