bring in all the atmel studio stuff

This commit is contained in:
Joey Castillo
2021-07-20 16:26:54 -04:00
parent bc1ee49d80
commit b4b81f476c
249 changed files with 137720 additions and 36817 deletions

View File

@@ -0,0 +1,769 @@
/**
* \file
*
* \brief SAM Analog Digital Converter
*
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <hpl_adc_async.h>
#include <hpl_adc_dma.h>
#include <hpl_adc_sync.h>
#include <utils_assert.h>
#include <utils_repeat_macro.h>
#include <hpl_adc_config.h>
#ifndef CONF_ADC_0_ENABLE
#define CONF_ADC_0_ENABLE 0
#endif
#ifndef CONF_ADC_1_ENABLE
#define CONF_ADC_1_ENABLE 0
#endif
/**
* \brief Macro is used to fill ADC configuration structure based on its number
*
* \param[in] n The number of structures
*/
#define ADC_CONFIGURATION(n) \
{ \
(n), \
(CONF_ADC_##n##_RUNSTDBY << ADC_CTRLA_RUNSTDBY_Pos) | (CONF_ADC_##n##_ONDEMAND << ADC_CTRLA_ONDEMAND_Pos), \
ADC_CTRLB_PRESCALER(CONF_ADC_##n##_PRESCALER), \
(CONF_ADC_##n##_REFCOMP << ADC_REFCTRL_REFCOMP_Pos) | ADC_REFCTRL_REFSEL(CONF_ADC_##n##_REFSEL), \
(CONF_ADC_##n##_WINMONEO << ADC_EVCTRL_WINMONEO_Pos) \
| (CONF_ADC_##n##_RESRDYEO << ADC_EVCTRL_RESRDYEO_Pos) \
| (CONF_ADC_##n##_STARTINV << ADC_EVCTRL_STARTINV_Pos) \
| (CONF_ADC_##n##_FLUSHINV << ADC_EVCTRL_FLUSHINV_Pos) \
| (CONF_ADC_##n##_STARTEI << ADC_EVCTRL_STARTEI_Pos) \
| (CONF_ADC_##n##_FLUSHEI << ADC_EVCTRL_FLUSHEI_Pos), \
ADC_INPUTCTRL_MUXNEG(CONF_ADC_##n##_MUXNEG) | ADC_INPUTCTRL_MUXPOS(CONF_ADC_##n##_MUXPOS), \
ADC_CTRLC_WINMODE(CONF_ADC_##n##_WINMODE) | ADC_CTRLC_RESSEL(CONF_ADC_##n##_RESSEL) \
| (CONF_ADC_##n##_CORREN << ADC_CTRLC_CORREN_Pos) | (CONF_ADC_##n##_FREERUN << ADC_CTRLC_FREERUN_Pos) \
| (CONF_ADC_##n##_LEFTADJ << ADC_CTRLC_LEFTADJ_Pos) \
| (CONF_ADC_##n##_DIFFMODE << ADC_CTRLC_DIFFMODE_Pos), \
ADC_AVGCTRL_ADJRES(CONF_ADC_##n##_ADJRES) | ADC_AVGCTRL_SAMPLENUM(CONF_ADC_##n##_SAMPLENUM), \
(CONF_ADC_##n##_OFFCOMP << ADC_SAMPCTRL_OFFCOMP_Pos) | ADC_SAMPCTRL_SAMPLEN(CONF_ADC_##n##_SAMPLEN), \
ADC_WINLT_WINLT(CONF_ADC_##n##_WINLT), ADC_WINUT_WINUT(CONF_ADC_##n##_WINUT), \
ADC_GAINCORR_GAINCORR(CONF_ADC_##n##_GAINCORR), ADC_OFFSETCORR_OFFSETCORR(CONF_ADC_##n##_OFFSETCORR), \
CONF_ADC_##n##_DBGRUN << ADC_DBGCTRL_DBGRUN_Pos, ADC_SEQCTRL_SEQEN(CONF_ADC_##n##_SEQEN), \
}
/**
* \brief ADC configuration
*/
struct adc_configuration {
uint8_t number;
hri_adc_ctrla_reg_t ctrl_a;
hri_adc_ctrlb_reg_t ctrl_b;
hri_adc_refctrl_reg_t ref_ctrl;
hri_adc_evctrl_reg_t ev_ctrl;
hri_adc_inputctrl_reg_t input_ctrl;
hri_adc_ctrlc_reg_t ctrl_c;
hri_adc_avgctrl_reg_t avg_ctrl;
hri_adc_sampctrl_reg_t samp_ctrl;
hri_adc_winlt_reg_t win_lt;
hri_adc_winut_reg_t win_ut;
hri_adc_gaincorr_reg_t gain_corr;
hri_adc_offsetcorr_reg_t offset_corr;
hri_adc_dbgctrl_reg_t dbg_ctrl;
hri_adc_seqctrl_reg_t seq_ctrl;
};
#define ADC_AMOUNT (CONF_ADC_0_ENABLE + CONF_ADC_1_ENABLE)
/**
* \brief Array of ADC configurations
*/
static const struct adc_configuration _adcs[] = {
#if CONF_ADC_0_ENABLE == 1
ADC_CONFIGURATION(0),
#endif
#if CONF_ADC_1_ENABLE == 1
ADC_CONFIGURATION(1),
#endif
};
static void _adc_set_reference_source(void *const hw, const adc_reference_t reference);
/**
* \brief Retrieve ordinal number of the given adc hardware instance
*/
static uint8_t _adc_get_hardware_index(const void *const hw)
{
(void)hw;
return 0;
}
/** \brief Return the pointer to register settings of specific ADC
* \param[in] hw_addr The hardware register base address.
* \return Pointer to register settings of specific ADC.
*/
static uint8_t _adc_get_regs(const uint32_t hw_addr)
{
uint8_t n = _adc_get_hardware_index((const void *)hw_addr);
uint8_t i;
for (i = 0; i < sizeof(_adcs) / sizeof(struct adc_configuration); i++) {
if (_adcs[i].number == n) {
return i;
}
}
ASSERT(false);
return 0;
}
/**
* \brief Retrieve IRQ number for the given hardware instance
*/
static uint8_t _adc_get_irq_num(const struct _adc_async_device *const device)
{
(void)device;
return ADC_IRQn;
}
/**
* \brief Init irq param with the given afec hardware instance
*/
static void _adc_init_irq_param(const void *const hw, struct _adc_async_device *dev)
{
}
/**
* \brief Initialize ADC
*
* \param[in] hw The pointer to hardware instance
* \param[in] i The number of hardware instance
*/
static int32_t _adc_init(void *const hw, const uint8_t i)
{
uint16_t calib_reg = 0;
calib_reg = ADC_CALIB_BIASREFBUF((*(uint32_t *)ADC_FUSES_BIASREFBUF_ADDR >> ADC_FUSES_BIASREFBUF_Pos))
| ADC_CALIB_BIASCOMP((*(uint32_t *)ADC_FUSES_BIASCOMP_ADDR >> ADC_FUSES_BIASCOMP_Pos));
ASSERT(hw == ADC);
if (!hri_adc_is_syncing(hw, ADC_SYNCBUSY_SWRST)) {
if (hri_adc_get_CTRLA_reg(hw, ADC_CTRLA_ENABLE)) {
hri_adc_clear_CTRLA_ENABLE_bit(hw);
hri_adc_wait_for_sync(hw, ADC_SYNCBUSY_ENABLE);
}
hri_adc_write_CTRLA_reg(hw, ADC_CTRLA_SWRST);
}
hri_adc_wait_for_sync(hw, ADC_SYNCBUSY_SWRST);
hri_adc_write_CALIB_reg(hw, calib_reg);
hri_adc_write_CTRLB_reg(hw, _adcs[i].ctrl_b);
hri_adc_write_REFCTRL_reg(hw, _adcs[i].ref_ctrl);
hri_adc_write_EVCTRL_reg(hw, _adcs[i].ev_ctrl);
hri_adc_write_INPUTCTRL_reg(hw, _adcs[i].input_ctrl);
hri_adc_write_CTRLC_reg(hw, _adcs[i].ctrl_c);
hri_adc_write_AVGCTRL_reg(hw, _adcs[i].avg_ctrl);
hri_adc_write_SAMPCTRL_reg(hw, _adcs[i].samp_ctrl);
hri_adc_write_WINLT_reg(hw, _adcs[i].win_lt);
hri_adc_write_WINUT_reg(hw, _adcs[i].win_ut);
hri_adc_write_GAINCORR_reg(hw, _adcs[i].gain_corr);
hri_adc_write_OFFSETCORR_reg(hw, _adcs[i].offset_corr);
hri_adc_write_DBGCTRL_reg(hw, _adcs[i].dbg_ctrl);
hri_adc_write_SEQCTRL_reg(hw, _adcs[i].seq_ctrl);
hri_adc_write_CTRLA_reg(hw, _adcs[i].ctrl_a);
return ERR_NONE;
}
/**
* \brief De-initialize ADC
*
* \param[in] hw The pointer to hardware instance
*/
static inline void _adc_deinit(void *hw)
{
hri_adc_clear_CTRLA_ENABLE_bit(hw);
hri_adc_set_CTRLA_SWRST_bit(hw);
}
/**
* \brief Initialize ADC
*/
int32_t _adc_sync_init(struct _adc_sync_device *const device, void *const hw)
{
ASSERT(device);
device->hw = hw;
return _adc_init(hw, _adc_get_regs((uint32_t)hw));
}
/**
* \brief Initialize ADC
*/
int32_t _adc_async_init(struct _adc_async_device *const device, void *const hw)
{
int32_t init_status;
ASSERT(device);
init_status = _adc_init(hw, _adc_get_regs((uint32_t)hw));
if (init_status) {
return init_status;
}
device->hw = hw;
_adc_init_irq_param(hw, device);
NVIC_DisableIRQ(_adc_get_irq_num(device));
NVIC_ClearPendingIRQ(_adc_get_irq_num(device));
NVIC_EnableIRQ(_adc_get_irq_num(device));
return ERR_NONE;
}
/**
* \brief Initialize ADC
*/
int32_t _adc_dma_init(struct _adc_dma_device *const device, void *const hw)
{
ASSERT(device);
device->hw = hw;
return _adc_init(hw, _adc_get_regs((uint32_t)hw));
}
/**
* \brief De-initialize ADC
*/
void _adc_sync_deinit(struct _adc_sync_device *const device)
{
_adc_deinit(device->hw);
}
/**
* \brief De-initialize ADC
*/
void _adc_async_deinit(struct _adc_async_device *const device)
{
NVIC_DisableIRQ(_adc_get_irq_num(device));
NVIC_ClearPendingIRQ(_adc_get_irq_num(device));
_adc_deinit(device->hw);
}
/**
* \brief De-initialize ADC
*/
void _adc_dma_deinit(struct _adc_dma_device *const device)
{
_adc_deinit(device->hw);
}
/**
* \brief Enable ADC
*/
void _adc_sync_enable_channel(struct _adc_sync_device *const device, const uint8_t channel)
{
(void)channel;
hri_adc_set_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Enable ADC
*/
void _adc_async_enable_channel(struct _adc_async_device *const device, const uint8_t channel)
{
(void)channel;
hri_adc_set_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Enable ADC
*/
void _adc_dma_enable_channel(struct _adc_dma_device *const device, const uint8_t channel)
{
(void)channel;
hri_adc_set_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Disable ADC
*/
void _adc_sync_disable_channel(struct _adc_sync_device *const device, const uint8_t channel)
{
(void)channel;
hri_adc_clear_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Disable ADC
*/
void _adc_async_disable_channel(struct _adc_async_device *const device, const uint8_t channel)
{
(void)channel;
hri_adc_clear_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Disable ADC
*/
void _adc_dma_disable_channel(struct _adc_dma_device *const device, const uint8_t channel)
{
(void)channel;
hri_adc_clear_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Return address of ADC DMA source
*/
uint32_t _adc_get_source_for_dma(struct _adc_dma_device *const device)
{
return (uint32_t) & (((Adc *)(device->hw))->RESULT.reg);
}
/**
* \brief Retrieve ADC conversion data size
*/
uint8_t _adc_sync_get_data_size(const struct _adc_sync_device *const device)
{
return hri_adc_read_CTRLC_RESSEL_bf(device->hw) == ADC_CTRLC_RESSEL_8BIT_Val ? 1 : 2;
}
/**
* \brief Retrieve ADC conversion data size
*/
uint8_t _adc_async_get_data_size(const struct _adc_async_device *const device)
{
return hri_adc_read_CTRLC_RESSEL_bf(device->hw) == ADC_CTRLC_RESSEL_8BIT_Val ? 1 : 2;
}
/**
* \brief Retrieve ADC conversion data size
*/
uint8_t _adc_dma_get_data_size(const struct _adc_dma_device *const device)
{
return hri_adc_read_CTRLC_RESSEL_bf(device->hw) == ADC_CTRLC_RESSEL_8BIT_Val ? 1 : 2;
}
/**
* \brief Check if conversion is done
*/
bool _adc_sync_is_channel_conversion_done(const struct _adc_sync_device *const device, const uint8_t channel)
{
(void)channel;
return hri_adc_get_interrupt_RESRDY_bit(device->hw);
}
/**
* \brief Check if conversion is done
*/
bool _adc_async_is_channel_conversion_done(const struct _adc_async_device *const device, const uint8_t channel)
{
(void)channel;
return hri_adc_get_interrupt_RESRDY_bit(device->hw);
}
/**
* \brief Check if conversion is done
*/
bool _adc_dma_is_conversion_done(const struct _adc_dma_device *const device)
{
return hri_adc_get_interrupt_RESRDY_bit(device->hw);
}
/**
* \brief Make conversion
*/
void _adc_sync_convert(struct _adc_sync_device *const device)
{
hri_adc_set_SWTRIG_START_bit(device->hw);
}
/**
* \brief Make conversion
*/
void _adc_async_convert(struct _adc_async_device *const device)
{
hri_adc_set_SWTRIG_START_bit(device->hw);
}
/**
* \brief Make conversion
*/
void _adc_dma_convert(struct _adc_dma_device *const device)
{
hri_adc_set_SWTRIG_START_bit(device->hw);
}
/**
* \brief Retrieve the conversion result
*/
uint16_t _adc_sync_read_channel_data(const struct _adc_sync_device *const device, const uint8_t channel)
{
(void)channel;
return hri_adc_read_RESULT_reg(device->hw);
}
/**
* \brief Retrieve the conversion result
*/
uint16_t _adc_async_read_channel_data(const struct _adc_async_device *const device, const uint8_t channel)
{
(void)channel;
return hri_adc_read_RESULT_reg(device->hw);
}
/**
* \brief Set reference source
*/
void _adc_sync_set_reference_source(struct _adc_sync_device *const device, const adc_reference_t reference)
{
_adc_set_reference_source(device->hw, reference);
}
/**
* \brief Set reference source
*/
void _adc_async_set_reference_source(struct _adc_async_device *const device, const adc_reference_t reference)
{
_adc_set_reference_source(device->hw, reference);
}
/**
* \brief Set reference source
*/
void _adc_dma_set_reference_source(struct _adc_dma_device *const device, const adc_reference_t reference)
{
_adc_set_reference_source(device->hw, reference);
}
/**
* \brief Set resolution
*/
void _adc_sync_set_resolution(struct _adc_sync_device *const device, const adc_resolution_t resolution)
{
hri_adc_write_CTRLC_RESSEL_bf(device->hw, resolution);
}
/**
* \brief Set resolution
*/
void _adc_async_set_resolution(struct _adc_async_device *const device, const adc_resolution_t resolution)
{
hri_adc_write_CTRLC_RESSEL_bf(device->hw, resolution);
}
/**
* \brief Set resolution
*/
void _adc_dma_set_resolution(struct _adc_dma_device *const device, const adc_resolution_t resolution)
{
hri_adc_write_CTRLC_RESSEL_bf(device->hw, resolution);
}
/**
* \brief Set channels input sources
*/
void _adc_sync_set_inputs(struct _adc_sync_device *const device, const adc_pos_input_t pos_input,
const adc_neg_input_t neg_input, const uint8_t channel)
{
(void)channel;
hri_adc_write_INPUTCTRL_MUXPOS_bf(device->hw, pos_input);
hri_adc_write_INPUTCTRL_MUXNEG_bf(device->hw, neg_input);
}
/**
* \brief Set channels input sources
*/
void _adc_async_set_inputs(struct _adc_async_device *const device, const adc_pos_input_t pos_input,
const adc_neg_input_t neg_input, const uint8_t channel)
{
(void)channel;
hri_adc_write_INPUTCTRL_MUXPOS_bf(device->hw, pos_input);
hri_adc_write_INPUTCTRL_MUXNEG_bf(device->hw, neg_input);
}
/**
* \brief Set channels input source
*/
void _adc_dma_set_inputs(struct _adc_dma_device *const device, const adc_pos_input_t pos_input,
const adc_neg_input_t neg_input, const uint8_t channel)
{
(void)channel;
hri_adc_write_INPUTCTRL_MUXPOS_bf(device->hw, pos_input);
hri_adc_write_INPUTCTRL_MUXNEG_bf(device->hw, neg_input);
}
/**
* \brief Set thresholds
*/
void _adc_sync_set_thresholds(struct _adc_sync_device *const device, const adc_threshold_t low_threshold,
const adc_threshold_t up_threshold)
{
hri_adc_write_WINLT_reg(device->hw, low_threshold);
hri_adc_write_WINUT_reg(device->hw, up_threshold);
}
/**
* \brief Set thresholds
*/
void _adc_async_set_thresholds(struct _adc_async_device *const device, const adc_threshold_t low_threshold,
const adc_threshold_t up_threshold)
{
hri_adc_write_WINLT_reg(device->hw, low_threshold);
hri_adc_write_WINUT_reg(device->hw, up_threshold);
}
/**
* \brief Set thresholds
*/
void _adc_dma_set_thresholds(struct _adc_dma_device *const device, const adc_threshold_t low_threshold,
const adc_threshold_t up_threshold)
{
hri_adc_write_WINLT_reg(device->hw, low_threshold);
hri_adc_write_WINUT_reg(device->hw, up_threshold);
}
/**
* \brief Set gain
*/
void _adc_sync_set_channel_gain(struct _adc_sync_device *const device, const uint8_t channel, const adc_gain_t gain)
{
(void)device, (void)channel, (void)gain;
}
/**
* \brief Set gain
*/
void _adc_async_set_channel_gain(struct _adc_async_device *const device, const uint8_t channel, const adc_gain_t gain)
{
(void)device, (void)channel, (void)gain;
}
/**
* \brief Set gain
*/
void _adc_dma_set_channel_gain(struct _adc_dma_device *const device, const uint8_t channel, const adc_gain_t gain)
{
(void)device, (void)channel, (void)gain;
}
/**
* \brief Set conversion mode
*/
void _adc_sync_set_conversion_mode(struct _adc_sync_device *const device, const enum adc_conversion_mode mode)
{
if (ADC_CONVERSION_MODE_FREERUN == mode) {
hri_adc_set_CTRLC_FREERUN_bit(device->hw);
} else {
hri_adc_clear_CTRLC_FREERUN_bit(device->hw);
}
}
/**
* \brief Set conversion mode
*/
void _adc_async_set_conversion_mode(struct _adc_async_device *const device, const enum adc_conversion_mode mode)
{
if (ADC_CONVERSION_MODE_FREERUN == mode) {
hri_adc_set_CTRLC_FREERUN_bit(device->hw);
} else {
hri_adc_clear_CTRLC_FREERUN_bit(device->hw);
}
}
/**
* \brief Set conversion mode
*/
void _adc_dma_set_conversion_mode(struct _adc_dma_device *const device, const enum adc_conversion_mode mode)
{
if (ADC_CONVERSION_MODE_FREERUN == mode) {
hri_adc_set_CTRLC_FREERUN_bit(device->hw);
} else {
hri_adc_clear_CTRLC_FREERUN_bit(device->hw);
}
}
/**
* \brief Set differential mode
*/
void _adc_sync_set_channel_differential_mode(struct _adc_sync_device *const device, const uint8_t channel,
const enum adc_differential_mode mode)
{
(void)channel;
if (ADC_DIFFERENTIAL_MODE_DIFFERENTIAL == mode) {
hri_adc_set_CTRLC_DIFFMODE_bit(device->hw);
} else {
hri_adc_clear_CTRLC_DIFFMODE_bit(device->hw);
}
}
/**
* \brief Set differential mode
*/
void _adc_async_set_channel_differential_mode(struct _adc_async_device *const device, const uint8_t channel,
const enum adc_differential_mode mode)
{
(void)channel;
if (ADC_DIFFERENTIAL_MODE_DIFFERENTIAL == mode) {
hri_adc_set_CTRLC_DIFFMODE_bit(device->hw);
} else {
hri_adc_clear_CTRLC_DIFFMODE_bit(device->hw);
}
}
/**
* \brief Set differential mode
*/
void _adc_dma_set_channel_differential_mode(struct _adc_dma_device *const device, const uint8_t channel,
const enum adc_differential_mode mode)
{
(void)channel;
if (ADC_DIFFERENTIAL_MODE_DIFFERENTIAL == mode) {
hri_adc_set_CTRLC_DIFFMODE_bit(device->hw);
} else {
hri_adc_clear_CTRLC_DIFFMODE_bit(device->hw);
}
}
/**
* \brief Set window mode
*/
void _adc_sync_set_window_mode(struct _adc_sync_device *const device, const adc_window_mode_t mode)
{
hri_adc_write_CTRLC_WINMODE_bf(device->hw, mode);
}
/**
* \brief Set window mode
*/
void _adc_async_set_window_mode(struct _adc_async_device *const device, const adc_window_mode_t mode)
{
hri_adc_write_CTRLC_WINMODE_bf(device->hw, mode);
}
/**
* \brief Set window mode
*/
void _adc_dma_set_window_mode(struct _adc_dma_device *const device, const adc_window_mode_t mode)
{
hri_adc_write_CTRLC_WINMODE_bf(device->hw, mode);
}
/**
* \brief Retrieve threshold state
*/
void _adc_sync_get_threshold_state(const struct _adc_sync_device *const device, adc_threshold_status_t *const state)
{
*state = hri_adc_get_interrupt_WINMON_bit(device->hw);
}
/**
* \brief Retrieve threshold state
*/
void _adc_async_get_threshold_state(const struct _adc_async_device *const device, adc_threshold_status_t *const state)
{
*state = hri_adc_get_interrupt_WINMON_bit(device->hw);
}
/**
* \brief Retrieve threshold state
*/
void _adc_dma_get_threshold_state(const struct _adc_dma_device *const device, adc_threshold_status_t *const state)
{
*state = hri_adc_get_interrupt_WINMON_bit(device->hw);
}
/**
* \brief Enable/disable ADC channel interrupt
*/
void _adc_async_set_irq_state(struct _adc_async_device *const device, const uint8_t channel,
const enum _adc_async_callback_type type, const bool state)
{
(void)channel;
void *const hw = device->hw;
if (ADC_ASYNC_DEVICE_MONITOR_CB == type) {
hri_adc_write_INTEN_WINMON_bit(hw, state);
} else if (ADC_ASYNC_DEVICE_ERROR_CB == type) {
hri_adc_write_INTEN_OVERRUN_bit(hw, state);
} else if (ADC_ASYNC_DEVICE_CONVERT_CB == type) {
hri_adc_write_INTEN_RESRDY_bit(hw, state);
}
}
/**
* \brief Retrieve ADC sync helper functions
*/
void *_adc_get_adc_sync(void)
{
return (void *)NULL;
}
/**
* \brief Retrieve ADC async helper functions
*/
void *_adc_get_adc_async(void)
{
return (void *)NULL;
}
/**
* \brief Set ADC reference source
*
* \param[in] hw The pointer to hardware instance
* \param[in] reference The reference to set
*/
static void _adc_set_reference_source(void *const hw, const adc_reference_t reference)
{
bool enabled = hri_adc_get_CTRLA_ENABLE_bit(hw);
hri_adc_clear_CTRLA_ENABLE_bit(hw);
hri_adc_write_REFCTRL_REFSEL_bf(hw, reference);
if (enabled) {
hri_adc_set_CTRLA_ENABLE_bit(hw);
}
}

View File

@@ -0,0 +1,72 @@
/**
* \file
*
* \brief ADC related functionality declaration.
*
* Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _HPL_ADC_ADC_H_INCLUDED
#define _HPL_ADC_ADC_H_INCLUDED
#include <hpl_adc_sync.h>
#include <hpl_adc_async.h>
/**
* \addtogroup HPL ADC
*
* \section hpl_adc_rev Revision History
* - v1.0.0 Initial Release
*
*@{
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \name HPL functions
*/
//@{
/**
* \brief Retrieve ADC helper functions
*
* \return A pointer to set of ADC helper functions
*/
void *_adc_get_adc_sync(void);
void *_adc_get_adc_async(void);
//@}
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _HPL_USART_UART_H_INCLUDED */

View File

@@ -0,0 +1,200 @@
/**
* \file
*
* \brief Core related functionality implementation.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <hpl_core.h>
#include <hpl_irq.h>
#include <hpl_reset.h>
#include <hpl_sleep.h>
#include <hpl_delay.h>
#ifndef _UNIT_TEST_
#include <utils.h>
#endif
#include <utils_assert.h>
#include <peripheral_clk_config.h>
#ifndef CONF_CPU_FREQUENCY
#define CONF_CPU_FREQUENCY 1000000
#endif
#if CONF_CPU_FREQUENCY < 1000
#define CPU_FREQ_POWER 3
#elif CONF_CPU_FREQUENCY < 10000
#define CPU_FREQ_POWER 4
#elif CONF_CPU_FREQUENCY < 100000
#define CPU_FREQ_POWER 5
#elif CONF_CPU_FREQUENCY < 1000000
#define CPU_FREQ_POWER 6
#elif CONF_CPU_FREQUENCY < 10000000
#define CPU_FREQ_POWER 7
#elif CONF_CPU_FREQUENCY < 100000000
#define CPU_FREQ_POWER 8
#endif
/**
* \brief The array of interrupt handlers
*/
struct _irq_descriptor *_irq_table[PERIPH_COUNT_IRQn];
/**
* \brief Reset MCU
*/
void _reset_mcu(void)
{
NVIC_SystemReset();
}
/**
* \brief Put MCU to sleep
*/
void _go_to_sleep(void)
{
__DSB();
__WFI();
}
/**
* \brief Retrieve current IRQ number
*/
uint8_t _irq_get_current(void)
{
return (uint8_t)__get_IPSR() - 16;
}
/**
* \brief Disable the given IRQ
*/
void _irq_disable(uint8_t n)
{
NVIC_DisableIRQ((IRQn_Type)n);
}
/**
* \brief Set the given IRQ
*/
void _irq_set(uint8_t n)
{
NVIC_SetPendingIRQ((IRQn_Type)n);
}
/**
* \brief Clear the given IRQ
*/
void _irq_clear(uint8_t n)
{
NVIC_ClearPendingIRQ((IRQn_Type)n);
}
/**
* \brief Enable the given IRQ
*/
void _irq_enable(uint8_t n)
{
NVIC_EnableIRQ((IRQn_Type)n);
}
/**
* \brief Register IRQ handler
*/
void _irq_register(const uint8_t n, struct _irq_descriptor *const irq)
{
ASSERT(n < PERIPH_COUNT_IRQn);
_irq_table[n] = irq;
}
/**
* \brief Default interrupt handler for unused IRQs.
*/
void Default_Handler(void)
{
while (1) {
}
}
/**
* \brief Retrieve the amount of cycles to delay for the given amount of us
*/
static inline uint32_t _get_cycles_for_us_internal(const uint16_t us, const uint32_t freq, const uint8_t power)
{
switch (power) {
case 8:
return (us * (freq / 100000) - 1) / 10 + 1;
case 7:
return (us * (freq / 10000) - 1) / 100 + 1;
case 6:
return (us * (freq / 1000) - 1) / 1000 + 1;
case 5:
return (us * (freq / 100) - 1) / 10000 + 1;
case 4:
return (us * (freq / 10) - 1) / 100000 + 1;
default:
return (us * freq - 1) / 1000000 + 1;
}
}
/**
* \brief Retrieve the amount of cycles to delay for the given amount of us
*/
uint32_t _get_cycles_for_us(const uint16_t us)
{
return _get_cycles_for_us_internal(us, CONF_CPU_FREQUENCY, CPU_FREQ_POWER);
}
/**
* \brief Retrieve the amount of cycles to delay for the given amount of ms
*/
static inline uint32_t _get_cycles_for_ms_internal(const uint16_t ms, const uint32_t freq, const uint8_t power)
{
switch (power) {
case 8:
return (ms * (freq / 100000)) * 100;
case 7:
return (ms * (freq / 10000)) * 10;
case 6:
return (ms * (freq / 1000));
case 5:
return (ms * (freq / 100) - 1) / 10 + 1;
case 4:
return (ms * (freq / 10) - 1) / 100 + 1;
default:
return (ms * freq - 1) / 1000 + 1;
}
}
/**
* \brief Retrieve the amount of cycles to delay for the given amount of ms
*/
uint32_t _get_cycles_for_ms(const uint16_t ms)
{
return _get_cycles_for_ms_internal(ms, CONF_CPU_FREQUENCY, CPU_FREQ_POWER);
}

View File

@@ -0,0 +1,61 @@
/**
* \file
*
* \brief Core related functionality implementation.
*
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _HPL_CORE_PORT_H_INCLUDED
#define _HPL_CORE_PORT_H_INCLUDED
#include <peripheral_clk_config.h>
/* It's possible to include this file in ARM ASM files (e.g., in FreeRTOS IAR
* portable implement, portasm.s -> FreeRTOSConfig.h -> hpl_core_port.h),
* there will be assembling errors.
* So the following things are not included for assembling.
*/
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
#ifndef _UNIT_TEST_
#include <compiler.h>
#endif
/**
* \brief Check if it's in ISR handling
* \return \c true if it's in ISR
*/
static inline bool _is_in_isr(void)
{
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk);
}
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
#endif /* _HPL_CORE_PORT_H_INCLUDED */

View File

@@ -0,0 +1,74 @@
/**
* \file
*
* \brief HPL initialization related functionality implementation.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <hpl_gpio.h>
#include <hpl_init.h>
#include <hpl_gclk_base.h>
#include <hpl_mclk_config.h>
#include <hpl_dma.h>
#include <hpl_dmac_config.h>
/* Referenced GCLKs (out of 0~4), should be initialized firstly
*/
#define _GCLK_INIT_1ST 0x00000000
/* Not referenced GCLKs, initialized last */
#define _GCLK_INIT_LAST 0x0000001F
/**
* \brief Initialize the hardware abstraction layer
*/
void _init_chip(void)
{
hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, CONF_NVM_WAIT_STATE);
_set_performance_level(2);
_osc32kctrl_init_sources();
_oscctrl_init_sources();
_mclk_init();
#if _GCLK_INIT_1ST
_gclk_init_generators_by_fref(_GCLK_INIT_1ST);
#endif
_oscctrl_init_referenced_generators();
_gclk_init_generators_by_fref(_GCLK_INIT_LAST);
#if CONF_DMAC_ENABLE
hri_mclk_set_AHBMASK_DMAC_bit(MCLK);
_dma_init();
#endif
#if (CONF_PORT_EVCTRL_PORT_0 | CONF_PORT_EVCTRL_PORT_1 | CONF_PORT_EVCTRL_PORT_2 | CONF_PORT_EVCTRL_PORT_3)
_port_event_init();
#endif
}

View File

@@ -0,0 +1,244 @@
/**
* \file
*
* \brief Generic DMAC related functionality.
*
* Copyright (c) 2016-2019 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <compiler.h>
#include <hpl_dma.h>
#include <hpl_dmac_config.h>
#include <utils.h>
#include <utils_assert.h>
#include <utils_repeat_macro.h>
#if CONF_DMAC_ENABLE
/* Section containing first descriptors for all DMAC channels */
COMPILER_ALIGNED(16)
DmacDescriptor _descriptor_section[DMAC_CH_NUM] SECTION_DMAC_DESCRIPTOR;
/* Section containing current descriptors for all DMAC channels */
COMPILER_ALIGNED(16)
DmacDescriptor _write_back_section[DMAC_CH_NUM] SECTION_DMAC_DESCRIPTOR;
/* Array containing callbacks for DMAC channels */
static struct _dma_resource _resources[DMAC_CH_NUM];
/* This macro DMAC configuration */
#define DMAC_CHANNEL_CFG(i, n) \
{(CONF_DMAC_RUNSTDBY_##n << DMAC_CHCTRLA_RUNSTDBY_Pos) | (CONF_DMAC_ENABLE_##n << DMAC_CHCTRLA_ENABLE_Pos), \
DMAC_CHCTRLB_TRIGACT(CONF_DMAC_TRIGACT_##n) | DMAC_CHCTRLB_TRIGSRC(CONF_DMAC_TRIGSRC_##n) \
| DMAC_CHCTRLB_LVL(CONF_DMAC_LVL_##n) | (CONF_DMAC_EVOE_##n << DMAC_CHCTRLB_EVOE_Pos) \
| (CONF_DMAC_EVIE_##n << DMAC_CHCTRLB_EVIE_Pos) | DMAC_CHCTRLB_EVACT(CONF_DMAC_EVACT_##n), \
DMAC_BTCTRL_STEPSIZE(CONF_DMAC_STEPSIZE_##n) | (CONF_DMAC_STEPSEL_##n << DMAC_BTCTRL_STEPSEL_Pos) \
| (CONF_DMAC_DSTINC_##n << DMAC_BTCTRL_DSTINC_Pos) | (CONF_DMAC_SRCINC_##n << DMAC_BTCTRL_SRCINC_Pos) \
| DMAC_BTCTRL_BEATSIZE(CONF_DMAC_BEATSIZE_##n) | DMAC_BTCTRL_BLOCKACT(CONF_DMAC_BLOCKACT_##n) \
| DMAC_BTCTRL_EVOSEL(CONF_DMAC_EVOSEL_##n)},
/* DMAC channel configuration */
struct dmac_channel_cfg {
uint8_t ctrla;
uint32_t ctrlb;
uint16_t btctrl;
};
/* DMAC channel configurations */
const static struct dmac_channel_cfg _cfgs[] = {REPEAT_MACRO(DMAC_CHANNEL_CFG, i, DMAC_CH_NUM)};
/**
* \brief Initialize DMAC
*/
int32_t _dma_init(void)
{
uint8_t i = 0;
hri_dmac_clear_CTRL_DMAENABLE_bit(DMAC);
hri_dmac_clear_CTRL_CRCENABLE_bit(DMAC);
hri_dmac_set_CHCTRLA_SWRST_bit(DMAC);
hri_dmac_write_CTRL_reg(DMAC,
(CONF_DMAC_LVLEN0 << DMAC_CTRL_LVLEN0_Pos) | (CONF_DMAC_LVLEN1 << DMAC_CTRL_LVLEN1_Pos)
| (CONF_DMAC_LVLEN2 << DMAC_CTRL_LVLEN2_Pos)
| (CONF_DMAC_LVLEN3 << DMAC_CTRL_LVLEN3_Pos));
hri_dmac_write_DBGCTRL_DBGRUN_bit(DMAC, CONF_DMAC_DBGRUN);
hri_dmac_write_QOSCTRL_reg(DMAC,
DMAC_QOSCTRL_WRBQOS(CONF_DMAC_WRBQOS) | DMAC_QOSCTRL_FQOS(CONF_DMAC_FQOS)
| DMAC_QOSCTRL_DQOS(CONF_DMAC_DQOS));
hri_dmac_write_PRICTRL0_reg(
DMAC,
DMAC_PRICTRL0_LVLPRI0(CONF_DMAC_LVLPRI0) | DMAC_PRICTRL0_LVLPRI1(CONF_DMAC_LVLPRI1)
| DMAC_PRICTRL0_LVLPRI2(CONF_DMAC_LVLPRI2) | DMAC_PRICTRL0_LVLPRI3(CONF_DMAC_LVLPRI3)
| (CONF_DMAC_RRLVLEN0 << DMAC_PRICTRL0_RRLVLEN0_Pos) | (CONF_DMAC_RRLVLEN1 << DMAC_PRICTRL0_RRLVLEN1_Pos)
| (CONF_DMAC_RRLVLEN2 << DMAC_PRICTRL0_RRLVLEN2_Pos) | (CONF_DMAC_RRLVLEN3 << DMAC_PRICTRL0_RRLVLEN3_Pos));
hri_dmac_write_BASEADDR_reg(DMAC, (uint32_t)_descriptor_section);
hri_dmac_write_WRBADDR_reg(DMAC, (uint32_t)_write_back_section);
for (; i < DMAC_CH_NUM; i++) {
hri_dmac_write_CHID_reg(DMAC, i);
hri_dmac_write_CHCTRLA_RUNSTDBY_bit(DMAC, _cfgs[i].ctrla & DMAC_CHCTRLA_RUNSTDBY);
hri_dmac_write_CHCTRLB_reg(DMAC, _cfgs[i].ctrlb);
hri_dmacdescriptor_write_BTCTRL_reg(&_descriptor_section[i], _cfgs[i].btctrl);
hri_dmacdescriptor_write_DESCADDR_reg(&_descriptor_section[i], 0x0);
}
NVIC_DisableIRQ(DMAC_IRQn);
NVIC_ClearPendingIRQ(DMAC_IRQn);
NVIC_EnableIRQ(DMAC_IRQn);
hri_dmac_set_CTRL_DMAENABLE_bit(DMAC);
return ERR_NONE;
}
/**
* \brief Enable/disable DMA interrupt
*/
void _dma_set_irq_state(const uint8_t channel, const enum _dma_callback_type type, const bool state)
{
hri_dmac_write_CHID_reg(DMAC, channel);
if (DMA_TRANSFER_COMPLETE_CB == type) {
hri_dmac_write_CHINTEN_TCMPL_bit(DMAC, state);
} else if (DMA_TRANSFER_ERROR_CB == type) {
hri_dmac_write_CHINTEN_TERR_bit(DMAC, state);
}
}
int32_t _dma_set_destination_address(const uint8_t channel, const void *const dst)
{
hri_dmacdescriptor_write_DSTADDR_reg(&_descriptor_section[channel], (uint32_t)dst);
return ERR_NONE;
}
int32_t _dma_set_source_address(const uint8_t channel, const void *const src)
{
hri_dmacdescriptor_write_SRCADDR_reg(&_descriptor_section[channel], (uint32_t)src);
return ERR_NONE;
}
int32_t _dma_set_next_descriptor(const uint8_t current_channel, const uint8_t next_channel)
{
hri_dmacdescriptor_write_DESCADDR_reg(&_descriptor_section[current_channel],
(uint32_t)&_descriptor_section[next_channel]);
return ERR_NONE;
}
int32_t _dma_srcinc_enable(const uint8_t channel, const bool enable)
{
hri_dmacdescriptor_write_BTCTRL_SRCINC_bit(&_descriptor_section[channel], enable);
return ERR_NONE;
}
int32_t _dma_set_data_amount(const uint8_t channel, const uint32_t amount)
{
uint32_t address = hri_dmacdescriptor_read_DSTADDR_reg(&_descriptor_section[channel]);
uint8_t beat_size = hri_dmacdescriptor_read_BTCTRL_BEATSIZE_bf(&_descriptor_section[channel]);
if (hri_dmacdescriptor_get_BTCTRL_DSTINC_bit(&_descriptor_section[channel])) {
hri_dmacdescriptor_write_DSTADDR_reg(&_descriptor_section[channel], address + amount * (1 << beat_size));
}
address = hri_dmacdescriptor_read_SRCADDR_reg(&_descriptor_section[channel]);
if (hri_dmacdescriptor_get_BTCTRL_SRCINC_bit(&_descriptor_section[channel])) {
hri_dmacdescriptor_write_SRCADDR_reg(&_descriptor_section[channel], address + amount * (1 << beat_size));
}
hri_dmacdescriptor_write_BTCNT_reg(&_descriptor_section[channel], amount);
return ERR_NONE;
}
int32_t _dma_enable_transaction(const uint8_t channel, const bool software_trigger)
{
hri_dmac_write_CHID_reg(DMAC, channel);
hri_dmacdescriptor_set_BTCTRL_VALID_bit(&_descriptor_section[channel]);
hri_dmac_set_CHCTRLA_ENABLE_bit(DMAC);
if (software_trigger) {
hri_dmac_set_SWTRIGCTRL_reg(DMAC, 1 << channel);
}
return ERR_NONE;
}
int32_t _dma_get_channel_resource(struct _dma_resource **resource, const uint8_t channel)
{
*resource = &_resources[channel];
return ERR_NONE;
}
int32_t _dma_dstinc_enable(const uint8_t channel, const bool enable)
{
hri_dmacdescriptor_write_BTCTRL_DSTINC_bit(&_descriptor_section[channel], enable);
return ERR_NONE;
}
/**
* \internal DMAC interrupt handler
*/
static inline void _dmac_handler(void)
{
uint8_t channel = hri_dmac_read_INTPEND_ID_bf(DMAC);
uint8_t current_channel = hri_dmac_read_CHID_reg(DMAC);
uint8_t flag_status;
struct _dma_resource *tmp_resource = &_resources[channel];
hri_dmac_write_CHID_reg(DMAC, channel);
flag_status = hri_dmac_get_CHINTFLAG_reg(DMAC, DMAC_CHINTFLAG_MASK);
if (flag_status & DMAC_CHINTFLAG_TERR) {
hri_dmac_clear_CHINTFLAG_TERR_bit(DMAC);
tmp_resource->dma_cb.error(tmp_resource);
} else if (flag_status & DMAC_CHINTFLAG_TCMPL) {
hri_dmac_clear_CHINTFLAG_TCMPL_bit(DMAC);
tmp_resource->dma_cb.transfer_done(tmp_resource);
}
hri_dmac_write_CHID_reg(DMAC, current_channel);
}
/**
* \brief DMAC interrupt handler
*/
void DMAC_Handler(void)
{
_dmac_handler();
}
#endif /* CONF_DMAC_ENABLE */

View File

@@ -0,0 +1,255 @@
/**
* \file
*
* \brief EIC related functionality implementation.
*
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <compiler.h>
#include <hpl_eic_config.h>
#include <hpl_ext_irq.h>
#include <string.h>
#include <utils.h>
#include <utils_assert.h>
#ifdef __MINGW32__
#define ffs __builtin_ffs
#endif
#if defined(__CC_ARM) || defined(__ICCARM__)
/* Find the first bit set */
static int ffs(int v)
{
int i, bit = 1;
for (i = 0; i < sizeof(int) * 8; i++) {
if (v & bit) {
return i + 1;
}
bit <<= 1;
}
return 0;
}
#endif
/**
* \brief Invalid external interrupt and pin numbers
*/
#define INVALID_EXTINT_NUMBER 0xFF
#define INVALID_PIN_NUMBER 0xFFFFFFFF
#ifndef CONFIG_EIC_EXTINT_MAP
/** Dummy mapping to pass compiling. */
#define CONFIG_EIC_EXTINT_MAP \
{ \
INVALID_EXTINT_NUMBER, INVALID_PIN_NUMBER \
}
#endif
#define EXT_IRQ_AMOUNT 3
/**
* \brief EXTINTx and pin number map
*/
struct _eic_map {
uint8_t extint;
uint32_t pin;
};
/**
* \brief PIN and EXTINT map for enabled external interrupts
*/
static const struct _eic_map _map[] = {CONFIG_EIC_EXTINT_MAP};
/**
* \brief The callback to upper layer's interrupt processing routine
*/
static void (*callback)(const uint32_t pin);
static void _ext_irq_handler(void);
/**
* \brief Initialize external interrupt module
*/
int32_t _ext_irq_init(void (*cb)(const uint32_t pin))
{
if (!hri_eic_is_syncing(EIC, EIC_SYNCBUSY_SWRST)) {
if (hri_eic_get_CTRLA_reg(EIC, EIC_CTRLA_ENABLE)) {
hri_eic_clear_CTRLA_ENABLE_bit(EIC);
hri_eic_wait_for_sync(EIC, EIC_SYNCBUSY_ENABLE);
}
hri_eic_write_CTRLA_reg(EIC, EIC_CTRLA_SWRST);
}
hri_eic_wait_for_sync(EIC, EIC_SYNCBUSY_SWRST);
hri_eic_write_CTRLA_CKSEL_bit(EIC, CONF_EIC_CKSEL);
hri_eic_write_NMICTRL_reg(EIC,
(CONF_EIC_NMIFILTEN << EIC_NMICTRL_NMIFILTEN_Pos)
| EIC_NMICTRL_NMISENSE(CONF_EIC_NMISENSE) | EIC_ASYNCH_ASYNCH(CONF_EIC_NMIASYNCH)
| 0);
hri_eic_write_EVCTRL_reg(EIC,
(CONF_EIC_EXTINTEO0 << 0) | (CONF_EIC_EXTINTEO1 << 1) | (CONF_EIC_EXTINTEO2 << 2)
| (CONF_EIC_EXTINTEO3 << 3) | (CONF_EIC_EXTINTEO4 << 4) | (CONF_EIC_EXTINTEO5 << 5)
| (CONF_EIC_EXTINTEO6 << 6) | (CONF_EIC_EXTINTEO7 << 7) | (CONF_EIC_EXTINTEO8 << 8)
| (CONF_EIC_EXTINTEO9 << 9) | (CONF_EIC_EXTINTEO10 << 10) | (CONF_EIC_EXTINTEO11 << 11)
| (CONF_EIC_EXTINTEO12 << 12) | (CONF_EIC_EXTINTEO13 << 13)
| (CONF_EIC_EXTINTEO14 << 14) | (CONF_EIC_EXTINTEO15 << 15) | 0);
hri_eic_write_ASYNCH_reg(EIC,
(CONF_EIC_ASYNCH0 << 0) | (CONF_EIC_ASYNCH1 << 1) | (CONF_EIC_ASYNCH2 << 2)
| (CONF_EIC_ASYNCH3 << 3) | (CONF_EIC_ASYNCH4 << 4) | (CONF_EIC_ASYNCH5 << 5)
| (CONF_EIC_ASYNCH6 << 6) | (CONF_EIC_ASYNCH7 << 7) | (CONF_EIC_ASYNCH8 << 8)
| (CONF_EIC_ASYNCH9 << 9) | (CONF_EIC_ASYNCH10 << 10) | (CONF_EIC_ASYNCH11 << 11)
| (CONF_EIC_ASYNCH12 << 12) | (CONF_EIC_ASYNCH13 << 13) | (CONF_EIC_ASYNCH14 << 14)
| (CONF_EIC_ASYNCH15 << 15) | 0);
hri_eic_write_CONFIG_reg(EIC,
0,
(CONF_EIC_FILTEN0 << EIC_CONFIG_FILTEN0_Pos) | EIC_CONFIG_SENSE0(CONF_EIC_SENSE0)
| (CONF_EIC_FILTEN1 << EIC_CONFIG_FILTEN1_Pos) | EIC_CONFIG_SENSE1(CONF_EIC_SENSE1)
| (CONF_EIC_FILTEN2 << EIC_CONFIG_FILTEN2_Pos) | EIC_CONFIG_SENSE2(CONF_EIC_SENSE2)
| (CONF_EIC_FILTEN3 << EIC_CONFIG_FILTEN3_Pos) | EIC_CONFIG_SENSE3(CONF_EIC_SENSE3)
| (CONF_EIC_FILTEN4 << EIC_CONFIG_FILTEN4_Pos) | EIC_CONFIG_SENSE4(CONF_EIC_SENSE4)
| (CONF_EIC_FILTEN5 << EIC_CONFIG_FILTEN5_Pos) | EIC_CONFIG_SENSE5(CONF_EIC_SENSE5)
| (CONF_EIC_FILTEN6 << EIC_CONFIG_FILTEN6_Pos) | EIC_CONFIG_SENSE6(CONF_EIC_SENSE6)
| (CONF_EIC_FILTEN7 << EIC_CONFIG_FILTEN7_Pos) | EIC_CONFIG_SENSE7(CONF_EIC_SENSE7)
| 0);
hri_eic_write_CONFIG_reg(EIC,
1,
(CONF_EIC_FILTEN8 << EIC_CONFIG_FILTEN0_Pos) | EIC_CONFIG_SENSE0(CONF_EIC_SENSE8)
| (CONF_EIC_FILTEN9 << EIC_CONFIG_FILTEN1_Pos) | EIC_CONFIG_SENSE1(CONF_EIC_SENSE9)
| (CONF_EIC_FILTEN10 << EIC_CONFIG_FILTEN2_Pos) | EIC_CONFIG_SENSE2(CONF_EIC_SENSE10)
| (CONF_EIC_FILTEN11 << EIC_CONFIG_FILTEN3_Pos) | EIC_CONFIG_SENSE3(CONF_EIC_SENSE11)
| (CONF_EIC_FILTEN12 << EIC_CONFIG_FILTEN4_Pos) | EIC_CONFIG_SENSE4(CONF_EIC_SENSE12)
| (CONF_EIC_FILTEN13 << EIC_CONFIG_FILTEN5_Pos) | EIC_CONFIG_SENSE5(CONF_EIC_SENSE13)
| (CONF_EIC_FILTEN14 << EIC_CONFIG_FILTEN6_Pos) | EIC_CONFIG_SENSE6(CONF_EIC_SENSE14)
| (CONF_EIC_FILTEN15 << EIC_CONFIG_FILTEN7_Pos) | EIC_CONFIG_SENSE7(CONF_EIC_SENSE15)
| 0);
hri_eic_set_CTRLA_ENABLE_bit(EIC);
NVIC_DisableIRQ(EIC_IRQn);
NVIC_ClearPendingIRQ(EIC_IRQn);
NVIC_EnableIRQ(EIC_IRQn);
callback = cb;
return ERR_NONE;
}
/**
* \brief De-initialize external interrupt module
*/
int32_t _ext_irq_deinit(void)
{
NVIC_DisableIRQ(EIC_IRQn);
callback = NULL;
hri_eic_clear_CTRLA_ENABLE_bit(EIC);
hri_eic_set_CTRLA_SWRST_bit(EIC);
return ERR_NONE;
}
/**
* \brief Enable / disable external irq
*/
int32_t _ext_irq_enable(const uint32_t pin, const bool enable)
{
uint8_t extint = INVALID_EXTINT_NUMBER;
uint8_t i = 0;
for (; i < ARRAY_SIZE(_map); i++) {
if (_map[i].pin == pin) {
extint = _map[i].extint;
break;
}
}
if (INVALID_EXTINT_NUMBER == extint) {
return -1;
}
if (enable) {
hri_eic_set_INTEN_reg(EIC, 1ul << extint);
} else {
hri_eic_clear_INTEN_reg(EIC, 1ul << extint);
hri_eic_clear_INTFLAG_reg(EIC, 1ul << extint);
}
return ERR_NONE;
}
/**
* \brief Inter EIC interrupt handler
*/
static void _ext_irq_handler(void)
{
volatile uint32_t flags = hri_eic_read_INTFLAG_reg(EIC);
int8_t pos;
uint32_t pin = INVALID_PIN_NUMBER;
hri_eic_clear_INTFLAG_reg(EIC, flags);
ASSERT(callback);
while (flags) {
pos = ffs(flags) - 1;
while (-1 != pos) {
uint8_t lower = 0, middle, upper = EXT_IRQ_AMOUNT;
while (upper >= lower) {
middle = (upper + lower) >> 1;
if (_map[middle].extint == pos) {
pin = _map[middle].pin;
break;
}
if (_map[middle].extint < pos) {
lower = middle + 1;
} else {
upper = middle - 1;
}
}
if (INVALID_PIN_NUMBER != pin) {
callback(pin);
}
flags &= ~(1ul << pos);
pos = ffs(flags) - 1;
}
flags = hri_eic_read_INTFLAG_reg(EIC);
hri_eic_clear_INTFLAG_reg(EIC, flags);
}
}
/**
* \brief EIC interrupt handler
*/
void EIC_Handler(void)
{
_ext_irq_handler();
}

View File

@@ -0,0 +1,163 @@
/**
* \file
*
* \brief Generic Clock Controller related functionality.
*
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <hpl_gclk_config.h>
#include <hpl_init.h>
#include <utils_assert.h>
/* Compatible naming definition */
#ifndef GCLK_GENCTRL_SRC_DPLL
#define GCLK_GENCTRL_SRC_DPLL GCLK_GENCTRL_SRC_FDPLL
#endif
/**
* \brief Initializes generators
*/
void _gclk_init_generators(void)
{
#if CONF_GCLK_GENERATOR_0_CONFIG == 1
hri_gclk_write_GENCTRL_reg(
GCLK,
0,
GCLK_GENCTRL_DIV(CONF_GCLK_GEN_0_DIV) | (CONF_GCLK_GEN_0_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos)
| (CONF_GCLK_GEN_0_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_0_OE << GCLK_GENCTRL_OE_Pos)
| (CONF_GCLK_GEN_0_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_0_IDC << GCLK_GENCTRL_IDC_Pos)
| (CONF_GCLK_GENERATOR_0_CONFIG << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_0_SOURCE);
#endif
#if CONF_GCLK_GENERATOR_1_CONFIG == 1
hri_gclk_write_GENCTRL_reg(
GCLK,
1,
GCLK_GENCTRL_DIV(CONF_GCLK_GEN_1_DIV) | (CONF_GCLK_GEN_1_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos)
| (CONF_GCLK_GEN_1_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_1_OE << GCLK_GENCTRL_OE_Pos)
| (CONF_GCLK_GEN_1_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_1_IDC << GCLK_GENCTRL_IDC_Pos)
| (CONF_GCLK_GENERATOR_1_CONFIG << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_1_SOURCE);
#endif
#if CONF_GCLK_GENERATOR_2_CONFIG == 1
hri_gclk_write_GENCTRL_reg(
GCLK,
2,
GCLK_GENCTRL_DIV(CONF_GCLK_GEN_2_DIV) | (CONF_GCLK_GEN_2_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos)
| (CONF_GCLK_GEN_2_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_2_OE << GCLK_GENCTRL_OE_Pos)
| (CONF_GCLK_GEN_2_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_2_IDC << GCLK_GENCTRL_IDC_Pos)
| (CONF_GCLK_GENERATOR_2_CONFIG << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_2_SOURCE);
#endif
#if CONF_GCLK_GENERATOR_3_CONFIG == 1
hri_gclk_write_GENCTRL_reg(
GCLK,
3,
GCLK_GENCTRL_DIV(CONF_GCLK_GEN_3_DIV) | (CONF_GCLK_GEN_3_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos)
| (CONF_GCLK_GEN_3_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_3_OE << GCLK_GENCTRL_OE_Pos)
| (CONF_GCLK_GEN_3_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_3_IDC << GCLK_GENCTRL_IDC_Pos)
| (CONF_GCLK_GENERATOR_3_CONFIG << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_3_SOURCE);
#endif
#if CONF_GCLK_GENERATOR_4_CONFIG == 1
hri_gclk_write_GENCTRL_reg(
GCLK,
4,
GCLK_GENCTRL_DIV(CONF_GCLK_GEN_4_DIV) | (CONF_GCLK_GEN_4_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos)
| (CONF_GCLK_GEN_4_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_4_OE << GCLK_GENCTRL_OE_Pos)
| (CONF_GCLK_GEN_4_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_4_IDC << GCLK_GENCTRL_IDC_Pos)
| (CONF_GCLK_GENERATOR_4_CONFIG << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_4_SOURCE);
#endif
}
void _gclk_init_generators_by_fref(uint32_t bm)
{
#if CONF_GCLK_GENERATOR_0_CONFIG == 1
if (bm & (1ul << 0)) {
hri_gclk_write_GENCTRL_reg(
GCLK,
0,
GCLK_GENCTRL_DIV(CONF_GCLK_GEN_0_DIV) | (CONF_GCLK_GEN_0_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos)
| (CONF_GCLK_GEN_0_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_0_OE << GCLK_GENCTRL_OE_Pos)
| (CONF_GCLK_GEN_0_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_0_IDC << GCLK_GENCTRL_IDC_Pos)
| (CONF_GCLK_GENERATOR_0_CONFIG << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_0_SOURCE);
}
#endif
#if CONF_GCLK_GENERATOR_1_CONFIG == 1
if (bm & (1ul << 1)) {
hri_gclk_write_GENCTRL_reg(
GCLK,
1,
GCLK_GENCTRL_DIV(CONF_GCLK_GEN_1_DIV) | (CONF_GCLK_GEN_1_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos)
| (CONF_GCLK_GEN_1_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_1_OE << GCLK_GENCTRL_OE_Pos)
| (CONF_GCLK_GEN_1_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_1_IDC << GCLK_GENCTRL_IDC_Pos)
| (CONF_GCLK_GENERATOR_1_CONFIG << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_1_SOURCE);
}
#endif
#if CONF_GCLK_GENERATOR_2_CONFIG == 1
if (bm & (1ul << 2)) {
hri_gclk_write_GENCTRL_reg(
GCLK,
2,
GCLK_GENCTRL_DIV(CONF_GCLK_GEN_2_DIV) | (CONF_GCLK_GEN_2_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos)
| (CONF_GCLK_GEN_2_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_2_OE << GCLK_GENCTRL_OE_Pos)
| (CONF_GCLK_GEN_2_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_2_IDC << GCLK_GENCTRL_IDC_Pos)
| (CONF_GCLK_GENERATOR_2_CONFIG << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_2_SOURCE);
}
#endif
#if CONF_GCLK_GENERATOR_3_CONFIG == 1
if (bm & (1ul << 3)) {
hri_gclk_write_GENCTRL_reg(
GCLK,
3,
GCLK_GENCTRL_DIV(CONF_GCLK_GEN_3_DIV) | (CONF_GCLK_GEN_3_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos)
| (CONF_GCLK_GEN_3_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_3_OE << GCLK_GENCTRL_OE_Pos)
| (CONF_GCLK_GEN_3_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_3_IDC << GCLK_GENCTRL_IDC_Pos)
| (CONF_GCLK_GENERATOR_3_CONFIG << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_3_SOURCE);
}
#endif
#if CONF_GCLK_GENERATOR_4_CONFIG == 1
if (bm & (1ul << 4)) {
hri_gclk_write_GENCTRL_reg(
GCLK,
4,
GCLK_GENCTRL_DIV(CONF_GCLK_GEN_4_DIV) | (CONF_GCLK_GEN_4_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos)
| (CONF_GCLK_GEN_4_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_4_OE << GCLK_GENCTRL_OE_Pos)
| (CONF_GCLK_GEN_4_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_4_IDC << GCLK_GENCTRL_IDC_Pos)
| (CONF_GCLK_GENERATOR_4_CONFIG << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_4_SOURCE);
}
#endif
}

View File

@@ -0,0 +1,87 @@
/**
* \file
*
* \brief Generic Clock Controller.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _HPL_GCLK_H_INCLUDED
#define _HPL_GCLK_H_INCLUDED
#include <compiler.h>
#ifdef _UNIT_TEST_
#include <hri_gclk1_v210_mock.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup gclk_group GCLK Hardware Proxy Layer
*
* \section gclk_hpl_rev Revision History
* - v0.0.0.1 Initial Commit
*
*@{
*/
/**
* \name HPL functions
*/
//@{
/**
* \brief Enable clock on the given channel with the given clock source
*
* This function maps the given clock source to the given clock channel
* and enables channel.
*
* \param[in] channel The channel to enable clock for
* \param[in] source The clock source for the given channel
*/
static inline void _gclk_enable_channel(const uint8_t channel, const uint8_t source)
{
hri_gclk_write_PCHCTRL_reg(GCLK, channel, source | GCLK_PCHCTRL_CHEN);
}
/**
* \brief Initialize GCLK generators by function references
* \param[in] bm Bit mapping for referenced generators,
* a bit 1 in position triggers generator initialization.
*/
void _gclk_init_generators_by_fref(uint32_t bm);
//@}
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* _HPL_GCLK_H_INCLUDED */

View File

@@ -0,0 +1,45 @@
/**
* \file
*
* \brief SAM Main Clock.
*
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <compiler.h>
#include <hpl_mclk_config.h>
/**
* \brief Initialize master clock generator
*/
void _mclk_init(void)
{
void *hw = (void *)MCLK;
hri_mclk_write_BUPDIV_reg(hw, MCLK_BUPDIV_BUPDIV(CONF_MCLK_BUPDIV));
hri_mclk_write_CPUDIV_reg(hw, MCLK_CPUDIV_CPUDIV(CONF_MCLK_CPUDIV));
}

View File

@@ -0,0 +1,86 @@
/**
* \file
*
* \brief SAM 32k Oscillators Controller.
*
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <hpl_init.h>
#include <compiler.h>
#include <hpl_osc32kctrl_config.h>
/**
* \brief Initialize 32 kHz clock sources
*/
void _osc32kctrl_init_sources(void)
{
void * hw = (void *)OSC32KCTRL;
uint16_t calib = 0;
#if CONF_XOSC32K_CONFIG == 1
hri_osc32kctrl_write_XOSC32K_reg(
hw,
OSC32KCTRL_XOSC32K_STARTUP(CONF_XOSC32K_STARTUP) | (CONF_XOSC32K_ONDEMAND << OSC32KCTRL_XOSC32K_ONDEMAND_Pos)
| (CONF_XOSC32K_RUNSTDBY << OSC32KCTRL_XOSC32K_RUNSTDBY_Pos)
| (CONF_XOSC32K_EN1K << OSC32KCTRL_XOSC32K_EN1K_Pos) | (CONF_XOSC32K_EN32K << OSC32KCTRL_XOSC32K_EN32K_Pos)
| (CONF_XOSC32K_XTALEN << OSC32KCTRL_XOSC32K_XTALEN_Pos)
| (CONF_XOSC32K_ENABLE << OSC32KCTRL_XOSC32K_ENABLE_Pos));
hri_osc32kctrl_write_CFDCTRL_reg(hw,
(CONF_XOSC32K_CFDEN << OSC32KCTRL_CFDCTRL_CFDEN_Pos)
| (CONF_XOSC32K_SWBEN << OSC32KCTRL_CFDCTRL_SWBACK_Pos));
hri_osc32kctrl_write_EVCTRL_reg(hw, (CONF_XOSC32K_CFDEO << OSC32KCTRL_EVCTRL_CFDEO_Pos));
#endif
#if CONF_OSCULP32K_CONFIG == 1
calib = hri_osc32kctrl_read_OSCULP32K_CALIB_bf(hw);
hri_osc32kctrl_write_OSCULP32K_reg(hw,
#if CONF_OSC32K_CALIB_ENABLE == 1
OSC32KCTRL_OSCULP32K_CALIB(CONF_OSC32K_CALIB)
#else
OSC32KCTRL_OSCULP32K_CALIB(calib)
#endif
);
#endif
#if CONF_XOSC32K_CONFIG
#if CONF_XOSC32K_ENABLE == 1 && CONF_XOSC32K_ONDEMAND == 0
while (!hri_osc32kctrl_get_STATUS_XOSC32KRDY_bit(hw))
;
#endif
#if CONF_OSCULP32K_ULP32KSW == 1
hri_osc32kctrl_set_OSCULP32K_reg(hw, OSC32KCTRL_OSCULP32K_ULP32KSW);
while (!hri_osc32kctrl_get_STATUS_ULP32KSW_bit(hw))
;
#endif
#endif
hri_osc32kctrl_write_RTCCTRL_reg(hw, OSC32KCTRL_RTCCTRL_RTCSEL(CONF_RTCCTRL));
(void)calib;
}

View File

@@ -0,0 +1,179 @@
/**
* \file
*
* \brief SAM Oscillators Controller.
*
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <compiler.h>
#include <hpl_init.h>
#include <hpl_oscctrl_config.h>
/**
* \brief Initialize clock sources
*/
void _oscctrl_init_sources(void)
{
void *hw = (void *)OSCCTRL;
#if CONF_XOSC_CONFIG == 1
hri_oscctrl_write_XOSCCTRL_reg(
hw,
OSCCTRL_XOSCCTRL_STARTUP(CONF_XOSC_STARTUP) | (0 << OSCCTRL_XOSCCTRL_AMPGC_Pos)
| OSCCTRL_XOSCCTRL_GAIN(CONF_XOSC_GAIN) | (0 << OSCCTRL_XOSCCTRL_ONDEMAND_Pos)
| (CONF_XOSC_RUNSTDBY << OSCCTRL_XOSCCTRL_RUNSTDBY_Pos) | (CONF_XOSC_SWBEN << OSCCTRL_XOSCCTRL_SWBEN_Pos)
| (CONF_XOSC_CFDEN << OSCCTRL_XOSCCTRL_CFDEN_Pos) | (CONF_XOSC_XTALEN << OSCCTRL_XOSCCTRL_XTALEN_Pos)
| (CONF_XOSC_ENABLE << OSCCTRL_XOSCCTRL_ENABLE_Pos));
hri_oscctrl_write_EVCTRL_reg(hw, (CONF_XOSC_CFDEO << OSCCTRL_EVCTRL_CFDEO_Pos));
#endif
#if CONF_OSC16M_CONFIG == 1
hri_oscctrl_write_OSC16MCTRL_reg(hw,
(CONF_OSC16M_ONDEMAND << OSCCTRL_OSC16MCTRL_ONDEMAND_Pos)
| (CONF_OSC16M_RUNSTDBY << OSCCTRL_OSC16MCTRL_RUNSTDBY_Pos)
| (CONF_OSC16M_ENABLE << OSCCTRL_OSC16MCTRL_ENABLE_Pos)
| OSCCTRL_OSC16MCTRL_FSEL(CONF_OSC16M_FSEL));
#endif
#if CONF_XOSC_CONFIG == 1
#if CONF_XOSC_ENABLE == 1
while (!hri_oscctrl_get_STATUS_XOSCRDY_bit(hw))
;
#endif
#if CONF_XOSC_AMPGC == 1
hri_oscctrl_set_XOSCCTRL_AMPGC_bit(hw);
#endif
#if CONF_XOSC_ONDEMAND == 1
hri_oscctrl_set_XOSCCTRL_ONDEMAND_bit(hw);
#endif
#endif
#if CONF_OSC16M_CONFIG == 1
#if CONF_OSC16M_ENABLE == 1
while (!hri_oscctrl_get_STATUS_OSC16MRDY_bit(hw))
;
#endif
#if CONF_OSC16M_ONDEMAND == 1
hri_oscctrl_set_OSC16MCTRL_ONDEMAND_bit(hw);
#endif
#endif
(void)hw;
}
void _oscctrl_init_referenced_generators(void)
{
void * hw = (void *)OSCCTRL;
hri_oscctrl_dfllctrl_reg_t tmp = 0;
#if CONF_DFLL_CONFIG == 1
#if CONF_DFLL_OVERWRITE_CALIBRATION == 0
#define NVM_DFLL_COARSE_POS 26
#define NVM_DFLL_COARSE_SIZE 6
uint32_t coarse;
coarse = *((uint32_t *)(NVMCTRL_OTP5)) >> NVM_DFLL_COARSE_POS;
#endif
#if CONF_DFLL_USBCRM != 1 && CONF_DFLL_MODE != 0
hri_gclk_write_PCHCTRL_reg(GCLK, 0, (1 << GCLK_PCHCTRL_CHEN_Pos) | GCLK_PCHCTRL_GEN(CONF_DFLL_GCLK));
#endif
hri_oscctrl_write_DFLLCTRL_reg(hw, OSCCTRL_DFLLCTRL_ENABLE);
while (!hri_oscctrl_get_STATUS_DFLLRDY_bit(hw))
;
hri_oscctrl_write_DFLLMUL_reg(hw,
OSCCTRL_DFLLMUL_CSTEP(CONF_DFLL_CSTEP) | OSCCTRL_DFLLMUL_FSTEP(CONF_DFLL_FSTEP)
| OSCCTRL_DFLLMUL_MUL(CONF_DFLL_MUL));
while (!hri_oscctrl_get_STATUS_DFLLRDY_bit(hw))
;
#if CONF_DFLL_OVERWRITE_CALIBRATION == 0
/* FINE is set to fixed value, which defined by DFLL48M Characteristics */
hri_oscctrl_write_DFLLVAL_reg(hw, OSCCTRL_DFLLVAL_COARSE(coarse) | OSCCTRL_DFLLVAL_FINE(512));
#else
hri_oscctrl_write_DFLLVAL_reg(hw, OSCCTRL_DFLLVAL_COARSE(CONF_DFLL_COARSE) | OSCCTRL_DFLLVAL_FINE(CONF_DFLL_FINE));
#endif
tmp = (CONF_DFLL_WAITLOCK << OSCCTRL_DFLLCTRL_WAITLOCK_Pos) | (CONF_DFLL_BPLCKC << OSCCTRL_DFLLCTRL_BPLCKC_Pos)
| (CONF_DFLL_QLDIS << OSCCTRL_DFLLCTRL_QLDIS_Pos) | (CONF_DFLL_CCDIS << OSCCTRL_DFLLCTRL_CCDIS_Pos)
| (CONF_DFLL_RUNSTDBY << OSCCTRL_DFLLCTRL_RUNSTDBY_Pos) | (CONF_DFLL_USBCRM << OSCCTRL_DFLLCTRL_USBCRM_Pos)
| (CONF_DFLL_LLAW << OSCCTRL_DFLLCTRL_LLAW_Pos) | (CONF_DFLL_STABLE << OSCCTRL_DFLLCTRL_STABLE_Pos)
| (CONF_DFLL_MODE << OSCCTRL_DFLLCTRL_MODE_Pos) | (CONF_DFLL_ENABLE << OSCCTRL_DFLLCTRL_ENABLE_Pos);
hri_oscctrl_write_DFLLCTRL_reg(hw, tmp);
#endif
#if CONF_DPLL_CONFIG == 1
#if CONF_DPLL_REFCLK == 2
hri_gclk_write_PCHCTRL_reg(GCLK, 1, (1 << GCLK_PCHCTRL_CHEN_Pos) | GCLK_PCHCTRL_GEN(CONF_DPLL_GCLK));
#endif
hri_oscctrl_write_DPLLRATIO_reg(
hw, OSCCTRL_DPLLRATIO_LDRFRAC(CONF_DPLL_LDRFRAC) | OSCCTRL_DPLLRATIO_LDR(CONF_DPLL_LDR));
hri_oscctrl_write_DPLLCTRLB_reg(
hw,
OSCCTRL_DPLLCTRLB_DIV(CONF_DPLL_DIV) | (CONF_DPLL_LBYPASS << OSCCTRL_DPLLCTRLB_LBYPASS_Pos)
| OSCCTRL_DPLLCTRLB_LTIME(CONF_DPLL_LTIME) | OSCCTRL_DPLLCTRLB_REFCLK(CONF_DPLL_REFCLK)
| (CONF_DPLL_WUF << OSCCTRL_DPLLCTRLB_WUF_Pos) | (CONF_DPLL_LPEN << OSCCTRL_DPLLCTRLB_LPEN_Pos)
| OSCCTRL_DPLLCTRLB_FILTER(CONF_DPLL_FILTER));
hri_oscctrl_write_DPLLPRESC_reg(hw, OSCCTRL_DPLLPRESC_PRESC(CONF_DPLL_PRESC));
hri_oscctrl_write_DPLLCTRLA_reg(hw,
(0 << OSCCTRL_DPLLCTRLA_ONDEMAND_Pos)
| (CONF_DPLL_RUNSTDBY << OSCCTRL_DPLLCTRLA_RUNSTDBY_Pos)
| (CONF_DPLL_ENABLE << OSCCTRL_DPLLCTRLA_ENABLE_Pos));
#endif
#if CONF_DFLL_CONFIG == 1
if (hri_oscctrl_get_DFLLCTRL_MODE_bit(hw)) {
hri_oscctrl_status_reg_t status_mask = OSCCTRL_STATUS_DFLLRDY | OSCCTRL_STATUS_DFLLLCKC;
while (hri_oscctrl_get_STATUS_reg(hw, status_mask) != status_mask)
;
} else {
while (!hri_oscctrl_get_STATUS_DFLLRDY_bit(hw))
;
}
#if CONF_DFLL_ONDEMAND == 1
hri_oscctrl_set_DFLLCTRL_ONDEMAND_bit(hw);
#endif
#endif
#if CONF_DPLL_CONFIG == 1
#if CONF_DPLL_ENABLE == 1
while (!(hri_oscctrl_get_DPLLSTATUS_LOCK_bit(hw) || hri_oscctrl_get_DPLLSTATUS_CLKRDY_bit(hw)))
;
#endif
#if CONF_DPLL_ONDEMAND == 1
hri_oscctrl_set_DPLLCTRLA_ONDEMAND_bit(hw);
#endif
#endif
#if CONF_DFLL_CONFIG == 1
while (hri_gclk_read_SYNCBUSY_reg(GCLK))
;
#endif
(void)hw, (void)tmp;
}

View File

@@ -0,0 +1,77 @@
/**
* \file
*
* \brief SAM Power manager
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <hpl_sleep.h>
#include <hpl_reset.h>
#include <hpl_init.h>
/**
* \brief Retrieve the reset reason
*/
enum reset_reason _get_reset_reason(void)
{
return (enum reset_reason)hri_rstc_read_RCAUSE_reg(RSTC);
}
/**
* \brief Set the sleep mode for the device
*/
int32_t _set_sleep_mode(const uint8_t mode)
{
switch (mode) {
case 2: /* IDLE */
case 4: /* STANDBY */
case 5: /* BACKUP */
case 6: /* OFF */
hri_pm_write_SLEEPCFG_SLEEPMODE_bf(PM, mode);
break;
default:
return ERR_INVALID_ARG;
}
return ERR_NONE;
}
/**
* \brief Set performance level
*/
void _set_performance_level(const uint8_t level)
{
if (hri_pm_get_PLCFG_PLSEL_bf(PM, PM_PLCFG_PLSEL_Msk) != level) {
hri_pm_clear_INTFLAG_reg(PM, 0xFF);
hri_pm_write_PLCFG_PLSEL_bf(PM, level);
while (!hri_pm_read_INTFLAG_reg(PM))
;
}
}

View File

@@ -0,0 +1,45 @@
/**
* \file
*
* \brief SAM Power manager
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*/
#ifndef _HPL_PM_BASE_H_INCLUDED
#define _HPL_PM_BASE_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#include <utils_assert.h>
#ifdef __cplusplus
}
#endif
#endif /* _HPL_PM_BASE_H_INCLUDED */

View File

@@ -0,0 +1,170 @@
/**
* \file
*
* \brief SAM PORT.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <compiler.h>
#include <hpl_gpio.h>
#include <utils_assert.h>
#include <hpl_port_config.h>
/**
* \brief Set direction on port with mask
*/
static inline void _gpio_set_direction(const enum gpio_port port, const uint32_t mask,
const enum gpio_direction direction)
{
switch (direction) {
case GPIO_DIRECTION_OFF:
hri_port_clear_DIR_reg(PORT_IOBUS, port, mask);
hri_port_write_WRCONFIG_reg(PORT, port, PORT_WRCONFIG_WRPINCFG | (mask & 0xffff));
hri_port_write_WRCONFIG_reg(
PORT, port, PORT_WRCONFIG_HWSEL | PORT_WRCONFIG_WRPINCFG | ((mask & 0xffff0000) >> 16));
break;
case GPIO_DIRECTION_IN:
hri_port_clear_DIR_reg(PORT_IOBUS, port, mask);
hri_port_write_WRCONFIG_reg(PORT, port, PORT_WRCONFIG_WRPINCFG | PORT_WRCONFIG_INEN | (mask & 0xffff));
hri_port_write_WRCONFIG_reg(PORT,
port,
PORT_WRCONFIG_HWSEL | PORT_WRCONFIG_WRPINCFG | PORT_WRCONFIG_INEN
| ((mask & 0xffff0000) >> 16));
break;
case GPIO_DIRECTION_OUT:
hri_port_set_DIR_reg(PORT_IOBUS, port, mask);
hri_port_write_WRCONFIG_reg(PORT, port, PORT_WRCONFIG_WRPINCFG | (mask & 0xffff));
hri_port_write_WRCONFIG_reg(
PORT, port, PORT_WRCONFIG_HWSEL | PORT_WRCONFIG_WRPINCFG | ((mask & 0xffff0000) >> 16));
break;
default:
ASSERT(false);
}
}
/**
* \brief Set output level on port with mask
*/
static inline void _gpio_set_level(const enum gpio_port port, const uint32_t mask, const bool level)
{
if (level) {
hri_port_set_OUT_reg(PORT_IOBUS, port, mask);
} else {
hri_port_clear_OUT_reg(PORT_IOBUS, port, mask);
}
}
/**
* \brief Change output level to the opposite with mask
*/
static inline void _gpio_toggle_level(const enum gpio_port port, const uint32_t mask)
{
hri_port_toggle_OUT_reg(PORT_IOBUS, port, mask);
}
/**
* \brief Get input levels on all port pins
*/
static inline uint32_t _gpio_get_level(const enum gpio_port port)
{
uint32_t tmp;
CRITICAL_SECTION_ENTER();
uint32_t dir_tmp = hri_port_read_DIR_reg(PORT_IOBUS, port);
tmp = hri_port_read_IN_reg(PORT, port) & ~dir_tmp;
tmp |= hri_port_read_OUT_reg(PORT_IOBUS, port) & dir_tmp;
CRITICAL_SECTION_LEAVE();
return tmp;
}
/**
* \brief Set pin pull mode
*/
static inline void _gpio_set_pin_pull_mode(const enum gpio_port port, const uint8_t pin,
const enum gpio_pull_mode pull_mode)
{
switch (pull_mode) {
case GPIO_PULL_OFF:
hri_port_clear_PINCFG_PULLEN_bit(PORT, port, pin);
break;
case GPIO_PULL_UP:
hri_port_clear_DIR_reg(PORT_IOBUS, port, 1U << pin);
hri_port_set_PINCFG_PULLEN_bit(PORT, port, pin);
hri_port_set_OUT_reg(PORT_IOBUS, port, 1U << pin);
break;
case GPIO_PULL_DOWN:
hri_port_clear_DIR_reg(PORT_IOBUS, port, 1U << pin);
hri_port_set_PINCFG_PULLEN_bit(PORT, port, pin);
hri_port_clear_OUT_reg(PORT_IOBUS, port, 1U << pin);
break;
default:
ASSERT(false);
break;
}
}
/**
* \brief Set gpio pin function
*/
static inline void _gpio_set_pin_function(const uint32_t gpio, const uint32_t function)
{
uint8_t port = GPIO_PORT(gpio);
uint8_t pin = GPIO_PIN(gpio);
if (function == GPIO_PIN_FUNCTION_OFF) {
hri_port_write_PINCFG_PMUXEN_bit(PORT, port, pin, false);
} else {
hri_port_write_PINCFG_PMUXEN_bit(PORT, port, pin, true);
if (pin & 1) {
// Odd numbered pin
hri_port_write_PMUX_PMUXO_bf(PORT, port, pin >> 1, function & 0xffff);
} else {
// Even numbered pin
hri_port_write_PMUX_PMUXE_bf(PORT, port, pin >> 1, function & 0xffff);
}
}
}
static inline void _port_event_init()
{
hri_port_set_EVCTRL_reg(PORT, 0, CONF_PORTA_EVCTRL);
hri_port_set_EVCTRL_reg(PORT, 1, CONF_PORTB_EVCTRL);
}

View File

@@ -0,0 +1,397 @@
/**
* \file
*
* \brief RTC Driver
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <hpl_calendar.h>
#include <utils_assert.h>
#include <hpl_rtc_config.h>
/*!< Pointer to hpl device */
static struct calendar_dev *_rtc_dev = NULL;
/**
* \brief Initializes the RTC module with given configurations.
*/
int32_t _calendar_init(struct calendar_dev *const dev)
{
ASSERT(dev && dev->hw);
_rtc_dev = dev;
if (hri_rtcmode0_get_CTRLA_ENABLE_bit(dev->hw)) {
#if !CONF_RTC_INIT_RESET
return ERR_DENIED;
#else
hri_rtcmode0_clear_CTRLA_ENABLE_bit(dev->hw);
hri_rtcmode0_wait_for_sync(dev->hw, RTC_MODE0_SYNCBUSY_ENABLE);
#endif
}
hri_rtcmode0_set_CTRLA_SWRST_bit(dev->hw);
hri_rtcmode0_wait_for_sync(dev->hw, RTC_MODE0_SYNCBUSY_SWRST);
#if CONF_RTC_EVENT_CONTROL_ENABLE == 1
hri_rtcmode0_write_EVCTRL_reg(
dev->hw,
(CONF_RTC_PEREO0 << RTC_MODE0_EVCTRL_PEREO0_Pos) | (CONF_RTC_PEREO1 << RTC_MODE0_EVCTRL_PEREO1_Pos)
| (CONF_RTC_PEREO2 << RTC_MODE0_EVCTRL_PEREO2_Pos) | (CONF_RTC_PEREO3 << RTC_MODE0_EVCTRL_PEREO3_Pos)
| (CONF_RTC_PEREO4 << RTC_MODE0_EVCTRL_PEREO4_Pos) | (CONF_RTC_PEREO5 << RTC_MODE0_EVCTRL_PEREO5_Pos)
| (CONF_RTC_PEREO6 << RTC_MODE0_EVCTRL_PEREO6_Pos) | (CONF_RTC_PEREO7 << RTC_MODE0_EVCTRL_PEREO7_Pos)
| (CONF_RTC_COMPE0 << RTC_MODE0_EVCTRL_CMPEO_Pos) | (CONF_RTC_OVFEO << RTC_MODE0_EVCTRL_OVFEO_Pos));
#endif
hri_rtcmode0_write_CTRLA_reg(dev->hw, RTC_MODE0_CTRLA_PRESCALER(CONF_RTC_PRESCALER) | RTC_MODE0_CTRLA_COUNTSYNC);
hri_rtc_write_TAMPCTRL_reg(
dev->hw,
(CONF_RTC_TAMPER_INACT_0 << RTC_TAMPCTRL_IN0ACT_Pos) | (CONF_RTC_TAMPER_INACT_1 << RTC_TAMPCTRL_IN1ACT_Pos)
| (CONF_RTC_TAMPER_INACT_2 << RTC_TAMPCTRL_IN2ACT_Pos)
| (CONF_RTC_TAMPER_INACT_3 << RTC_TAMPCTRL_IN3ACT_Pos)
| (CONF_RTC_TAMPER_INACT_4 << RTC_TAMPCTRL_IN4ACT_Pos) | (CONF_RTC_TAMP_LVL_0 << RTC_TAMPCTRL_TAMLVL0_Pos)
| (CONF_RTC_TAMP_LVL_1 << RTC_TAMPCTRL_TAMLVL1_Pos) | (CONF_RTC_TAMP_LVL_2 << RTC_TAMPCTRL_TAMLVL2_Pos)
| (CONF_RTC_TAMP_LVL_3 << RTC_TAMPCTRL_TAMLVL3_Pos) | (CONF_RTC_TAMP_LVL_4 << RTC_TAMPCTRL_TAMLVL4_Pos)
| (CONF_RTC_TAMP_DEBNC_0 << RTC_TAMPCTRL_DEBNC0_Pos) | (CONF_RTC_TAMP_DEBNC_1 << RTC_TAMPCTRL_DEBNC1_Pos)
| (CONF_RTC_TAMP_DEBNC_2 << RTC_TAMPCTRL_DEBNC2_Pos) | (CONF_RTC_TAMP_DEBNC_3 << RTC_TAMPCTRL_DEBNC3_Pos)
| (CONF_RTC_TAMP_DEBNC_4 << RTC_TAMPCTRL_DEBNC4_Pos));
if ((CONF_RTC_TAMPER_INACT_0 == TAMPER_MODE_ACTL) | (CONF_RTC_TAMPER_INACT_1 == TAMPER_MODE_ACTL)
| (CONF_RTC_TAMPER_INACT_2 == TAMPER_MODE_ACTL) | (CONF_RTC_TAMPER_INACT_3 == TAMPER_MODE_ACTL)
| (CONF_RTC_TAMPER_INACT_4 == TAMPER_MODE_ACTL)) {
hri_rtcmode0_set_CTRLB_RTCOUT_bit(dev->hw);
}
return ERR_NONE;
}
/**
* \brief Deinit the RTC module
*/
int32_t _calendar_deinit(struct calendar_dev *const dev)
{
ASSERT(dev && dev->hw);
NVIC_DisableIRQ(RTC_IRQn);
dev->callback = NULL;
hri_rtcmode0_clear_CTRLA_ENABLE_bit(dev->hw);
hri_rtcmode0_set_CTRLA_SWRST_bit(dev->hw);
return ERR_NONE;
}
/**
* \brief Enable the RTC module
*/
int32_t _calendar_enable(struct calendar_dev *const dev)
{
ASSERT(dev && dev->hw);
hri_rtcmode0_set_CTRLA_ENABLE_bit(dev->hw);
return ERR_NONE;
}
/**
* \brief Disable the RTC module
*/
int32_t _calendar_disable(struct calendar_dev *const dev)
{
ASSERT(dev && dev->hw);
hri_rtcmode0_clear_CTRLA_ENABLE_bit(dev->hw);
return ERR_NONE;
}
/**
* \brief Set the current calendar time to desired time.
*/
int32_t _calendar_set_counter(struct calendar_dev *const dev, const uint32_t counter)
{
ASSERT(dev && dev->hw);
hri_rtcmode0_write_COUNT_reg(dev->hw, counter);
return ERR_NONE;
}
/**
* \brief Get current counter
*/
uint32_t _calendar_get_counter(struct calendar_dev *const dev)
{
ASSERT(dev && dev->hw);
return hri_rtcmode0_read_COUNT_reg(dev->hw);
}
/**
* \brief Set the compare for the specified value.
*/
int32_t _calendar_set_comp(struct calendar_dev *const dev, const uint32_t comp)
{
ASSERT(dev && dev->hw);
hri_rtcmode0_write_COMP_reg(dev->hw, 0, comp);
return ERR_NONE;
}
/**
* \brief Get the compare value
*/
uint32_t _calendar_get_comp(struct calendar_dev *const dev)
{
ASSERT(dev && dev->hw);
return hri_rtcmode0_read_COMP_reg(dev->hw, 0);
}
/**
* \brief Find tamper is detected on specified pin
*/
bool _is_tamper_detected(struct calendar_dev *const dev, enum tamper_id tamper_id_pin)
{
bool value;
ASSERT(dev && dev->hw);
value = ((hri_rtc_read_TAMPID_reg(dev->hw) >> tamper_id_pin) & 0x01);
return value;
}
/**
* \brief Clear the Tamper ID flag
*/
int32_t _tamper_clear_tampid_flag(struct calendar_dev *const dev, enum tamper_id tamper_id_pin)
{
ASSERT(dev && dev->hw);
hri_rtc_write_TAMPID_reg(dev->hw, (true << tamper_id_pin));
return ERR_NONE;
}
/**
* \brief Enable Tamper Debounce Asynchronous Feature
*/
int32_t _tamper_enable_debounce_asynchronous(struct calendar_dev *const dev)
{
int32_t return_value;
hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, false);
while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
}
if (hri_rtcmode0_read_CTRLA_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
return_value = ERR_FAILURE;
} else {
hri_rtcmode0_write_CTRLB_DEBASYNC_bit(dev->hw, true);
return_value = ERR_NONE;
while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
}
hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, true);
}
return return_value;
}
/**
* \brief Disable Tamper Debounce Asynchronous Feature
*/
int32_t _tamper_disable_debounce_asynchronous(struct calendar_dev *const dev)
{
int32_t return_value;
hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, false);
while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
}
if (hri_rtcmode0_read_CTRLA_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
return_value = ERR_FAILURE;
} else {
hri_rtcmode0_write_CTRLB_DEBASYNC_bit(dev->hw, false);
return_value = ERR_NONE;
while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
}
hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, true);
}
return return_value;
}
/**
* \brief Enable Tamper Debounce Majority Feature
*/
int32_t _tamper_enable_debounce_majority(struct calendar_dev *const dev)
{
int32_t return_value;
hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, false);
while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
}
if (hri_rtcmode0_read_CTRLA_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
return_value = ERR_FAILURE;
} else {
hri_rtcmode0_write_CTRLB_DEBMAJ_bit(dev->hw, true);
return_value = ERR_NONE;
while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
}
hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, true);
}
return return_value;
}
/**
* \brief Disable Tamper Debounce Majority Feature
*/
int32_t _tamper_disable_debounce_majority(struct calendar_dev *const dev)
{
int32_t return_value;
hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, false);
while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
}
if (hri_rtcmode0_read_CTRLA_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
return_value = ERR_FAILURE;
} else {
hri_rtcmode0_write_CTRLB_DEBMAJ_bit(dev->hw, false);
return_value = ERR_NONE;
while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
}
hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, true);
}
return return_value;
}
int32_t _tamper_register_callback(struct calendar_dev *const dev, tamper_drv_cb_t callback_tamper)
{
ASSERT(dev && dev->hw);
/* Check callback */
if (callback_tamper != NULL) {
/* register the callback */
dev->callback_tamper = callback_tamper;
/* enable RTC_IRQn */
NVIC_ClearPendingIRQ(RTC_IRQn);
NVIC_EnableIRQ(RTC_IRQn);
/* enable tamper interrupt */
hri_rtcmode0_set_INTEN_PER7_bit(dev->hw);
} else {
/* disable tamper interrupt */
hri_rtcmode0_clear_INTEN_PER7_bit(dev->hw);
/* disable RTC_IRQn */
NVIC_DisableIRQ(RTC_IRQn);
}
return ERR_NONE;
}
/**
* \brief Registers callback for the specified callback type
*/
int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv_cb_alarm_t callback)
{
ASSERT(dev && dev->hw);
/* Check callback */
if (callback != NULL) {
/* register the callback */
dev->callback = callback;
/* enable RTC_IRQn */
NVIC_ClearPendingIRQ(RTC_IRQn);
NVIC_EnableIRQ(RTC_IRQn);
/* enable cmp */
hri_rtcmode0_set_INTEN_CMP0_bit(dev->hw);
} else {
/* disable cmp */
hri_rtcmode0_clear_INTEN_CMP0_bit(dev->hw);
/* disable RTC_IRQn */
NVIC_DisableIRQ(RTC_IRQn);
}
return ERR_NONE;
}
/**
* \brief RTC interrupt handler
*
* \param[in] dev The pointer to calendar device struct
*/
static void _rtc_interrupt_handler(struct calendar_dev *dev)
{
/* Read and mask interrupt flag register */
uint16_t interrupt_status = hri_rtcmode0_read_INTFLAG_reg(dev->hw);
uint16_t interrupt_enabled = hri_rtcmode0_read_INTEN_reg(dev->hw);
if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_ALARM0) {
dev->callback(dev);
/* Clear interrupt flag */
hri_rtcmode0_clear_interrupt_CMP0_bit(dev->hw);
} else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_PER7) {
dev->callback_tamper(dev);
/* Clear interrupt flag */
hri_rtcmode0_clear_interrupt_PER7_bit(dev->hw);
}
}
/**
* \brief Set calendar IRQ
*/
void _calendar_set_irq(struct calendar_dev *const dev)
{
(void)dev;
NVIC_SetPendingIRQ(RTC_IRQn);
}
/**
* \brief Rtc interrupt handler
*/
void RTC_Handler(void)
{
_rtc_interrupt_handler(_rtc_dev);
}

View File

@@ -0,0 +1,52 @@
/**
* \file
*
* \brief RTC
*
* Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*/
#ifndef _HPL_RTC2_V200_H_INCLUDED
#define _HPL_RTC2_V200_H_INCLUDED
#include <hpl_timer.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Retrieve timer helper functions
*
* \return A pointer to set of timer helper functions
*/
struct _timer_hpl_interface *_rtc_get_timer(void);
#ifdef __cplusplus
}
#endif
#endif /* _HPL_RTC2_V200_H_INCLUDED */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,336 @@
/**
* \file
*
* \brief SLCD Segment Liquid Crystal Display Controller(Sync) functionality
* Implementation.
*
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <utils_assert.h>
#include <hpl_slcd_sync.h>
#include <hpl_slcd_config.h>
#include <hpl_slcd_cm_7_seg_mapping.h>
#include <hpl_slcd_cm_14_seg_mapping.h>
static int32_t _slcd_sync_set_segment(struct _slcd_sync_device *dev, const uint32_t com, const uint32_t seg,
const bool on);
/**
* \brief SLCD configuration type
*/
struct slcd_configuration {
hri_slcd_ctrla_reg_t ctrla; /*!< Control A Register */
hri_slcd_ctrlb_reg_t ctrlb; /*!< Control B Register */
hri_slcd_ctrlc_reg_t ctrlc; /*!< Control C Register */
hri_slcd_ctrld_reg_t ctrld; /*!< Control D Register */
};
/**
* \brief Array of AC configurations
*/
static struct slcd_configuration _slcd
= {SLCD_CTRLA_DUTY(CONF_SLCD_COM_NUM) | CONF_SLCD_WMOD << SLCD_CTRLA_WMOD_Pos
| CONF_SLCD_RUNSTDBY << SLCD_CTRLA_RUNSTDBY_Pos | SLCD_CTRLA_PRESC(CONF_SLCD_PRESC)
| SLCD_CTRLA_CKDIV(CONF_SLCD_CKDIV) | SLCD_CTRLA_BIAS(CONF_SLCD_BIAS)
| CONF_SLCD_XVLCD << SLCD_CTRLA_XVLCD_Pos | SLCD_CTRLA_PRF(CONF_SLCD_PRF) | SLCD_CTRLA_RRF(CONF_SLCD_RRF),
CONF_SLCD_BBEN << SLCD_CTRLB_BBEN_Pos | SLCD_CTRLB_BBD(CONF_SLCD_BBD - 1),
SLCD_CTRLC_CTST(CONF_SLCD_CONTRAST_ADJUST),
SLCD_CTRLD_DISPEN};
static const struct slcd_char_setting cm_setting[] = SLCD_CHAR_SETTING_TABLE;
static const struct slcd_char_mapping cm7_lut[] = SLCD_SEG7_LUT;
static const struct slcd_char_mapping cm14_lut[] = SLCD_SEG14_LUT;
/**
* \brief Initialize SLCD Device Descriptor
*/
int32_t _slcd_sync_init(struct _slcd_sync_device *dev, void *const hw)
{
if (!hri_slcd_is_syncing(hw, SLCD_SYNCBUSY_SWRST)) {
if (hri_slcd_get_CTRLA_ENABLE_bit(hw)) {
hri_slcd_clear_CTRLA_ENABLE_bit(hw);
hri_slcd_wait_for_sync(hw, SLCD_SYNCBUSY_ENABLE);
}
hri_slcd_write_CTRLA_reg(hw, SLCD_CTRLA_SWRST);
}
hri_slcd_wait_for_sync(hw, SLCD_SYNCBUSY_SWRST);
dev->hw = hw;
hri_slcd_write_CTRLA_reg(hw, _slcd.ctrla);
hri_slcd_write_CTRLB_reg(hw, _slcd.ctrlb);
hri_slcd_write_CTRLC_reg(hw, _slcd.ctrlc);
hri_slcd_write_CTRLD_reg(hw, _slcd.ctrld);
hri_slcd_write_LPENL_reg(hw, CONF_SLCD_LPENL);
hri_slcd_write_LPENH_reg(hw, CONF_SLCD_LPENH);
hri_slcd_write_SDATAL0_reg(hw, 0);
hri_slcd_write_SDATAH0_reg(hw, 0);
hri_slcd_write_SDATAL1_reg(hw, 0);
hri_slcd_write_SDATAH1_reg(hw, 0);
hri_slcd_write_SDATAL2_reg(hw, 0);
hri_slcd_write_SDATAH2_reg(hw, 0);
hri_slcd_write_SDATAL3_reg(hw, 0);
hri_slcd_write_SDATAH3_reg(hw, 0);
hri_slcd_write_SDATAL4_reg(hw, 0);
hri_slcd_write_SDATAH4_reg(hw, 0);
hri_slcd_write_SDATAL5_reg(hw, 0);
hri_slcd_write_SDATAH5_reg(hw, 0);
hri_slcd_write_SDATAL6_reg(hw, 0);
hri_slcd_write_SDATAH6_reg(hw, 0);
hri_slcd_write_SDATAL7_reg(hw, 0);
hri_slcd_write_SDATAH7_reg(hw, 0);
hri_slcd_set_BCFG_MODE_bit(dev->hw);
return ERR_NONE;
}
/**
* \brief DeInitialize SLCD Device Descriptor
*/
int32_t _slcd_sync_deinit(struct _slcd_sync_device *dev)
{
hri_slcd_clear_CTRLA_ENABLE_bit(dev->hw);
hri_slcd_wait_for_sync(dev->hw, SLCD_SYNCBUSY_ENABLE);
hri_slcd_set_CTRLA_SWRST_bit(dev->hw);
dev->hw = NULL;
return ERR_NONE;
}
/**
* \brief Enable SLCD driver
*
* \param[in] dev SLCD device descriptor to be enabled
*/
int32_t _slcd_sync_enable(struct _slcd_sync_device *dev)
{
hri_slcd_set_CTRLA_ENABLE_bit(dev->hw);
return ERR_NONE;
}
/**
* \brief Disable SLCD driver
*/
int32_t _slcd_sync_disable(struct _slcd_sync_device *dev)
{
hri_slcd_clear_CTRLA_ENABLE_bit(dev->hw);
return ERR_NONE;
}
/**
* \brief Turn on a Segment
*/
int32_t _slcd_sync_seg_on(struct _slcd_sync_device *dev, uint32_t seg)
{
return _slcd_sync_set_segment(dev, SLCD_COMNUM(seg), SLCD_SEGNUM(seg), true);
}
/**
* \brief Turn off a Segment
*/
int32_t _slcd_sync_seg_off(struct _slcd_sync_device *dev, uint32_t seg)
{
return _slcd_sync_set_segment(dev, SLCD_COMNUM(seg), SLCD_SEGNUM(seg), false);
}
/**
* \brief Blink a Segment
*/
int32_t _slcd_sync_seg_blink(struct _slcd_sync_device *dev, uint32_t seg, const uint32_t period)
{
if ((SLCD_COMNUM(seg) >= CONF_SLCD_COM_NUM) || (SLCD_SEGNUM(seg) >= CONF_SLCD_SEG_NUM)) {
return ERR_INVALID_ARG;
}
/* COM[0..7], Seg[0,1] support blink */
if (SLCD_SEGNUM(seg) >= 2) {
return ERR_INVALID_ARG;
}
/* Verify period */
if (period > SLCD_FC_MAX_MS || period < SLCD_FC_MIN_MS) {
return ERR_INVALID_ARG;
}
/* Set Period, use Frame Counter 0 for blink */
hri_slcd_clear_CTRLD_FC0EN_bit(dev->hw);
hri_slcd_wait_for_sync(dev->hw, SLCD_SYNCBUSY_CTRLD);
if (period <= SLCD_FC_BYPASS_MAX_MS) {
hri_slcd_set_FC0_reg(dev->hw, SLCD_FC0_PB | ((period / (1000 / SLCD_FRAME_FREQUENCY)) - 1));
} else {
hri_slcd_set_FC0_reg(dev->hw, (((period / (1000 / SLCD_FRAME_FREQUENCY)) / 8 - 1)));
}
hri_slcd_set_CTRLD_FC0EN_bit(dev->hw);
/* Set Blink Segments */
_slcd_sync_set_segment(dev, SLCD_COMNUM(seg), SLCD_SEGNUM(seg), true);
hri_slcd_clear_CTRLD_BLINK_bit(dev->hw);
hri_slcd_clear_CTRLA_ENABLE_bit(dev->hw);
hri_slcd_wait_for_sync(dev->hw, SLCD_SYNCBUSY_ENABLE);
/* Update BCFG */
if (SLCD_SEGNUM(seg) == 0) {
hri_slcd_set_BCFG_BSS0_bf(dev->hw, 1 << SLCD_COMNUM(seg));
} else {
hri_slcd_set_BCFG_BSS1_bf(dev->hw, 1 << SLCD_COMNUM(seg));
}
hri_slcd_set_CTRLA_ENABLE_bit(dev->hw);
hri_slcd_set_CTRLD_BLINK_bit(dev->hw);
return ERR_NONE;
}
/**
* \brief Displays a character
*/
int32_t _slcd_sync_write_char(struct _slcd_sync_device *dev, const uint8_t character, uint32_t index)
{
uint32_t i;
uint32_t data = ~0;
if (cm_setting[index].size == 7) {
for (i = 0; i<sizeof(cm7_lut)>> 2; i++) {
if (cm7_lut[i].character == character) {
data = cm7_lut[i].mapping;
break;
}
}
} else if (cm_setting[index].size == 14) {
for (i = 0; i<sizeof(cm14_lut)>> 2; i++) {
if (cm14_lut[i].character == character) {
data = cm14_lut[i].mapping;
break;
}
}
}
if (data == 0xFFFFFFFF) {
return ERR_INVALID_ARG;
}
hri_slcd_write_CMCFG_NSEG_bf(dev->hw, cm_setting[index].nseg);
hri_slcd_write_CMINDEX_CINDEX_bf(dev->hw, cm_setting[index].com_index);
hri_slcd_write_CMINDEX_SINDEX_bf(dev->hw, cm_setting[index].seg_index);
if (cm_setting[index].size == 7) {
hri_slcd_write_CMDMASK_reg(dev->hw, SEG7_MASK);
} else if (cm_setting[index].size == 14) {
hri_slcd_write_CMDMASK_reg(dev->hw, SEG14_MASK);
}
while (hri_slcd_get_STATUS_CMWRBUSY_bit(dev->hw))
;
hri_slcd_write_CMDATA_reg(dev->hw, data);
return ERR_NONE;
}
/**
* \brief Start animation play by a segment array
*/
int32_t _slcd_sync_start_animation(struct _slcd_sync_device *dev, const uint32_t segs[], uint32_t len,
const uint32_t period)
{
uint32_t i;
uint32_t csrlen = 0;
if (len > 16) {
return ERR_INVALID_ARG;
}
/* COM[0..7], Seg[2,3] support animation */
for (i = 0; i < len; i++) {
if ((SLCD_SEGNUM(segs[i]) != 2 && SLCD_SEGNUM(segs[i]) != 3)) {
return ERR_INVALID_ARG;
}
}
/* Verify period */
if (period > SLCD_FC_MAX_MS || period < SLCD_FC_MIN_MS) {
return ERR_INVALID_ARG;
}
/* Set Period */
_slcd_sync_set_animation_period(dev, period);
/* Set animation segments */
hri_slcd_clear_CTRLA_ENABLE_bit(dev->hw);
hri_slcd_clear_CTRLD_CSREN_bit(dev->hw);
hri_slcd_wait_for_sync(dev->hw, SLCD_SYNCBUSY_ENABLE | SLCD_SYNCBUSY_CTRLD);
hri_slcd_set_CSRCFG_FCS_bf(dev->hw, 1);
hri_slcd_write_CSRCFG_DATA_bf(dev->hw, 0);
for (i = 0; i < len; i++) {
hri_slcd_set_CSRCFG_DATA_bf(dev->hw, (1 << ((SLCD_COMNUM(segs[i]) * 2) + (SLCD_SEGNUM(segs[i]) - 2))));
if (((SLCD_COMNUM(segs[i]) * 2) + (SLCD_SEGNUM(segs[i]) - 2)) > csrlen) {
csrlen = (SLCD_COMNUM(segs[i]) * 2) + (SLCD_SEGNUM(segs[i]) - 2);
}
}
hri_slcd_set_CSRCFG_SIZE_bf(dev->hw, csrlen + 1);
hri_slcd_set_BCFG_MODE_bit(dev->hw);
hri_slcd_set_CTRLD_CSREN_bit(dev->hw);
hri_slcd_set_CTRLA_ENABLE_bit(dev->hw);
return ERR_NONE;
}
/**
* \brief Stop animation play by a segment array
*/
int32_t _slcd_sync_stop_animation(struct _slcd_sync_device *dev, const uint32_t segs[], uint32_t len)
{
/* Not used because of the current version is not supported, Reserved */
(void)segs;
(void)len;
hri_slcd_wait_for_sync(dev->hw, SLCD_SYNCBUSY_CTRLD);
hri_slcd_clear_CTRLD_CSREN_bit(dev->hw);
return ERR_NONE;
}
/**
* \brief Set animation Frequency
*/
int32_t _slcd_sync_set_animation_period(struct _slcd_sync_device *dev, const uint32_t period)
{
hri_slcd_clear_CTRLD_FC1EN_bit(dev->hw);
hri_slcd_wait_for_sync(dev->hw, SLCD_SYNCBUSY_CTRLD);
/* Use Frame Counter 1 for blink */
if (period <= SLCD_FC_BYPASS_MAX_MS) {
hri_slcd_set_FC1_reg(dev->hw, SLCD_FC1_PB | ((period / (1000 / SLCD_FRAME_FREQUENCY)) - 1));
} else {
hri_slcd_set_FC1_reg(dev->hw, (((period / (1000 / SLCD_FRAME_FREQUENCY)) / 8 - 1)));
}
hri_slcd_set_CTRLD_FC1EN_bit(dev->hw);
return ERR_NONE;
}
static int32_t _slcd_sync_set_segment(struct _slcd_sync_device *dev, const uint32_t com, const uint32_t seg,
const bool on)
{
if ((SLCD_COMNUM(seg) >= CONF_SLCD_COM_NUM) || (SLCD_SEGNUM(seg) >= CONF_SLCD_SEG_NUM)) {
return ERR_INVALID_ARG;
}
/* Use register instead hri interface to optimization code */
if (on) {
((uint32_t *)&(((Slcd *)dev->hw)->SDATAL0))[(com * 2) + (seg >> 5)]
|= (seg < 32) ? (1 << seg) : (1 << (seg >> 5));
} else {
((uint32_t *)&(((Slcd *)dev->hw)->SDATAL0))[(com * 2) + (seg >> 5)]
&= ~((seg < 32) ? (1 << seg) : (1 << (seg >> 5)));
}
return ERR_NONE;
}

View File

@@ -0,0 +1,59 @@
/**
* \file
*
* \brief SLCD Character Mapping declaration.
*
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef HPL_SLCD_CM_H_INCLUDED
#define HPL_SLCD_CM_H_INCLUDED
#include <stdint.h>
/* Character Mapping Struct */
struct slcd_char_mapping {
uint32_t character : 8; /*!< ASCII character */
uint32_t mapping : 24; /*!< Mapping value */
};
/* SLCD Character settting Struct */
struct slcd_char_setting {
uint8_t com_index; /*!< Common terminal index, start from 0 */
uint8_t seg_index; /*!< Segment terminal index, start from 0 */
uint8_t nseg; /*!< Number of Segment, this field is used to
indentify which segments line will be
used. For example, if char mapping from
COM1/SEG2 and nseg=2,size=7, then
COM1/SEG2, COM1/SEG3, COM2/SEG2,
COM2/SEG3, COM3/SEG2, COM3/SEG3,
COM4/SEG2 will be used for mapping
*/
uint8_t size; /*!< char size, typical is 7/14/16 */
};
#endif /* HPL_SLCD_CM_H_INCLUDED */

View File

@@ -0,0 +1,104 @@
#include <hpl_slcd_config.h>
/**
* character segments position index
*
* For a 14-segments character, each segment has an unique position index.
* The segment layout and position index value is shown as below.
* The symbol '-', '|', '/', '\' represent the SLCD character segment, and the
* number represent each segment's position index, which equals to macro
* SEG14_0 to SEG14_7.
* The character lookup mapping table use those position index
* (SEG14_0..SEG14_14) to compose some visible arabic numerals, letters or some
* specific ASCII.
* For example char '1' can be represented by use position index 1,2.
* (SEG7_1 | SEG7_2).
* More predefined character lookup can be found at below "14-segment character
* lookup mapping table"
*
* -0
* |5 \6 |7 /8 |1
* -9 -10
* |4 /11 |12 \13 |2
* -3
*/
/**
* Character segment position remapping setting
*
* An SLCD screen typically use several hardware segments to display a
* character(for example from COM3/SEG0 to COM4/SEG7).
* The lowest COM and SEG index is 0 (COM3/SEG0 index is 0).
* The "hardware character segments index" maybe different with the "character
* segments position index". The remapping setting allow application to adjust
* those sequence.
*
*/
#define SEG14_0 (0x1 << CONF_SLCD_CM_14SEGS_0_SETTING)
#define SEG14_1 (0x1 << CONF_SLCD_CM_14SEGS_1_SETTING)
#define SEG14_2 (0x1 << CONF_SLCD_CM_14SEGS_2_SETTING)
#define SEG14_3 (0x1 << CONF_SLCD_CM_14SEGS_3_SETTING)
#define SEG14_4 (0x1 << CONF_SLCD_CM_14SEGS_4_SETTING)
#define SEG14_5 (0x1 << CONF_SLCD_CM_14SEGS_5_SETTING)
#define SEG14_6 (0x1 << CONF_SLCD_CM_14SEGS_6_SETTING)
#define SEG14_7 (0x1 << CONF_SLCD_CM_14SEGS_7_SETTING)
#define SEG14_8 (0x1 << CONF_SLCD_CM_14SEGS_8_SETTING)
#define SEG14_9 (0x1 << CONF_SLCD_CM_14SEGS_9_SETTING)
#define SEG14_10 (0x1 << CONF_SLCD_CM_14SEGS_10_SETTING)
#define SEG14_11 (0x1 << CONF_SLCD_CM_14SEGS_11_SETTING)
#define SEG14_12 (0x1 << CONF_SLCD_CM_14SEGS_12_SETTING)
#define SEG14_13 (0x1 << CONF_SLCD_CM_14SEGS_13_SETTING)
/**
* 17-segments character mask value
*/
#define SEG14_MASK \
(0xFFFFFF \
& ~(SEG14_0 | SEG14_1 | SEG14_2 | SEG14_3 | SEG14_4 | SEG14_5 | SEG14_6 | SEG14_7 | SEG14_8 | SEG14_9 | SEG14_10 \
| SEG14_11 | SEG14_12 | SEG14_13))
/**
* 14-segment character lookup mapping table
* struct slcd_char_mapping;
*/
#define SLCD_SEG14_LUT \
{ \
{'0', SEG14_0 | SEG14_1 | SEG14_2 | SEG14_3 | SEG14_4 | SEG14_5 | SEG14_8 | SEG14_11}, \
{'1', SEG14_1 | SEG14_2}, {'2', SEG14_0 | SEG14_1 | SEG14_3 | SEG14_4 | SEG14_9 | SEG14_10}, \
{'3', SEG14_0 | SEG14_1 | SEG14_2 | SEG14_3 | SEG14_9 | SEG14_10}, \
{'4', SEG14_1 | SEG14_2 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'5', SEG14_0 | SEG14_2 | SEG14_3 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'6', SEG14_0 | SEG14_2 | SEG14_3 | SEG14_4 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'7', SEG14_0 | SEG14_1 | SEG14_2}, \
{'8', SEG14_0 | SEG14_1 | SEG14_2 | SEG14_3 | SEG14_4 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'9', SEG14_0 | SEG14_1 | SEG14_2 | SEG14_3 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'a', SEG14_0 | SEG14_1 | SEG14_2 | SEG14_4 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'b', SEG14_0 | SEG14_1 | SEG14_2 | SEG14_3 | SEG14_7 | SEG14_10 | SEG14_12}, \
{'c', SEG14_0 | SEG14_3 | SEG14_4 | SEG14_5}, \
{'d', SEG14_0 | SEG14_1 | SEG14_2 | SEG14_3 | SEG14_7 | SEG14_12}, \
{'e', SEG14_0 | SEG14_3 | SEG14_4 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'f', SEG14_0 | SEG14_4 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'g', SEG14_0 | SEG14_2 | SEG14_3 | SEG14_4 | SEG14_5 | SEG14_10}, \
{'h', SEG14_1 | SEG14_2 | SEG14_4 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'i', SEG14_1 | SEG14_2 | SEG14_4 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'j', SEG14_1 | SEG14_2 | SEG14_3 | SEG14_4}, {'k', SEG14_4 | SEG14_5 | SEG14_8 | SEG14_9 | SEG14_13}, \
{'l', SEG14_3 | SEG14_4 | SEG14_5}, {'m', SEG14_1 | SEG14_2 | SEG14_4 | SEG14_5 | SEG14_6 | SEG14_8}, \
{'n', SEG14_1 | SEG14_2 | SEG14_4 | SEG14_5 | SEG14_6 | SEG14_13}, \
{'o', SEG14_0 | SEG14_1 | SEG14_2 | SEG14_3 | SEG14_4 | SEG14_5}, \
{'p', SEG14_0 | SEG14_1 | SEG14_4 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'q', SEG14_0 | SEG14_1 | SEG14_2 | SEG14_3 | SEG14_4 | SEG14_5 | SEG14_13}, \
{'r', SEG14_0 | SEG14_1 | SEG14_4 | SEG14_5 | SEG14_9 | SEG14_10 | SEG14_13}, \
{'s', SEG14_0 | SEG14_3 | SEG14_5 | SEG14_9 | SEG14_13}, {'t', SEG14_0 | SEG14_7 | SEG14_12}, \
{'u', SEG14_1 | SEG14_2 | SEG14_3 | SEG14_4 | SEG14_5}, {'v', SEG14_4 | SEG14_5 | SEG14_8 | SEG14_11}, \
{'w', SEG14_1 | SEG14_2 | SEG14_4 | SEG14_5 | SEG14_11 | SEG14_13}, \
{'x', SEG14_6 | SEG14_8 | SEG14_11 | SEG14_13}, \
{'y', SEG14_1 | SEG14_2 | SEG14_3 | SEG14_5 | SEG14_9 | SEG14_10}, \
{'z', SEG14_0 | SEG14_3 | SEG14_8 | SEG14_11}, {'-', SEG14_9 | SEG14_10}, \
{'+', SEG14_7 | SEG14_9 | SEG14_10 | SEG14_12}, {'/', SEG14_8 | SEG14_11}, \
{'=', SEG14_3 | SEG14_9 | SEG14_10}, \
{'#', SEG14_1 | SEG14_2 | SEG14_3 | SEG14_7 | SEG14_9 | SEG14_10 | SEG14_12}, \
{'*', SEG14_6 | SEG14_8 | SEG14_11 | SEG14_13}, {'\'', SEG14_13}, {')', SEG14_6 | SEG14_11}, \
{'(', SEG14_8 | SEG14_13}, {'@', SEG14_0 | SEG14_1 | SEG14_2 | SEG14_3 | SEG14_4 | SEG14_9 | SEG14_13}, \
{'$', SEG14_0 | SEG14_2 | SEG14_3 | SEG14_5 | SEG14_7 | SEG14_9 | SEG14_10 | SEG14_12}, \
{'%', SEG14_2 | SEG14_5 | SEG14_8 | SEG14_11}, {'\\', SEG14_6 | SEG14_13}, {'_', SEG14_3}, {0, 0}, \
}

View File

@@ -0,0 +1,68 @@
#include <hpl_slcd_config.h>
/**
* character segments position index
*
* For a 7 segments character, each segment has an unique position index.
* The segment layout and position index value is shown as below.
* The symbol '-', '|' represent the SLCD character segment, and the
* number represent each segment's position index, which equals to macro
* SEG7_0 to SEG7_7.
* The character lookup mapping table use those position index (SEG7_0..SEG7_7)
* to compose some visible arabic numerals, letters or some specific ASCII.
* For example char '0' can be represented by use position index 0,1,2,3,4,5.
* (SEG7_0 | SEG7_1 | SEG7_2 | SEG7_3 | SEG7_4 | SEG7_5).
* More predefined character lookup can be found at below "7-segments character
* lookup mapping table"
* -0
* |5 |1
* -6
* |4 |2
* -3
*/
/**
* Character segment position remapping setting
*
* An SLCD screen typically use several hardware segments to display a
* character(for example from COM3/SEG0 to COM3/SEG7).
* The lowest COM and SEG index is 0 (COM3/SEG0 index is 0).
* The "hardware character segments index" maybe different with the "character
* segments position index". The remapping setting allow application to adjust
* those sequence.
*
*/
#define SEG7_0 (0x1 << CONF_SLCD_CM_7SEGS_0_SETTING)
#define SEG7_1 (0x1 << CONF_SLCD_CM_7SEGS_1_SETTING)
#define SEG7_2 (0x1 << CONF_SLCD_CM_7SEGS_2_SETTING)
#define SEG7_3 (0x1 << CONF_SLCD_CM_7SEGS_3_SETTING)
#define SEG7_4 (0x1 << CONF_SLCD_CM_7SEGS_4_SETTING)
#define SEG7_5 (0x1 << CONF_SLCD_CM_7SEGS_5_SETTING)
#define SEG7_6 (0x1 << CONF_SLCD_CM_7SEGS_6_SETTING)
/**
* 7-segments character mask value
*/
#define SEG7_MASK (0xFFFFFF & ~(SEG7_0 | SEG7_1 | SEG7_2 | SEG7_3 | SEG7_4 | SEG7_5 | SEG7_6))
/**
* 7-segments character lookup mapping table.
*
* Array value of slcd_char_mapping struct, application can add or remove
* item from it.
*/
#define SLCD_SEG7_LUT \
{ \
{0, 0}, {'0', SEG7_0 | SEG7_1 | SEG7_2 | SEG7_3 | SEG7_4 | SEG7_5}, {'1', SEG7_1 | SEG7_2}, \
{'2', SEG7_0 | SEG7_1 | SEG7_3 | SEG7_4 | SEG7_6}, {'3', SEG7_0 | SEG7_1 | SEG7_2 | SEG7_3 | SEG7_6}, \
{'4', SEG7_1 | SEG7_2 | SEG7_5 | SEG7_6}, {'5', SEG7_0 | SEG7_2 | SEG7_3 | SEG7_5 | SEG7_6}, \
{'6', SEG7_0 | SEG7_2 | SEG7_3 | SEG7_4 | SEG7_5 | SEG7_6}, {'7', SEG7_0 | SEG7_1 | SEG7_2}, \
{'8', SEG7_0 | SEG7_1 | SEG7_2 | SEG7_3 | SEG7_4 | SEG7_5 | SEG7_6}, \
{'9', SEG7_0 | SEG7_1 | SEG7_2 | SEG7_5 | SEG7_6}, \
{'a', SEG7_0 | SEG7_1 | SEG7_2 | SEG7_4 | SEG7_5 | SEG7_6}, \
{'b', SEG7_2 | SEG7_3 | SEG7_4 | SEG7_5 | SEG7_6}, {'c', SEG7_0 | SEG7_3 | SEG7_4 | SEG7_5}, \
{'d', SEG7_1 | SEG7_2 | SEG7_3 | SEG7_4 | SEG7_6}, {'e', SEG7_0 | SEG7_3 | SEG7_4 | SEG7_5 | SEG7_6}, \
{ \
'f', SEG7_0 | SEG7_4 | SEG7_5 | SEG7_6 \
} \
}

View File

@@ -0,0 +1,103 @@
/**
* \file
*
* \brief SysTick related functionality implementation.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <hpl_time_measure.h>
#include <hpl_systick_config.h>
/**
* \brief Initialize system time module
*/
void _system_time_init(void *const hw)
{
(void)hw;
SysTick->LOAD = (0xFFFFFF << SysTick_LOAD_RELOAD_Pos);
SysTick->CTRL = (1 << SysTick_CTRL_ENABLE_Pos) | (CONF_SYSTICK_TICKINT << SysTick_CTRL_TICKINT_Pos)
| (1 << SysTick_CTRL_CLKSOURCE_Pos);
}
/**
* \brief Initialize delay functionality
*/
void _delay_init(void *const hw)
{
_system_time_init(hw);
}
/**
* \brief De-initialize system time module
*/
void _system_time_deinit(void *const hw)
{
(void)hw;
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
/**
* \brief Get system time
*/
system_time_t _system_time_get(const void *const hw)
{
(void)hw;
return (system_time_t)SysTick->VAL;
}
/**
* \brief Get maximum possible system time
*/
system_time_t _system_time_get_max_time_value(const void *const hw)
{
(void)hw;
return 0xFFFFFF;
}
/**
* \brief Delay loop to delay n number of cycles
*/
void _delay_cycles(void *const hw, uint32_t cycles)
{
(void)hw;
uint8_t n = cycles >> 24;
uint32_t buf = cycles;
while (n--) {
SysTick->LOAD = 0xFFFFFF;
SysTick->VAL = 0xFFFFFF;
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk))
;
buf -= 0xFFFFFF;
}
SysTick->LOAD = buf;
SysTick->VAL = buf;
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk))
;
}

View File

@@ -0,0 +1,374 @@
/**
* \file
*
* \brief SAM TC
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <hpl_pwm.h>
#include <hpl_tc_config.h>
#include <hpl_timer.h>
#include <utils.h>
#include <utils_assert.h>
#include <hpl_tc_base.h>
#ifndef CONF_TC0_ENABLE
#define CONF_TC0_ENABLE 0
#endif
#ifndef CONF_TC1_ENABLE
#define CONF_TC1_ENABLE 0
#endif
#ifndef CONF_TC2_ENABLE
#define CONF_TC2_ENABLE 0
#endif
#ifndef CONF_TC3_ENABLE
#define CONF_TC3_ENABLE 0
#endif
#ifndef CONF_TC4_ENABLE
#define CONF_TC4_ENABLE 0
#endif
#ifndef CONF_TC5_ENABLE
#define CONF_TC5_ENABLE 0
#endif
#ifndef CONF_TC6_ENABLE
#define CONF_TC6_ENABLE 0
#endif
#ifndef CONF_TC7_ENABLE
#define CONF_TC7_ENABLE 0
#endif
/**
* \brief Macro is used to fill usart configuration structure based on its
* number
*
* \param[in] n The number of structures
*/
#define TC_CONFIGURATION(n) \
{ \
n, TC##n##_IRQn, \
TC_CTRLA_MODE(CONF_TC##n##_MODE) | TC_CTRLA_PRESCSYNC(CONF_TC##n##_PRESCSYNC) \
| (CONF_TC##n##_RUNSTDBY << TC_CTRLA_RUNSTDBY_Pos) | (CONF_TC##n##_ONDEMAND << TC_CTRLA_ONDEMAND_Pos) \
| TC_CTRLA_PRESCALER(CONF_TC##n##_PRESCALER) | (CONF_TC##n##_ALOCK << TC_CTRLA_ALOCK_Pos), \
(CONF_TC##n##_OVFEO << TC_EVCTRL_OVFEO_Pos) | (CONF_TC##n##_TCEI << TC_EVCTRL_TCEI_Pos) \
| (CONF_TC##n##_TCINV << TC_EVCTRL_TCINV_Pos) | (CONF_TC##n##_EVACT << TC_EVCTRL_EVACT_Pos) \
| (CONF_TC##n##_MCEO0 << TC_EVCTRL_MCEO0_Pos) | (CONF_TC##n##_MCEO1 << TC_EVCTRL_MCEO1_Pos), \
(CONF_TC##n##_DBGRUN << TC_DBGCTRL_DBGRUN_Pos), CONF_TC##n##_PER, CONF_TC##n##_CC0, CONF_TC##n##_CC1, \
}
/**
* \brief TC configuration type
*/
struct tc_configuration {
uint8_t number;
IRQn_Type irq;
hri_tc_ctrla_reg_t ctrl_a;
hri_tc_evctrl_reg_t event_ctrl;
hri_tc_dbgctrl_reg_t dbg_ctrl;
hri_tccount8_per_reg_t per;
hri_tccount32_cc_reg_t cc0;
hri_tccount32_cc_reg_t cc1;
};
/**
* \brief Array of TC configurations
*/
static struct tc_configuration _tcs[] = {
#if CONF_TC0_ENABLE == 1
TC_CONFIGURATION(0),
#endif
#if CONF_TC1_ENABLE == 1
TC_CONFIGURATION(1),
#endif
#if CONF_TC2_ENABLE == 1
TC_CONFIGURATION(2),
#endif
#if CONF_TC3_ENABLE == 1
TC_CONFIGURATION(3),
#endif
#if CONF_TC4_ENABLE == 1
TC_CONFIGURATION(4),
#endif
#if CONF_TC5_ENABLE == 1
TC_CONFIGURATION(5),
#endif
#if CONF_TC6_ENABLE == 1
TC_CONFIGURATION(6),
#endif
#if CONF_TC7_ENABLE == 1
TC_CONFIGURATION(7),
#endif
};
/**
* \brief Set of pointer to hal_pwm helper functions
*/
static struct _pwm_hpl_interface _tc_pwm_functions = {
_tc_pwm_init,
_tc_pwm_deinit,
_tc_start_pwm,
_tc_stop_pwm,
_tc_set_pwm_param,
_tc_is_pwm_enabled,
_tc_pwm_get_period,
_tc_pwm_get_duty,
_tc_pwm_set_irq_state,
};
static struct _pwm_device *_tc3_dev = NULL;
static int8_t get_tc_index(const void *const hw);
static void _tc_init_irq_param(const void *const hw, void *dev);
static inline uint8_t _get_hardware_offset(const void *const hw);
/**
* \brief Initialize TC for PWM mode
*/
int32_t _tc_pwm_init(struct _pwm_device *const device, void *const hw)
{
int8_t i = get_tc_index(hw);
device->hw = hw;
if (!hri_tc_is_syncing(hw, TC_SYNCBUSY_SWRST)) {
if (hri_tc_get_CTRLA_reg(hw, TC_CTRLA_ENABLE)) {
hri_tc_clear_CTRLA_ENABLE_bit(hw);
hri_tc_wait_for_sync(hw, TC_SYNCBUSY_ENABLE);
}
hri_tc_write_CTRLA_reg(hw, TC_CTRLA_SWRST);
}
hri_tc_wait_for_sync(hw, TC_SYNCBUSY_SWRST);
hri_tc_write_CTRLA_reg(hw, _tcs[i].ctrl_a);
hri_tc_write_DBGCTRL_reg(hw, _tcs[i].dbg_ctrl);
hri_tc_write_EVCTRL_reg(hw, _tcs[i].event_ctrl);
hri_tc_write_WAVE_reg(hw, TC_WAVE_WAVEGEN_MPWM_Val);
if ((_tcs[i].ctrl_a & TC_CTRLA_MODE_Msk) == TC_CTRLA_MODE_COUNT32) {
hri_tccount32_write_CC_reg(hw, 0, _tcs[i].cc0);
hri_tccount32_write_CC_reg(hw, 1, _tcs[i].cc1);
} else if ((_tcs[i].ctrl_a & TC_CTRLA_MODE_Msk) == TC_CTRLA_MODE_COUNT16) {
hri_tccount16_write_CC_reg(hw, 0, (uint16_t)_tcs[i].cc0);
hri_tccount16_write_CC_reg(hw, 1, (uint16_t)_tcs[i].cc1);
} else {
/* 8-bit resolution is not accepted by duty cycle control */
return -1;
}
_tc_init_irq_param(hw, (void *)device);
NVIC_DisableIRQ(_tcs[i].irq);
NVIC_ClearPendingIRQ(_tcs[i].irq);
NVIC_EnableIRQ(_tcs[i].irq);
return 0;
}
/**
* \brief De-initialize TC for PWM mode
*/
void _tc_pwm_deinit(struct _pwm_device *const device)
{
void *const hw = device->hw;
int8_t i = get_tc_index(hw);
ASSERT(ARRAY_SIZE(_tcs));
NVIC_DisableIRQ(_tcs[i].irq);
hri_tc_clear_CTRLA_ENABLE_bit(hw);
hri_tc_set_CTRLA_SWRST_bit(hw);
}
/**
* \brief Start PWM
*/
void _tc_start_pwm(struct _pwm_device *const device)
{
hri_tc_set_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Stop PWM
*/
void _tc_stop_pwm(struct _pwm_device *const device)
{
hri_tc_clear_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Set PWM parameter
*/
void _tc_set_pwm_param(struct _pwm_device *const device, const pwm_period_t period, const pwm_period_t duty_cycle)
{
void *const hw = device->hw;
int8_t i = get_tc_index(hw);
_tcs[i].cc0 = period;
_tcs[i].cc1 = duty_cycle;
if ((_tcs[i].ctrl_a & TC_CTRLA_MODE_Msk) == TC_CTRLA_MODE_COUNT32) {
hri_tccount32_write_CC_reg(hw, 0, _tcs[i].cc0);
hri_tccount32_write_CC_reg(hw, 1, _tcs[i].cc1);
} else {
hri_tccount16_write_CC_reg(hw, 0, _tcs[i].cc0);
hri_tccount16_write_CC_reg(hw, 1, _tcs[i].cc1);
}
}
/**
* \brief Get pwm waveform period value
*/
pwm_period_t _tc_pwm_get_period(const struct _pwm_device *const device)
{
void *const hw = device->hw;
int8_t i = get_tc_index(hw);
if ((_tcs[i].ctrl_a & TC_CTRLA_MODE_Msk) == TC_CTRLA_MODE_COUNT32) {
return (pwm_period_t)(hri_tccount32_read_CC_reg(hw, 0));
} else {
return (pwm_period_t)(hri_tccount16_read_CC_reg(hw, 0));
}
}
/**
* \brief Get pwm waveform duty cycle
*/
uint32_t _tc_pwm_get_duty(const struct _pwm_device *const device)
{
void *const hw = device->hw;
int8_t i = get_tc_index(hw);
uint32_t per;
uint32_t duty_cycle;
if ((_tcs[i].ctrl_a & TC_CTRLA_MODE_Msk) == TC_CTRLA_MODE_COUNT32) {
per = hri_tccount32_read_CC_reg(hw, 0);
duty_cycle = hri_tccount32_read_CC_reg(hw, 1);
} else {
per = hri_tccount16_read_CC_reg(hw, 0);
duty_cycle = hri_tccount16_read_CC_reg(hw, 1);
}
return ((duty_cycle * 1000) / per);
}
/**
* \brief Check if PWM is running
*/
bool _tc_is_pwm_enabled(const struct _pwm_device *const device)
{
return hri_tc_get_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Enable/disable PWM interrupt
*/
void _tc_pwm_set_irq_state(struct _pwm_device *const device, const enum _pwm_callback_type type, const bool disable)
{
ASSERT(device);
if (PWM_DEVICE_PERIOD_CB == type) {
hri_tc_write_INTEN_OVF_bit(device->hw, disable);
} else if (PWM_DEVICE_ERROR_CB == type) {
hri_tc_write_INTEN_ERR_bit(device->hw, disable);
}
}
/**
* \brief Retrieve timer helper functions
*/
struct _timer_hpl_interface *_tc_get_timer(void)
{
return NULL;
}
/**
* \brief Retrieve pwm helper functions
*/
struct _pwm_hpl_interface *_tc_get_pwm(void)
{
return &_tc_pwm_functions;
}
/**
* \internal TC interrupt handler for PWM
*
* \param[in] instance TC instance number
*/
static void tc_pwm_interrupt_handler(struct _pwm_device *device)
{
void *const hw = device->hw;
if (hri_tc_get_interrupt_OVF_bit(hw)) {
hri_tc_clear_interrupt_OVF_bit(hw);
if (NULL != device->callback.pwm_period_cb) {
device->callback.pwm_period_cb(device);
}
}
if (hri_tc_get_INTEN_ERR_bit(hw)) {
hri_tc_clear_interrupt_ERR_bit(hw);
if (NULL != device->callback.pwm_error_cb) {
device->callback.pwm_error_cb(device);
}
}
}
/**
* \brief TC interrupt handler
*/
void TC3_Handler(void)
{
tc_pwm_interrupt_handler(_tc3_dev);
}
/**
* \internal Retrieve TC index
*
* \param[in] hw The pointer to hardware instance
*
* \return The index of TC configuration
*/
static int8_t get_tc_index(const void *const hw)
{
uint8_t index = _get_hardware_offset(hw);
uint8_t i;
for (i = 0; i < ARRAY_SIZE(_tcs); i++) {
if (_tcs[i].number == index) {
return i;
}
}
ASSERT(false);
return -1;
}
/**
* \brief Init irq param with the given tc hardware instance
*/
static void _tc_init_irq_param(const void *const hw, void *dev)
{
if (hw == TC3) {
_tc3_dev = (struct _pwm_device *)dev;
}
}
/**
* \internal Retrieve TC hardware index
*
* \param[in] hw The pointer to hardware instance
*/
static inline uint8_t _get_hardware_offset(const void *const hw)
{
return (((uint32_t)hw - (uint32_t)TC0) >> 10);
}

View File

@@ -0,0 +1,160 @@
/**
* \file
*
* \brief SAM Timer/Counter
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*/
#ifndef _HPL_TC_BASE_H_INCLUDED
#define _HPL_TC_BASE_H_INCLUDED
#include <hpl_timer.h>
#include <hpl_pwm.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup tc_group TC Hardware Proxy Layer
*
* \section tc_hpl_rev Revision History
* - v0.0.0.1 Initial Commit
*
*@{
*/
/**
* \name HPL functions
*/
//@{
/**
* \brief Retrieve timer helper functions
*
* \return A pointer to set of timer helper functions
*/
struct _timer_hpl_interface *_tc_get_timer(void);
/**
* \brief Initialize TC for PWM
*
* This function does low level TC configuration.
*
* \param[in] device The pointer to TC device instance
* \param[in] hw The pointer to hardware instance
*
* \return Initialization status.
*/
int32_t _tc_pwm_init(struct _pwm_device *const device, void *const hw);
/**
* \brief De-initialize TC for PWM
*
* \param[in] device The pointer to TC device instance
*/
void _tc_pwm_deinit(struct _pwm_device *const device);
/**
* \brief Retrieve offset of the given tc hardware instance
*
* \param[in] device The pointer to TC device instance
*
* \return The offset of the given tc hardware instance
*/
uint8_t _tc_pwm_get_hardware_offset(const struct _pwm_device *const device);
/**
* \brief Start PWM
*
* \param[in] device The pointer to TC device instance
*/
void _tc_start_pwm(struct _pwm_device *const device);
/**
* \brief Stop PWM
*
* \param[in] device The pointer to TC device instance
*/
void _tc_stop_pwm(struct _pwm_device *const device);
/**
* \brief Check if PWM is running
*
* \param[in] device The pointer to TC device instance
*
* \return Check status.
* \retval true The given timer is running
* \retval false The given timer is not running
*/
bool _tc_is_pwm_enabled(const struct _pwm_device *const device);
/**
* \brief Set PWM parameter
* \param[in] device The pointer to TC device instance
* \param[in] period Total period of one PWM cycle.
* \param[in] duty_cycle Period of PWM first half during one cycle.
*/
void _tc_set_pwm_param(struct _pwm_device *const device, const pwm_period_t period, const pwm_period_t duty_cycle);
/**
* \brief Get pwm waveform period value
* \param[in] device The pointer to TC device instance
* \return Period value.
*/
pwm_period_t _tc_pwm_get_period(const struct _pwm_device *const device);
/**
* \brief Get pwm waveform duty cycle value
* \param[in] device The pointer to TC device instance
* \return Duty cycle value
*/
uint32_t _tc_pwm_get_duty(const struct _pwm_device *const device);
/**
* \brief Enable/disable PWM interrupt
*
* param[in] device The pointer to PWM device instance
* param[in] type The type of interrupt to disable/enable if applicable
* param[in] disable Enable or disable
*/
void _tc_pwm_set_irq_state(struct _pwm_device *const device, const enum _pwm_callback_type type, const bool disable);
/**
* \brief Retrieve pwm helper functions
*
* \return A pointer to set of pwm helper functions
*/
struct _pwm_hpl_interface *_tc_get_pwm(void);
//@}
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* _HPL_TC_BASE_H_INCLUDED */

View File

@@ -0,0 +1,364 @@
/**
* \file
*
* \brief SAM TCC
*
* Copyright (c) 2014-2019 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include <compiler.h>
#include <hpl_pwm.h>
#include <hpl_tcc.h>
#include <hpl_tcc_config.h>
#include <hpl_timer.h>
#include <utils.h>
#include <utils_assert.h>
/**
* \brief TCC configuration type
*/
struct tcc_cfg {
void * hw; /*!< instance of TCC */
IRQn_Type irq;
hri_tcc_ctrla_reg_t ctrl_a;
hri_tcc_ctrlbset_reg_t ctrl_b;
hri_tcc_dbgctrl_reg_t dbg_ctrl;
hri_tcc_evctrl_reg_t event_ctrl;
hri_tcc_cc_reg_t cc0;
hri_tcc_cc_reg_t cc1;
hri_tcc_cc_reg_t cc2;
hri_tcc_cc_reg_t cc3;
hri_tcc_per_reg_t per;
};
/**
* \brief pwm configuration type
*/
struct tcc_pwm_cfg {
void * hw; /*!< instance of TCC */
IRQn_Type irq;
uint8_t sel_ch;
uint32_t period;
uint32_t duty_cycle;
uint32_t wave;
};
/**
* \internal Retrieve configuration
*
* \param[in] hw The pointer of TCC base address
*
* \return The configuration
*/
static struct tcc_cfg *_get_tcc_cfg(void *hw);
/**
* \brief Array of TCC configurations
*/
static struct tcc_cfg _cfgs[1] = {
{(void *)TCC0,
TCC0_IRQn,
CONF_TCC0_CTRLA,
CONF_TCC0_CTRLB,
CONF_TCC0_DBGCTRL,
CONF_TCC0_EVCTRL,
CONF_TCC0_CC0,
CONF_TCC0_CC1,
CONF_TCC0_CC2,
CONF_TCC0_CC3,
CONF_TCC0_PER},
};
/**
* \internal Retrieve configuration
*
* \param[in] hw The pointer of TCC base address
*
* \return The configuration
*/
static struct tcc_pwm_cfg *_get_tcc_pwm_cfg(void *hw);
/**
* \brief Array of PWM configurations
*/
static struct tcc_pwm_cfg _cfgs_pwm[1] = {
{(void *)TCC0,
TCC0_IRQn,
CONF_TCC0_SEL_CH,
CONF_TCC0_PER_REG,
CONF_TCC0_CCX_REG,
(CONF_TCC0_WAVEGEN << TCC_WAVE_WAVEGEN_Pos)},
};
/* Renamed access REG name PERB -> PERBUF */
#define hri_tcc_write_PERB_reg hri_tcc_write_PERBUF_reg
#define hri_tcc_read_PERB_reg hri_tcc_read_PERBUF_reg
/** Renamed access REG name CCB -> CCBUF */
#define hri_tcc_write_CCB_reg hri_tcc_write_CCBUF_reg
#define hri_tcc_read_CCB_reg hri_tcc_read_CCBUF_reg
static struct _pwm_device *_tcc0_dev = NULL;
/**
* \brief Set of pointer to hal_pwm helper functions
*/
static struct _pwm_hpl_interface _tcc_pwm_functions = {
_tcc_pwm_init,
_tcc_pwm_deinit,
_tcc_start_pwm,
_tcc_stop_pwm,
_tcc_set_pwm_param,
_tcc_is_pwm_enabled,
_tcc_pwm_get_period,
_tcc_pwm_get_duty,
_tcc_pwm_set_irq_state,
};
/**
* \brief Init irq param with the given tcc hardware instance
*/
static void _tcc_init_irq_param(const void *const hw, void *dev)
{
if (hw == TCC0) {
_tcc0_dev = (struct _pwm_device *)dev;
}
}
/**
* \brief Initialize TCC for PWM mode
*/
int32_t _tcc_pwm_init(struct _pwm_device *const device, void *const hw)
{
struct tcc_cfg *cfg = _get_tcc_cfg(hw);
if (cfg == NULL) {
return ERR_NOT_FOUND;
}
struct tcc_pwm_cfg *cfg_pwm = _get_tcc_pwm_cfg(hw);
if (cfg_pwm == NULL) {
return ERR_NOT_FOUND;
}
device->hw = hw;
if (!hri_tcc_is_syncing(hw, TCC_SYNCBUSY_SWRST)) {
if (hri_tcc_get_CTRLA_reg(hw, TCC_CTRLA_ENABLE)) {
hri_tcc_clear_CTRLA_ENABLE_bit(hw);
hri_tcc_wait_for_sync(hw, TCC_SYNCBUSY_ENABLE);
}
hri_tcc_write_CTRLA_reg(hw, TCC_CTRLA_SWRST);
}
hri_tcc_wait_for_sync(hw, TCC_SYNCBUSY_SWRST);
hri_tcc_write_CTRLA_reg(hw, cfg->ctrl_a);
hri_tcc_set_CTRLB_reg(hw, cfg->ctrl_b);
hri_tcc_write_DBGCTRL_reg(hw, cfg->dbg_ctrl);
hri_tcc_write_EVCTRL_reg(hw, cfg->event_ctrl);
hri_tcc_write_WAVE_reg(hw, cfg_pwm->wave);
hri_tcc_write_PER_reg(hw, cfg_pwm->period);
cfg->per = cfg_pwm->period;
switch (cfg_pwm->sel_ch) {
case 0:
cfg->cc0 = cfg_pwm->duty_cycle;
hri_tcc_write_CC_reg(hw, 0, cfg->cc0);
break;
case 1:
cfg->cc1 = cfg_pwm->duty_cycle;
hri_tcc_write_CC_reg(hw, 1, cfg->cc1);
break;
case 2:
cfg->cc2 = cfg_pwm->duty_cycle;
hri_tcc_write_CC_reg(hw, 2, cfg->cc2);
break;
case 3:
cfg->cc3 = cfg_pwm->duty_cycle;
hri_tcc_write_CC_reg(hw, 3, cfg->cc3);
break;
default:
return ERR_NO_RESOURCE;
break;
}
hri_tcc_clear_CTRLB_LUPD_bit(hw);
_tcc_init_irq_param(hw, (void *)device);
NVIC_DisableIRQ((IRQn_Type)cfg_pwm->irq);
NVIC_ClearPendingIRQ((IRQn_Type)cfg_pwm->irq);
NVIC_EnableIRQ((IRQn_Type)cfg_pwm->irq);
return ERR_NONE;
}
/**
* \brief De-initialize TCC for PWM mode
*/
void _tcc_pwm_deinit(struct _pwm_device *const device)
{
void *const hw = device->hw;
struct tcc_pwm_cfg *cfg_pwm = _get_tcc_pwm_cfg(hw);
if (cfg_pwm != NULL) {
NVIC_DisableIRQ((IRQn_Type)cfg_pwm->irq);
hri_tcc_clear_CTRLA_ENABLE_bit(hw);
hri_tcc_set_CTRLA_SWRST_bit(hw);
}
}
/**
* \brief Start PWM
*/
void _tcc_start_pwm(struct _pwm_device *const device)
{
hri_tcc_set_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Stop PWM
*/
void _tcc_stop_pwm(struct _pwm_device *const device)
{
hri_tcc_clear_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Set PWM parameter
*/
void _tcc_set_pwm_param(struct _pwm_device *const device, const pwm_period_t period, const pwm_period_t duty_cycle)
{
void *const hw = device->hw;
struct tcc_pwm_cfg *cfg_pwm = _get_tcc_pwm_cfg(hw);
if (cfg_pwm != NULL) {
hri_tcc_write_PERB_reg(hw, period);
hri_tcc_write_CCB_reg(hw, cfg_pwm->sel_ch, duty_cycle);
;
}
}
/**
* \brief Get pwm waveform period value
*/
pwm_period_t _tcc_pwm_get_period(const struct _pwm_device *const device)
{
return (pwm_period_t)(hri_tcc_read_PERB_reg(device->hw));
}
/**
* \brief Get pwm waveform duty cycle
*/
uint32_t _tcc_pwm_get_duty(const struct _pwm_device *const device)
{
void *const hw = device->hw;
struct tcc_pwm_cfg *cfg_pwm = _get_tcc_pwm_cfg(hw);
if (cfg_pwm == NULL) {
return ERR_NOT_FOUND;
}
uint32_t per = hri_tcc_read_PERB_reg(hw);
uint32_t duty_cycle = hri_tcc_read_CCB_reg(hw, cfg_pwm->sel_ch);
return ((duty_cycle * 1000) / per);
}
/**
* \brief Check if PWM is running
*/
bool _tcc_is_pwm_enabled(const struct _pwm_device *const device)
{
return hri_tcc_get_CTRLA_ENABLE_bit(device->hw);
}
/**
* \brief Enable/disable PWM interrupt
*/
void _tcc_pwm_set_irq_state(struct _pwm_device *const device, const enum _pwm_callback_type type, const bool disable)
{
ASSERT(device);
if (PWM_DEVICE_PERIOD_CB == type) {
hri_tcc_write_INTEN_OVF_bit(device->hw, disable);
} else if (PWM_DEVICE_ERROR_CB == type) {
hri_tcc_write_INTEN_ERR_bit(device->hw, disable);
}
}
/**
* \brief Retrieve timer helper functions
*/
struct _timer_hpl_interface *_tcc_get_timer(void)
{
return NULL;
}
/**
* \brief Retrieve pwm helper functions
*/
struct _pwm_hpl_interface *_tcc_get_pwm(void)
{
return &_tcc_pwm_functions;
}
/**
* \internal TC interrupt handler for PWM
*
* \param[in] instance TC instance number
*/
static void tcc_pwm_interrupt_handler(struct _pwm_device *device)
{
void *const hw = device->hw;
if (hri_tcc_get_interrupt_OVF_bit(hw)) {
hri_tcc_clear_interrupt_OVF_bit(hw);
if (NULL != device->callback.pwm_period_cb) {
device->callback.pwm_period_cb(device);
}
}
if (hri_tcc_get_INTEN_ERR_bit(hw)) {
hri_tcc_clear_interrupt_ERR_bit(hw);
if (NULL != device->callback.pwm_error_cb) {
device->callback.pwm_error_cb(device);
}
}
}
/**
* \brief TCC interrupt handler
*/
void TCC0_Handler(void)
{
tcc_pwm_interrupt_handler(_tcc0_dev);
}
static struct tcc_cfg *_get_tcc_cfg(void *hw)
{
uint8_t i;
for (i = 0; i < ARRAY_SIZE(_cfgs); i++) {
if (_cfgs[i].hw == hw) {
return &(_cfgs[i]);
}
}
return NULL;
}
static struct tcc_pwm_cfg *_get_tcc_pwm_cfg(void *hw)
{
uint8_t i;
for (i = 0; i < ARRAY_SIZE(_cfgs_pwm); i++) {
if (_cfgs_pwm[i].hw == hw) {
return &(_cfgs_pwm[i]);
}
}
return NULL;
}

View File

@@ -0,0 +1,160 @@
/**
* \file
*
* \brief SAM Timer/Counter for Control Applications
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*/
#ifndef _HPL_TCC_V101_BASE_H_INCLUDED
#define _HPL_TCC_V101_BASE_H_INCLUDED
#include <hpl_timer.h>
#include <hpl_pwm.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup tcc_group TCC Low Level Driver Helpers
*
* \section tcc_helpers_rev Revision History
* - v0.0.0.1 Initial Commit
*
*@{
*/
/**
* \name HPL functions
*/
//@{
/**
* \brief Retrieve timer helper functions
*
* \return A pointer to set of timer helper functions
*/
struct _timer_hpl_interface *_tcc_get_timer(void);
/**
* \brief Initialize TCC for PWM
*
* This function does low level TCC configuration.
*
* \param[in] device The pointer to PWM device instance
* \param[in] hw The pointer to hardware instance
*
* \return Initialization status.
*/
int32_t _tcc_pwm_init(struct _pwm_device *const device, void *const hw);
/**
* \brief De-initialize TCC for PWM
*
* \param[in] device The pointer to TCC device instance
*/
void _tcc_pwm_deinit(struct _pwm_device *const device);
/**
* \brief Retrieve offset of the given tcc hardware instance
*
* \param[in] device The pointer to TCC device instance
*
* \return The offset of the given tcc hardware instance
*/
uint8_t _tcc_pwm_get_hardware_offset(const struct _pwm_device *const device);
/**
* \brief Start PWM
*
* \param[in] device The pointer to TCC device instance
*/
void _tcc_start_pwm(struct _pwm_device *const device);
/**
* \brief Stop PWM
*
* \param[in] device The pointer to TCC device instance
*/
void _tcc_stop_pwm(struct _pwm_device *const device);
/**
* \brief Check if PWM is running
*
* \param[in] device The pointer to TCC device instance
*
* \return Check status.
* \retval true The given pwm is running
* \retval false The given pwm is not running
*/
bool _tcc_is_pwm_enabled(const struct _pwm_device *const device);
/**
* \brief Set PWM parameter
* \param[in] device The pointer to TCC device instance
* \param[in] period Total period of one PWM cycle.
* \param[in] duty_cycle Period of PWM first half during one cycle.
*/
void _tcc_set_pwm_param(struct _pwm_device *const device, const pwm_period_t period, const pwm_period_t duty_cycle);
/**
* \brief Get pwm waveform period value
* \param[in] device The pointer to TCC device instance
* \return Period value.
*/
pwm_period_t _tcc_pwm_get_period(const struct _pwm_device *const device);
/**
* \brief Get pwm waveform duty cycle value
* \param[in] device The pointer to TCC device instance
* \return Duty cycle value
*/
uint32_t _tcc_pwm_get_duty(const struct _pwm_device *const device);
/**
* \brief Enable/disable PWM interrupt
*
* param[in] device The pointer to PWM device instance
* param[in] type The type of interrupt to disable/enable if applicable
* param[in] disable Enable or disable
*/
void _tcc_pwm_set_irq_state(struct _pwm_device *const device, const enum _pwm_callback_type type, const bool disable);
/**
* \brief Retrieve pwm helper functions
*
* \return A pointer to set of pwm helper functions
*/
struct _pwm_hpl_interface *_tcc_get_pwm(void);
//@}
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* _HPL_TCC_V101_BASE_H_INCLUDED */