ADC timing faster + timer without HAL

This commit is contained in:
Ben V. Brown
2022-04-20 21:18:01 +10:00
parent 25283e434f
commit 3a82210b73
10 changed files with 125 additions and 603 deletions

View File

@@ -12,8 +12,8 @@
// These control the period's of time used for the PWM
const uint16_t powerPWM = 255;
const uint8_t holdoffTicks = 10;
const uint8_t tempMeasureTicks = 14;
const uint8_t holdoffTicks = 14;
const uint8_t tempMeasureTicks = 10;
uint16_t totalPWM = 255; // Total length of the cycle's ticks

View File

@@ -120,7 +120,7 @@ bool FRToSI2C::wakePart(uint16_t DevAddress) {
i2cCfg.subAddrSize = 0;
err = I2C_MasterReceiveBlocking(I2C0_ID, &i2cCfg);
MSG((char *)"I2C wakePart %02X - %d\r\n", DevAddress >> 1, err);
// MSG((char *)"I2C wakePart %02X - %d\r\n", DevAddress >> 1, err);
bool res = err == SUCCESS;
if (!res) {
I2C_Unstick();

View File

@@ -16,9 +16,7 @@ extern "C" {
#include "bl702_glb.h"
#include "bl702_pwm.h"
#include "bl702_timer.h"
#include "hal_adc.h"
#include "hal_clock.h"
#include "hal_timer.h"
}
#define ADC_Filter_Smooth 4
@@ -27,10 +25,8 @@ history<uint16_t, ADC_Filter_Smooth> ADC_Temp;
history<uint16_t, ADC_Filter_Smooth> ADC_Tip;
void adc_fifo_irq(void) {
MSG((char *)"ADC IRQ\r\n");
if (ADC_GetIntStatus(ADC_INT_FIFO_READY) == SET) {
ADC_IntClr(ADC_INT_FIFO_READY);
// Read out all entries in the fifo
const uint8_t cnt = ADC_Get_FIFO_Count();
for (uint8_t i = 0; i < cnt; i++) {
@@ -50,27 +46,17 @@ void adc_fifo_irq(void) {
break;
default:
MSG((char *)"ADC Invalid chan %d\r\n", source);
// 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());
// 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);
}
}
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_Start();
}
void stop_adc(void) {}
static bool fastPWM;
static void switchToSlowPWM(void);
static bool fastPWM = false;
static void switchToFastPWM(void);
volatile uint16_t PWMSafetyTimer = 0;
@@ -78,46 +64,44 @@ volatile uint8_t pendingPWM = 200;
volatile bool lastPeriodWasFast = false;
// Timer 0 is used to co-ordinate the ADC and the output PWM
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");
// Used to start the ADC
start_adc_tip();
} else if (state == TIMER_EVENT_COMP1) {
// MSG((char *)"timer event comp1! \r\n");
// Used to turn tip off at set point in cycle
PWM_Channel_Disable(PWM_Channel);
} else if (state == TIMER_EVENT_COMP2) {
// This occurs at timer rollover, so if we want to turn on the output PWM; we do so
if (PWMSafetyTimer) {
PWMSafetyTimer--;
if (lastPeriodWasFast != fastPWM) {
if (fastPWM) {
switchToFastPWM();
} else {
switchToSlowPWM();
}
}
// Update trigger for the end point of the PWM cycle
if (pendingPWM > 0) {
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_1, pendingPWM - 1);
// Turn on output
PWM_Channel_Enable(PWM_Channel);
void timer0_comp0_callback(void) {
MSG((char *)"Timer CMP0\r\n");
ADC_Start();
}
void timer0_comp1_callback(void) {
MSG((char *)"Timer CMP1\r\n");
PWM_Channel_Disable(PWM_Channel);
}
void timer0_comp2_callback(void) {
MSG((char *)"Timer CMP2\r\n");
// This occurs at timer rollover, so if we want to turn on the output PWM; we do so
if (PWMSafetyTimer) {
PWMSafetyTimer--;
if (lastPeriodWasFast != fastPWM) {
if (fastPWM) {
switchToFastPWM();
} else {
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_1, 0);
// Leave output off
PWM_Channel_Disable(PWM_Channel);
switchToSlowPWM();
}
}
// unblock the PID controller thread
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (pidTaskNotification) {
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
// Update trigger for the end point of the PWM cycle
if (pendingPWM > 0) {
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_1, pendingPWM - 1);
// Turn on output
PWM_Channel_Enable(PWM_Channel);
} else {
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_1, 0);
// Leave output off
PWM_Channel_Disable(PWM_Channel);
}
}
// 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");
}
}
@@ -132,7 +116,7 @@ void switchToFastPWM(void) {
uint32_t tmpVal = BL_RD_REG(TIMER_BASE, TIMER_TCDR);
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, TIMER_TCDR2, 11);
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, TIMER_TCDR2, 20);
BL_WR_REG(TIMER_BASE, TIMER_TCDR, tmpVal);
}
@@ -150,7 +134,7 @@ void switchToSlowPWM(void) {
uint32_t tmpVal = BL_RD_REG(TIMER_BASE, TIMER_TCDR);
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, TIMER_TCDR2, 22);
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, TIMER_TCDR2, 40);
BL_WR_REG(TIMER_BASE, TIMER_TCDR, tmpVal);
}
@@ -194,11 +178,11 @@ void GPIO_IRQHandler(void) {
bool getFUS302IRQLow() {
// Return true if the IRQ line is still held low
return false;
// return (RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin));
return !gpio_read(FUSB302_IRQ_Pin);
}
uint16_t rescaleADC(const uint16_t value) {
// return value;
// TODO This can be removed once we figure out final op-amp scaling
// return value;
uint32_t temp = value * 33;
uint16_t res = temp / 32;
return res;

View File

@@ -16,10 +16,12 @@
#ifdef __cplusplus
extern "C" {
#endif
void timer0_irq_callback(struct device *dev, void *args, uint32_t size, uint32_t state);
void timer0_comp0_callback(void);
void timer0_comp1_callback(void);
void timer0_comp2_callback(void);
void adc_fifo_irq(void);
void start_adc_misc(void);
void GPIO_IRQHandler(void);
void switchToSlowPWM(void);
#ifdef __cplusplus
}
#endif

View File

@@ -38,20 +38,18 @@ void hardware_init() {
void setup_pwm(void) {
// Setup PWM we use for driving the tip
PWM_CH_CFG_Type cfg = {
PWM_Channel, // channel
PWM_CLK_XCLK, // Clock
PWM_STOP_GRACEFUL, // Stop mode
PWM_POL_NORMAL, // Normal Polarity
50, // Clock Div
100, // Period
0, // Thres 1 - start at beginng
50, // Thres 2 - turn off at 50%
0, // Interrupt pulse count
PWM_Channel, // channel
PWM_CLK_XCLK, // Clock
PWM_STOP_ABRUPT, // Stop mode
PWM_POL_NORMAL, // Normal Polarity
50, // Clock Div
100, // Period
0, // Thres 1 - start at beginng
50, // Thres 2 - turn off at 50%
0, // Interrupt pulse count
};
BL_Err_Type err = PWM_Channel_Init(&cfg);
uint32_t pwm_clk = peripheral_clock_get(PERIPHERAL_CLOCK_PWM);
MSG((char *)"PWM Setup returns %d %d\r\n", err, pwm_clk);
PWM_Channel_Init(&cfg);
PWM_Channel_Disable(PWM_Channel);
}
@@ -61,7 +59,6 @@ const ADC_Chan_Type adc_tip_neg_chans[] = {ADC_CHAN_GND, ADC_CHAN_GND, ADC_CHAN_
static_assert(sizeof(adc_tip_pos_chans) == sizeof(adc_tip_neg_chans));
void setup_adc(void) {
MSG((char *)"Setting up ADC\r\n");
//
ADC_CFG_Type adc_cfg = {};
ADC_FIFO_Cfg_Type adc_fifo_cfg = {};
@@ -70,9 +67,9 @@ void setup_adc(void) {
ADC_IntMask(ADC_INT_ALL, MASK);
adc_cfg.clkDiv = ADC_CLK_DIV_32;
adc_cfg.clkDiv = ADC_CLK_DIV_4;
adc_cfg.vref = ADC_VREF_3P2V;
adc_cfg.resWidth = ADC_DATA_WIDTH_16_WITH_256_AVERAGE;
adc_cfg.resWidth = ADC_DATA_WIDTH_16_WITH_128_AVERAGE;
adc_cfg.inputMode = ADC_INPUT_SINGLE_END;
adc_cfg.v18Sel = ADC_V18_SEL_1P82V;
adc_cfg.v11Sel = ADC_V11_SEL_1P1V;
@@ -102,30 +99,36 @@ void setup_adc(void) {
ADC_FIFO_Clear();
}
struct device *timer0;
void setup_timer_scheduler() {
TIMER_Disable(TIMER_CH0);
timer_register(TIMER0_INDEX, "timer0");
TIMER_CFG_Type cfg = {
TIMER_CH0, // Channel
TIMER_CLKSRC_32K, // Clock source
TIMER_PRELOAD_TRIG_COMP2, // Trigger
TIMER_COUNT_PRELOAD, // Counter mode
22, // Clock div
(uint16_t)(powerPWM + holdoffTicks), // CH0 compare (adc)
0, // CH1 compare (pwm out)
(uint16_t)(powerPWM + tempMeasureTicks + holdoffTicks), // CH2 comapre (total period)
0, // Preload
};
TIMER_Init(&cfg);
timer0 = device_find("timer0");
Timer_Int_Callback_Install(TIMER_CH0, TIMER_INT_COMP_0, timer0_comp0_callback);
Timer_Int_Callback_Install(TIMER_CH0, TIMER_INT_COMP_1, timer0_comp1_callback);
Timer_Int_Callback_Install(TIMER_CH0, TIMER_INT_COMP_2, timer0_comp2_callback);
if (timer0) {
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_0);
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_1);
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_2);
device_open(timer0, DEVICE_OFLAG_INT_TX); /* 1s,2s,3s timing*/
// Set interrupt handler
device_set_callback(timer0, timer0_irq_callback);
// Enable both interrupts (0 and 1)
device_control(timer0, DEVICE_CTRL_SET_INT, (void *)(TIMER_COMP0_IT | TIMER_COMP1_IT | TIMER_COMP2_IT));
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_0, 255 + 10 - 2); // Channel 0 is used to trigger the ADC
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_1, 128 - 2);
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_2, (255 + 10 + 10) - 2); // We are using compare 2 to set the max duration of the timer
TIMER_SetPreloadValue(TIMER_CH0, 0);
TIMER_SetCountMode(TIMER_CH0, TIMER_COUNT_PRELOAD);
} else {
MSG((char *)"timer device open failed! \n");
}
TIMER_IntMask(TIMER_CH0, TIMER_INT_COMP_0, UNMASK);
TIMER_IntMask(TIMER_CH0, TIMER_INT_COMP_1, UNMASK);
TIMER_IntMask(TIMER_CH0, TIMER_INT_COMP_2, UNMASK);
CPU_Interrupt_Enable(TIMER_CH0_IRQn);
TIMER_Enable(TIMER_CH0);
// switchToSlowPWM();
}
void setupFUSBIRQ() {

View File

@@ -18,7 +18,6 @@ extern "C" {
#include "bl702_timer.h"
#include "hal_adc.h"
#include "hal_clock.h"
#include "hal_timer.h"
}
#ifdef __cplusplus
extern "C" {

View File

@@ -1,97 +0,0 @@
/**
* @file hal_timer.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#ifndef __HAL_TIMER__H__
#define __HAL_TIMER__H__
#ifdef __cplusplus
extern "C"{
#endif
#include "hal_common.h"
#include "drv_device.h"
#include "bl702_config.h"
enum timer_index_type {
#ifdef BSP_USING_TIMER0
TIMER0_INDEX,
#endif
#ifdef BSP_USING_TIMER1
TIMER1_INDEX,
#endif
TIMER_MAX_INDEX
};
enum timer_preload_trigger_type {
TIMER_PRELOAD_TRIGGER_NONE,
TIMER_PRELOAD_TRIGGER_COMP0,
TIMER_PRELOAD_TRIGGER_COMP1,
TIMER_PRELOAD_TRIGGER_COMP2,
};
enum timer_cnt_mode_type {
TIMER_CNT_PRELOAD,
TIMER_CNT_FREERUN,
};
enum timer_compare_id_type {
TIMER_COMPARE_ID_0,
TIMER_COMPARE_ID_1,
TIMER_COMPARE_ID_2,
};
enum timer_it_type {
TIMER_COMP0_IT = 1 << 0,
TIMER_COMP1_IT = 1 << 1,
TIMER_COMP2_IT = 1 << 2,
};
enum timer_event_type {
TIMER_EVENT_COMP0,
TIMER_EVENT_COMP1,
TIMER_EVENT_COMP2,
TIMER_EVENT_UNKNOWN
};
typedef struct timer_timeout_cfg {
enum timer_compare_id_type timeout_id;
uint32_t timeout_val;
} timer_timeout_cfg_t;
typedef struct timer_device {
struct device parent;
uint8_t id;
enum timer_cnt_mode_type cnt_mode;
enum timer_preload_trigger_type trigger;
uint32_t reload;
uint32_t timeout1;
uint32_t timeout2;
uint32_t timeout3;
} timer_device_t;
#define TIMER_DEV(dev) ((timer_device_t *)dev)
int timer_register(enum timer_index_type index, const char *name);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,373 +0,0 @@
/**
* @file hal_timer.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#include "hal_timer.h"
#include "bl702_glb.h"
#include "bl702_timer.h"
#include "hal_clock.h"
#ifdef BSP_USING_TIMER0
void TIMER0_IRQ(void);
#endif
#ifdef BSP_USING_TIMER1
void TIMER1_IRQ(void);
#endif
static timer_device_t timerx_device[TIMER_MAX_INDEX] = {
#ifdef BSP_USING_TIMER0
TIMER0_CONFIG,
#endif
#ifdef BSP_USING_TIMER1
TIMER1_CONFIG,
#endif
};
/**
* @brief
*
* @param dev
* @param oflag
* @return int
*/
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;
/* 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));
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);
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 (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;
/* 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);
/* 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_INT_TX) {
#ifdef BSP_USING_TIMER0
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
}
/* Enable timer */
TIMER_Enable(timer_device->id);
return 0;
}
/**
* @brief
*
* @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;
}
/**
* @brief
*
* @param dev
* @param cmd
* @param args
* @return int
*/
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);
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;
}
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
*
* @param index
* @param name
* @return int
*/
int timer_register(enum timer_index_type index, const char *name) {
struct device *dev;
if (TIMER_MAX_INDEX == 0) {
return -DEVICE_EINVAL;
}
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->type = DEVICE_CLASS_TIMER;
dev->handle = NULL;
return device_register(dev, name);
}
void timer_isr(timer_device_t *handle) {
uint32_t intId = 0;
uint32_t tmpVal = 0;
uint32_t tmpAddr = 0;
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);
/* 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 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
/**
* @brief
*
*/
void TIMER0_IRQ(void) { timer_isr(&timerx_device[TIMER0_INDEX]); }
#endif
#ifdef BSP_USING_TIMER1
/**
* @brief
*
*/
void TIMER1_IRQ(void) { timer_isr(&timerx_device[TIMER1_INDEX]); }
#endif

View File

@@ -572,23 +572,23 @@ BL_Err_Type I2C_MasterReceiveBlocking(I2C_ID_Type i2cNo, I2C_Transfer_Cfg *cfg)
I2C_Init(i2cNo, I2C_READ, cfg);
I2C_Enable(i2cNo);
timeOut = I2C_FIFO_STATUS_TIMEOUT;
if (cfg->dataSize == 0 && cfg->subAddrSize == 0) {
while (BL_RD_REG(I2C_BASE, I2C_BUS_BUSY)) {
timeOut--;
while (BL_RD_REG(I2C_BASE, I2C_BUS_BUSY)) {
timeOut--;
if (timeOut == 0) {
I2C_Disable(i2cNo);
return TIMEOUT;
}
}
if (timeOut == 0) {
temp = BL_RD_REG(I2C_BASE, I2C_INT_STS); // TODO this sucks as a workaround
if (BL_IS_REG_BIT_SET(temp, I2C_NAK_INT)) {
temp = BL_RD_REG(I2C_BASE, I2C_BUS_BUSY);
I2C_Disable(i2cNo);
MSG((char *)"I2C BSY\r\n");
return TIMEOUT;
}
}
temp = BL_RD_REG(I2C_BASE, I2C_INT_STS); // TODO this sucks as a workaround
if (BL_IS_REG_BIT_SET(temp, I2C_NAK_INT)) {
temp = BL_RD_REG(I2C_BASE, I2C_BUS_BUSY);
MSG((char *)"I2C NACK\r\n");
I2C_Disable(i2cNo);
return TIMEOUT;
}
/* Read I2C data */
while (cfg->dataSize - i >= 4) {
timeOut = I2C_FIFO_STATUS_TIMEOUT;

View File

@@ -32,28 +32,32 @@
#define BSP_FCLK_DIV 0
#define BSP_BCLK_DIV 1
#define BSP_UART_CLOCK_SOURCE ROOT_CLOCK_SOURCE_PLL_96M
#define BSP_UART_CLOCK_DIV 0
#define BSP_I2C_CLOCK_SOURCE ROOT_CLOCK_SOURCE_BCLK
#define BSP_I2C_CLOCK_DIV 0
#define BSP_SPI_CLOCK_SOURCE ROOT_CLOCK_SOURCE_BCLK
#define BSP_SPI_CLOCK_DIV 0
#define BSP_TIMER0_CLOCK_SOURCE ROOT_CLOCK_SOURCE_32K_CLK
#define BSP_TIMER0_CLOCK_DIV 22
#define BSP_TIMER1_CLOCK_SOURCE ROOT_CLOCK_SOURCE_32K_CLK
#define BSP_TIMER1_CLOCK_DIV 31
#define BSP_WDT_CLOCK_SOURCE ROOT_CLOCK_SOURCE_FCLK
#define BSP_WDT_CLOCK_DIV 0
#define BSP_PWM_CLOCK_SOURCE ROOT_CLOCK_SOURCE_XCLK
#define BSP_PWM_CLOCK_DIV 22
#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 255
#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
#define BSP_CAM_CLOCK_DIV 3
#define BSP_UART_CLOCK_SOURCE ROOT_CLOCK_SOURCE_PLL_96M
#define BSP_UART_CLOCK_DIV 0
#define BSP_I2C_CLOCK_SOURCE ROOT_CLOCK_SOURCE_BCLK
#define BSP_I2C_CLOCK_DIV 0
#define BSP_SPI_CLOCK_SOURCE ROOT_CLOCK_SOURCE_BCLK
#define BSP_SPI_CLOCK_DIV 0
#define BSP_TIMER0_CLOCK_SOURCE ROOT_CLOCK_SOURCE_32K_CLK
#define BSP_TIMER0_CLOCK_DIV 22
#define BSP_TIMER1_CLOCK_SOURCE ROOT_CLOCK_SOURCE_32K_CLK
#define BSP_TIMER1_CLOCK_DIV 31
#define BSP_WDT_CLOCK_SOURCE ROOT_CLOCK_SOURCE_32K_CLK
#define BSP_WDT_CLOCK_DIV 32
#define BSP_PWM_CLOCK_SOURCE ROOT_CLOCK_SOURCE_XCLK
#define BSP_PWM_CLOCK_DIV 22
#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 16
#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
#define BSP_CAM_CLOCK_DIV 3
#define BSP_QDEC_KEYSCAN_CLOCK_SOURCE ROOT_CLOCK_SOURCE_XCLK
#define BSP_QDEC_KEYSCAN_CLOCK_DIV 31