[sn32] ct16: further chibios integration (#30)

* [sn32] ct16: further chibios integration

general purpose and pwm driver
also introduce a reset function

* build ct16 driver

* [sn32] have some isr handling

* 240: config the board for pwm

* Revert "240: config the board for pwm"
probably best to do in pwm driver
This reverts commit c09059a8ba60ea1832ea14f4d557bd8e22df3fd7.

* ct: logic fix. remove unecessary include

* ct: typos + use notifications

* ct: the periodic notification should not stop the timer

* ct: pfpa assignment

* ct: pwm:  enable channel only if configured as active

* ct: pwm: periodic tic should track the timer

* derp

* ct: our chip supports IRQ priority level [0-3]

* isr: use the appropriate priority for each device

* ct: pwm: actually handle the channels

* ct: we define the # of channels already so..

* isr: we handle this on the specific drivers
disable for now

* ct: pwm: don't override TC. Call a counter reset

* ct: pwm: Set the prescaler properly

PRE is the max value of PC. PC increments on every tick.
When PC reaches PRE, TC increments and the timer overflows
Periodic timer is software controlled

* ct: gpt: PRE is the interval. Call a counter reset

* ct: Rename reset funtion to be more precise

* ct: pwm: Invert the channel disable logic

* ct: pwm: autoreload on period match

* ct: pwm: we only care for the last 25bits of IC

* ct: gpt: we only care for the last 25bits of IC

* ct: pwm: init config as hw defaults

* ct: pwm: mr24 is the driver callback

* Revert "isr: we handle this on the specific drivers"

This reverts commit 9ca061f170d9523d0e4e42011881f3d0b8dd1599.

* Revert "[sn32] have some isr handling"

This reverts commit cf45020072ea828522f2de2f6d5d2521398a61cd.

* ct: pwm: update the periodic notification

* ct: gpt: use MR0

* ct: priority bump

* Revert "ct: priority bump"
3 is probably fine
This reverts commit d2a861097a43f367ffbd15f6fc5d6747d9f14426.

* sn32: pwm: introduce oneshot mode

enable it with by defining SN32_PWM_USE_ONESHOT TRUE

* pwm: reset: we have a function for that

* explicitly enable pwm channels

* bugfix for bad PWM_OUTPUT_MASK

if it is DISABLED, bad things occur
Only ever identify and use PWM_OUTPUT_ACTIVE_HIGH and PWM_OUTPUT_ACTIVE_LOW

* periodic notification: clear and disable it

* we definitely need this to only run at first init

* ct: pwm: support 23 channel chips

* ct: support 240b and 260 chips

* make the macro check build

* pwm: correctly set the logic level

* pwm: speed improvements
in our shared matrix driver, we only care about the last callback.
having a shortcut to that if no other flag is raised will improve speed

+ident and comment

* Revert "pwm: speed improvements"

This reverts commit e143544b807dd860d26548c803503521450822b8.
This commit is contained in:
dexter93 2021-11-21 23:52:53 +02:00 committed by Dimitris Mantzouranis
parent 68a138c41d
commit 19faddfeb8
10 changed files with 2049 additions and 0 deletions

View File

@ -57,7 +57,22 @@ void CT16B0_Init (void)
//SN_SYS1->APBCP0_b.CT16B0PRE = 0x03; //PCLK = HCLK/8
//SN_SYS1->APBCP0_b.CT16B0PRE = 0x04; //PCLK = HCLK/16
}
/*****************************************************************************
* Function : CT16B0_ResetTimer
* Description : Reset of CT16B0 timer
* Input : None
* Output : None
* Return : None
* Note : None
*****************************************************************************/
void CT16B0_ResetTimer (void)
{
//Set CT16B0 as the up-counting mode.
SN_CT16B0->TMRCTRL = (mskCT16_CRST);
// Wait until timer reset done.
while (SN_CT16B0->TMRCTRL & mskCT16_CRST);
}
/*****************************************************************************
* Function : CT16B0_NvicEnable
* Description : Enable CT16B0 timer interrupt

View File

@ -21,6 +21,7 @@
extern volatile uint32_t iwCT16B0_IrqEvent; //The bitmask usage of iwCT16Bn_IrqEvent is the same with CT16Bn_RIS
extern void CT16B0_Init(void);
extern void CT16B0_ResetTimer(void);
extern void CT16B0_NvicEnable (void);
extern void CT16B0_NvicDisable (void);
#endif /*__SN32F240_CT16B0_H*/

View File

@ -58,6 +58,23 @@ void CT16B1_Init (void)
//SN_SYS1->APBCP1_b.CT16B1PRE = 0x04; //PCLK = HCLK/16
}
/*****************************************************************************
* Function : CT16B1_ResetTimer
* Description : Reset of CT16B1 timer
* Input : None
* Output : None
* Return : None
* Note : None
*****************************************************************************/
void CT16B1_ResetTimer (void)
{
//Set CT16B1 as the up-counting mode.
SN_CT16B1->TMRCTRL = (mskCT16_CRST);
// Wait until timer reset done.
while (SN_CT16B1->TMRCTRL & mskCT16_CRST);
}
/*****************************************************************************
* Function : CT16B1_NvicEnable
* Description : Enable CT16B1 timer interrupt

View File

@ -21,6 +21,7 @@
extern volatile uint32_t iwCT16B1_IrqEvent; //The bitmask usage of iwCT16Bn_IrqEvent is the same with CT16Bn_RIS
extern void CT16B1_Init(void);
extern void CT16B1_ResetTimer(void);
extern void CT16B1_NvicEnable(void);
extern void CT16B1_NvicDisable(void);
extern void CT16B1_IRQHandler(void);

View File

@ -3,9 +3,17 @@ ifneq ($(findstring HAL_USE_CT TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F24xB/CT/CT16B0.c
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F24xB/CT/CT16B1.c
endif
ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F24xB/CT/hal_gpt_lld.c
endif
ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F24xB/CT/hal_pwm_lld.c
endif
else
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F24xB/CT/CT16B0.c
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F24xB/CT/CT16B1.c
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F24xB/CT/hal_gpt_lld.c
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F24xB/CT/hal_pwm_lld.c
endif
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F24xB/CT

View File

@ -0,0 +1,285 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file CT/hal_gpt_lld.c
* @brief SN32 GPT subsystem low level driver source.
*
* @addtogroup GPT
* @{
*/
#include "hal.h"
#if HAL_USE_GPT || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief GPTD1 driver identifier.
* @note The driver GPTD1 allocates the complex timer CT16B0 when enabled.
*/
#if SN32_GPT_USE_CT16B0 || defined(__DOXYGEN__)
GPTDriver GPTD1;
#endif
/**
* @brief GPTD2 driver identifier.
* @note The driver GPTD2 allocates the timer CT16B1 when enabled.
*/
#if SN32_GPT_USE_CT16B1 || defined(__DOXYGEN__)
GPTDriver GPTD2;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if SN32_GPT_USE_CT16B0 || defined(__DOXYGEN__)
#if !defined(SN32_CT16B0_SUPPRESS_ISR)
#if !defined(SN32_CT16B0_HANDLER)
#error "SN32_CT16B0_HANDLER not defined"
#endif
/**
* @brief CT16B0 interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(SN32_CT16B0_HANDLER) {
OSAL_IRQ_PROLOGUE();
gpt_lld_serve_interrupt(&GPTD1);
OSAL_IRQ_EPILOGUE();
}
#endif /* !defined(SN32_CT16B0_SUPPRESS_ISR) */
#endif /* SN32_GPT_USE_CT16B0 */
#if SN32_GPT_USE_CT16B1 || defined(__DOXYGEN__)
#if !defined(SN32_CT16B1_SUPPRESS_ISR)
#if !defined(SN32_CT16B1_HANDLER)
#error "SN32_CT16B1_HANDLER not defined"
#endif
/**
* @brief CT16B1 interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(SN32_CT16B1_HANDLER) {
OSAL_IRQ_PROLOGUE();
gpt_lld_serve_interrupt(&GPTD2);
OSAL_IRQ_EPILOGUE();
}
#endif /* !defined(SN32_CT16B1_SUPPRESS_ISR) */
#endif /* SN32_GPT_USE_CT16B1 */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level GPT driver initialization.
*
* @notapi
*/
void gpt_lld_init(void) {
#if SN32_GPT_USE_CT16B0
/* Driver initialization.*/
GPTD1.ct = SN32_CT16B0;
gptObjectInit(&GPTD1);
#endif
#if SN32_GPT_USE_CT16B1
/* Driver initialization.*/
GPTD2.ct = SN32_CT16B1;
gptObjectInit(&GPTD2);
#endif
}
/**
* @brief Configures and activates the GPT peripheral.
*
* @param[in] gptp pointer to the @p GPTDriver object
*
* @notapi
*/
void gpt_lld_start(GPTDriver *gptp) {
uint16_t psc;
if (gptp->state == GPT_STOP) {
/* Clock activation.*/
#if SN32_GPT_USE_CT16B0
if (&GPTD1 == gptp) {
CT16B0_Init();
CT16B0_ResetTimer();
#if !defined(SN32_CT16B0_SUPPRESS_ISR)
nvicEnableVector(SN32_CT16B0_NUMBER, SN32_GPT_CT16B0_IRQ_PRIORITY);
#endif
gptp->clock = SystemCoreClock;
}
#endif
#if SN32_GPT_USE_CT16B1
if (&GPTD2 == gptp) {
CT16B1_Init();
CT16B1_ResetTimer();
#if !defined(SN32_CT16B1_SUPPRESS_ISR)
nvicEnableVector(SN32_CT16B1_NUMBER, SN32_GPT_CT16B1_IRQ_PRIORITY);
#endif
gptp->clock = SystemCoreClock;
}
#endif
}
/* Prescaler value calculation.*/
psc = (uint8_t)((gptp->clock / gptp->config->frequency) - 1);
osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock,
"invalid frequency");
/* Timer configuration.*/
gptp->ct->TMRCTRL = CT16_CEN_DIS; /* Initially stopped. */
gptp->ct->CNTCTRL = gptp->config->cntctrl;
gptp->ct->PRE = psc; /* Prescaler value. */
gptp->ct->IC &= 0x1FFFFFF; /* Clear pending IRQs. */
}
/**
* @brief Deactivates the GPT peripheral.
*
* @param[in] gptp pointer to the @p GPTDriver object
*
* @notapi
*/
void gpt_lld_stop(GPTDriver *gptp) {
if (gptp->state == GPT_READY) {
gptp->ct->TMRCTRL = CT16_CEN_DIS; /* Timer disabled. */
gptp->ct->IC &= 0x1FFFFFF; /* Clear pending IRQs. */
#if SN32_GPT_USE_CT16B0
if (&GPTD1 == gptp) {
#if !defined(SN32_CT16B0_SUPPRESS_ISR)
nvicDisableVector(SN32_CT16B0_NUMBER);
#endif
SN_SYS1->AHBCLKEN_b.CT16B0CLKEN = DISABLE;
}
#endif
#if SN32_GPT_USE_CT16B1
if (&GPTD2 == gptp) {
#if !defined(SN32_CT16B1_SUPPRESS_ISR)
nvicDisableVector(SN32_CT16B1_NUMBER);
#endif
SN_SYS1->AHBCLKEN_b.CT16B1CLKEN = DISABLE;
}
#endif
}
}
/**
* @brief Starts the timer in continuous mode.
*
* @param[in] gptp pointer to the @p GPTDriver object
* @param[in] interval period in ticks
*
* @notapi
*/
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) {
gptp->ct->MR0 = (uint32_t)(interval - 1U); /* Time constant. */
gptp->ct->TMRCTRL = mskCT16_CRST; /* Reset counter. */
gptp->ct->IC &= 0x1FFFFFF; /* Clear pending IRQs. */
if (NULL != gptp->config->callback)
gptp->ct->MCTRL |= mskCT16_MR0IE_EN;
gptp->ct->TMRCTRL |= mskCT16_CEN_EN;
}
/**
* @brief Stops the timer.
*
* @param[in] gptp pointer to the @p GPTDriver object
*
* @notapi
*/
void gpt_lld_stop_timer(GPTDriver *gptp) {
gptp->ct->TMRCTRL = CT16_CEN_DIS; /* Initially stopped. */
gptp->ct->IC &= 0x1FFFFFF; /* Clear pending IRQs. */
gptp->ct->MCTRL &= ~mskCT16_MR0IE_EN; /* Disable the interrupt */
}
/**
* @brief Starts the timer in one shot mode and waits for completion.
* @details This function specifically polls the timer waiting for completion
* in order to not have extra delays caused by interrupt servicing,
* this function is only recommended for short delays.
*
* @param[in] gptp pointer to the @p GPTDriver object
* @param[in] interval time interval in ticks
*
* @notapi
*/
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) {
gptp->ct->MR0 = (uint32_t)(interval - 1U); /* Time constant. */
gptp->ct->IC &= 0x1FFFFFF; /* Clear pending IRQs. */
gptp->ct->MCTRL = (mskCT16_MR0IE_EN | mskCT16_MR0STOP_EN);
gptp->ct->TMRCTRL |= mskCT16_CEN_EN;
while (!(gptp->ct->RIS & mskCT16_MR0IF))
;
gptp->ct->IC &= 0x1FFFFFF; /* Clear pending IRQs. */
}
/**
* @brief Shared IRQ handler.
*
* @param[in] gptp pointer to a @p GPTDriver object
*
* @notapi
*/
void gpt_lld_serve_interrupt(GPTDriver *gptp) {
gptp->ct->IC &= 0x1FFFFFF;
if (gptp->state == GPT_ONESHOT) {
gptp->state = GPT_READY; /* Back in GPT_READY state. */
gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */
}
gptp->config->callback(gptp);
}
#endif /* HAL_USE_GPT */
/** @} */

View File

@ -0,0 +1,269 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file CT/hal_gpt_lld.h
* @brief SN32 GPT subsystem low level driver header.
*
* @addtogroup GPT
* @{
*/
#ifndef HAL_GPT_LLD_H
#define HAL_GPT_LLD_H
#include "sn32_ct.h"
#if HAL_USE_GPT || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief GPTD1 driver enable switch.
* @details If set to @p TRUE the support for GPTD1 is included.
* @note The default is @p TRUE.
*/
#if !defined(SN32_GPT_USE_CT16B0) || defined(__DOXYGEN__)
#define SN32_GPT_USE_CT16B0 FALSE
#endif
/**
* @brief GPTD2 driver enable switch.
* @details If set to @p TRUE the support for GPTD2 is included.
* @note The default is @p TRUE.
*/
#if !defined(SN32_GPT_USE_CT16B1) || defined(__DOXYGEN__)
#define SN32_GPT_USE_CT16B1 FALSE
#endif
/**
* @brief GPTD1 interrupt priority level setting.
*/
#if !defined(SN32_GPT_CT16B0_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define SN32_GPT_CT16B0_IRQ_PRIORITY 3
#endif
/**
* @brief GPTD2 interrupt priority level setting.
*/
#if !defined(SN32_GPT_CT16B1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define SN32_GPT_CT16B1_IRQ_PRIORITY 3
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if !defined(SN32_HAS_CT16B0)
#define SN32_HAS_CT16B0 FALSE
#endif
#if !defined(SN32_HAS_CT16B1)
#define SN32_HAS_CT16B1 FALSE
#endif
#if SN32_GPT_USE_CT16B0 && !SN32_HAS_CT16B0
#error "CT16B0 not present in the selected device"
#endif
#if SN32_GPT_USE_CT16B1 && !SN32_HAS_CT16B1
#error "CT16B1 not present in the selected device"
#endif
#if !SN32_GPT_USE_CT16B0 && !SN32_GPT_USE_CT16B0 && \
!SN32_GPT_USE_CT16B1 && !SN32_GPT_USE_CT16B1
#error "GPT driver activated but no CT16 peripheral assigned"
#endif
/* Checks on allocation of CT16Bx units.*/
#if SN32_GPT_USE_CT16B0
#if defined(SN32_CT16B0_IS_USED)
#error "GPTD1 requires CT16B0 but the timer is already used"
#else
#define SN32_CT16B0_IS_USED
#endif
#endif
#if SN32_GPT_USE_CT16B1
#if defined(SN32_CT16B1_IS_USED)
#error "GPTD2 requires CT16B1 but the timer is already used"
#else
#define SN32_CT16B1_IS_USED
#endif
#endif
/* IRQ priority checks.*/
#if SN32_GPT_USE_CT16B0 && !defined(SN32_CT16B0_SUPPRESS_ISR) && \
!OSAL_IRQ_IS_VALID_PRIORITY(SN32_GPT_CT16B0_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to CT16B0"
#endif
#if SN32_GPT_USE_CT16B1 && !defined(SN32_CT16B1_SUPPRESS_ISR) && \
!OSAL_IRQ_IS_VALID_PRIORITY(SN32_GPT_CT16B1_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to CT16B1"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief GPT frequency type.
*/
typedef uint32_t gptfreq_t;
/**
* @brief GPT counter type.
*/
typedef uint16_t gptcnt_t;
/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
typedef struct {
/**
* @brief Timer clock in Hz.
* @note The low level can use assertions in order to catch invalid
* frequency specifications.
*/
gptfreq_t frequency;
/**
* @brief Timer callback pointer.
* @note This callback is invoked on GPT counter events.
* @note This callback can be set to @p NULL but in that case the
* one-shot mode cannot be used.
*/
gptcallback_t callback;
/* End of the mandatory fields.*/
/**
* @brief CT16 CNTCTRL register initialization data.
* @note The value of this field should normally be equal to zero.
*/
uint32_t cntctrl;
} GPTConfig;
/**
* @brief Structure representing a GPT driver.
*/
struct GPTDriver {
/**
* @brief Driver state.
*/
gptstate_t state;
/**
* @brief Current configuration data.
*/
const GPTConfig *config;
#if defined(GPT_DRIVER_EXT_FIELDS)
GPT_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
/**
* @brief Timer base clock.
*/
uint32_t clock;
/**
* @brief Pointer to the CT registers block.
*/
sn32_ct_t *ct;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Changes the interval of GPT peripheral.
* @details This function changes the interval of a running GPT unit.
* @pre The GPT unit must be running in continuous mode.
* @post The GPT unit interval is changed to the new value.
* @note The function has effect at the next cycle start.
*
* @param[in] gptp pointer to a @p GPTDriver object
* @param[in] interval new cycle time in timer ticks
*
* @notapi
*/
#define gpt_lld_change_interval(gptp, interval) \
((gptp)->ct->MR0 = (uint32_t)((interval) - 1U))
/**
* @brief Returns the interval of GPT peripheral.
* @pre The GPT unit must be running in continuous mode.
*
* @param[in] gptp pointer to a @p GPTDriver object
* @return The current interval.
*
* @notapi
*/
#define gpt_lld_get_interval(gptp) ((gptcnt_t)((gptp)->ct->MR0 + 1U))
/**
* @brief Returns the counter value of GPT peripheral.
* @pre The GPT unit must be running in continuous mode.
* @note The nature of the counter is not defined, it may count upward
* or downward, it could be continuously running or not.
*
* @param[in] gptp pointer to a @p GPTDriver object
* @return The current counter value.
*
* @notapi
*/
#define gpt_lld_get_counter(gptp) ((gptcnt_t)(gptp)->ct->TC)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if SN32_GPT_USE_CT16B0 && !defined(__DOXYGEN__)
extern GPTDriver GPTD1;
#endif
#if SN32_GPT_USE_CT16B1 && !defined(__DOXYGEN__)
extern GPTDriver GPTD2;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void gpt_lld_init(void);
void gpt_lld_start(GPTDriver *gptp);
void gpt_lld_stop(GPTDriver *gptp);
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period);
void gpt_lld_stop_timer(GPTDriver *gptp);
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval);
void gpt_lld_serve_interrupt(GPTDriver *gptp);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_GPT */
#endif /* HAL_GPT_LLD_H */
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,277 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file CT/hal_pwm_lld.h
* @brief SN32 PWM subsystem low level driver header.
*
* @addtogroup PWM
* @{
*/
#ifndef HAL_PWM_LLD_H
#define HAL_PWM_LLD_H
#if HAL_USE_PWM || defined(__DOXYGEN__)
#include "sn32_ct.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Number of PWM channels per PWM driver.
*/
#define PWM_CHANNELS SN32_CT16B1_CHANNELS
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief PWMD1 driver enable switch.
* @details If set to @p TRUE the support for PWMD1 is included.
* @note The default is @p TRUE.
*/
#if !defined(SN32_PWM_USE_CT16B1) || defined(__DOXYGEN__)
#define SN32_PWM_USE_CT16B1 FALSE
#endif
/**
* @brief PWMD1 interrupt priority level setting.
*/
#if !defined(SN32_PWM_CT16B1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define SN32_PWM_CT16B1_IRQ_PRIORITY 3
#endif
/** @} */
/*===========================================================================*/
/* Configuration checks. */
/*===========================================================================*/
#if !defined(SN32_HAS_CT16B1)
#define SN32_HAS_CT16B1 FALSE
#endif
#if SN32_PWM_USE_CT16B1 && !SN32_HAS_CT16B1
#error "CT16B1 not present in the selected device"
#endif
#if !SN32_PWM_USE_CT16B1
#error "PWM driver activated but no CT peripheral assigned"
#endif
/* Checks on allocation of CT units.*/
#if SN32_PWM_USE_CT16B1
#if defined(SN32_CT16B1_IS_USED)
#error "PWMD1 requires CT16B1 but the timer is already used"
#else
#define SN32_CT16B1_IS_USED
#endif
#endif
/* IRQ priority checks.*/
#if SN32_PWM_USE_CT16B1 && !defined(SN32_CT16B1_SUPPRESS_ISR) && \
!OSAL_IRQ_IS_VALID_PRIORITY(SN32_PWM_CT16B1_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to CT16B1"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Type of a PWM mode.
*/
typedef uint32_t pwmmode_t;
/**
* @brief Type of a PWM channel.
*/
typedef uint8_t pwmchannel_t;
/**
* @brief Type of a channels mask.
*/
typedef uint32_t pwmchnmsk_t;
/**
* @brief Type of a PWM counter.
*/
typedef uint32_t pwmcnt_t;
/**
* @brief Type of a PWM driver channel configuration structure.
*/
typedef struct {
/**
* @brief Channel active logic level.
*/
pwmmode_t mode;
/**
* @brief Channel callback pointer.
* @note This callback is invoked on the channel compare event. If set to
* @p NULL then the callback is disabled.
*/
pwmcallback_t callback;
/* End of the mandatory fields.*/
/**
* @brief CT16 PFPA register initialization data.
* @note The value of this field should normally be equal to zero.
*/
uint8_t pfpamsk;
} PWMChannelConfig;
/**
* @brief Type of a PWM driver configuration structure.
*/
typedef struct {
/**
* @brief Timer clock in Hz.
* @note The low level can use assertions in order to catch invalid
* frequency specifications.
*/
uint32_t frequency;
/**
* @brief PWM period in ticks.
* @note The low level can use assertions in order to catch invalid
* period specifications.
*/
pwmcnt_t period;
/**
* @brief Periodic callback pointer.
* @note This callback is invoked on PWM counter reset. If set to
* @p NULL then the callback is disabled.
*/
pwmcallback_t callback;
/**
* @brief Channels configurations.
*/
PWMChannelConfig channels[PWM_CHANNELS];
/* End of the mandatory fields.*/
/**
* @brief CT16 CNTCTRL register initialization data.
* @note The value of this field should normally be equal to zero.
*/
uint32_t cntctrl;
} PWMConfig;
/**
* @brief Structure representing a PWM driver.
*/
struct PWMDriver {
/**
* @brief Driver state.
*/
pwmstate_t state;
/**
* @brief Current driver configuration data.
*/
const PWMConfig *config;
/**
* @brief Current PWM period in ticks.
*/
pwmcnt_t period;
/**
* @brief Mask of the enabled channels.
*/
pwmchnmsk_t enabled;
/**
* @brief Number of channels in this instance.
*/
pwmchannel_t channels;
#if defined(PWM_DRIVER_EXT_FIELDS)
PWM_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
/**
* @brief Timer base clock.
*/
uint32_t clock;
/**
* @brief Pointer to the CT registers block.
*/
sn32_ct_t *ct;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Changes the period the PWM peripheral.
* @details This function changes the period of a PWM unit that has already
* been activated using @p pwmStart().
* @pre The PWM unit must have been activated using @p pwmStart().
* @post The PWM unit period is changed to the new value.
* @note The function has effect at the next cycle start.
* @note If a period is specified that is shorter than the pulse width
* programmed in one of the channels then the behavior is not
* guaranteed.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] period new cycle time in ticks
*
* @notapi
*/
#if PWM_CHANNELS > 23
#define pwm_lld_change_period(pwmp, period) \
((pwmp)->ct->MR24 = ((period) - 1))
#else
#define pwm_lld_change_period(pwmp, period) \
((pwmp)->ct->MR23 = ((period) - 1))
#endif
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if SN32_PWM_USE_CT16B1 && !defined(__DOXYGEN__)
extern PWMDriver PWMD1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void pwm_lld_init(void);
void pwm_lld_start(PWMDriver *pwmp);
void pwm_lld_stop(PWMDriver *pwmp);
void pwm_lld_enable_channel(PWMDriver *pwmp,
pwmchannel_t channel,
pwmcnt_t width);
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel);
void pwm_lld_enable_periodic_notification(PWMDriver *pwmp);
void pwm_lld_disable_periodic_notification(PWMDriver *pwmp);
void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel);
void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel);
void pwm_lld_serve_interrupt(PWMDriver *pwmp);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_PWM */
#endif /* HAL_PWM_LLD_H */
/** @} */

View File

@ -0,0 +1,121 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file CT/sn32_ct.h
* @brief SN32 CT units common header.
* @note This file requires definitions from the SN32 header file.
*
* @{
*/
#ifndef SN32_CT_H
#define SN32_CT_H
#include "CT16.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @name CT units references
* @{
*/
#define SN32_CT16B0 ((sn32_ct_t *)SN_CT16B0_BASE)
#define SN32_CT16B1 ((sn32_ct_t *)SN_CT16B1_BASE)
#if defined(SN32F240B)
#define SN32_CT16B1_CHANNELS 24
#elif defined(SN32F260)
#define SN32_CT16B1_CHANNELS 23
#else
#error "CT not supported in the selected device"
#endif
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief SN32 CT registers block.
* @note This is the most general known form, not all timers have
* necessarily all registers and bits.
*/
typedef struct { /*!< (@ 0x40002000) SN_CT16Bn Structure */
volatile uint32_t TMRCTRL; /*!< (@ 0x00000000) Offset:0x00 CT16Bn Timer Control Register */
volatile uint32_t TC; /*!< (@ 0x00000004) Offset:0x04 CT16Bn Timer Counter Register */
volatile uint32_t PRE; /*!< (@ 0x00000008) Offset:0x08 CT16Bn Prescale Register */
volatile uint32_t PC; /*!< (@ 0x0000000C) Offset:0x0C CT16Bn Prescale Counter Register */
volatile uint32_t CNTCTRL; /*!< (@ 0x00000010) Offset:0x10 CT16Bn Counter Control Register */
volatile uint32_t MCTRL; /*!< (@ 0x00000014) Offset:0x14 CT16Bn Match Control Register */
volatile uint32_t MCTRL2; /*!< (@ 0x00000018) Offset:0x18 CT16Bn Match Control Register 2 */
volatile uint32_t MCTRL3; /*!< (@ 0x0000001C) Offset:0x1C CT16Bn Match Control Register 3 */
volatile uint32_t MR0; /*!< (@ 0x00000020) Offset:0x20 CT16Bn MR0 Register */
volatile uint32_t MR1; /*!< (@ 0x00000024) Offset:0x24 CT16Bn MR1 Register */
volatile uint32_t MR2; /*!< (@ 0x00000028) Offset:0x28 CT16Bn MR2 Register */
volatile uint32_t MR3; /*!< (@ 0x0000002C) Offset:0x2C CT16Bn MR3 Register */
volatile uint32_t MR4; /*!< (@ 0x00000030) Offset:0x30 CT16Bn MR4 Register */
volatile uint32_t MR5; /*!< (@ 0x00000034) Offset:0x34 CT16Bn MR5 Register */
volatile uint32_t MR6; /*!< (@ 0x00000038) Offset:0x38 CT16Bn MR6 Register */
volatile uint32_t MR7; /*!< (@ 0x0000003C) Offset:0x3C CT16Bn MR7 Register */
volatile uint32_t MR8; /*!< (@ 0x00000040) Offset:0x40 CT16Bn MR8 Register */
volatile uint32_t MR9; /*!< (@ 0x00000044) Offset:0x44 CT16Bn MR9 Register */
volatile uint32_t MR10; /*!< (@ 0x00000048) Offset:0x48 CT16Bn MR10 Register */
volatile uint32_t MR11; /*!< (@ 0x0000004C) Offset:0x4C CT16Bn MR11 Register */
volatile uint32_t MR12; /*!< (@ 0x00000050) Offset:0x50 CT16Bn MR12 Register */
volatile uint32_t MR13; /*!< (@ 0x00000054) Offset:0x54 CT16Bn MR13 Register */
volatile uint32_t MR14; /*!< (@ 0x00000058) Offset:0x58 CT16Bn MR14 Register */
volatile uint32_t MR15; /*!< (@ 0x0000005C) Offset:0x5C CT16Bn MR15 Register */
volatile uint32_t MR16; /*!< (@ 0x00000060) Offset:0x60 CT16Bn MR16 Register */
volatile uint32_t MR17; /*!< (@ 0x00000064) Offset:0x64 CT16Bn MR17 Register */
volatile uint32_t MR18; /*!< (@ 0x00000068) Offset:0x68 CT16Bn MR18 Register */
volatile uint32_t MR19; /*!< (@ 0x0000006C) Offset:0x6C CT16Bn MR19 Register */
volatile uint32_t MR20; /*!< (@ 0x00000070) Offset:0x70 CT16Bn MR20 Register */
volatile uint32_t MR21; /*!< (@ 0x00000074) Offset:0x74 CT16Bn MR21 Register */
volatile uint32_t MR22; /*!< (@ 0x00000078) Offset:0x78 CT16Bn MR22 Register */
volatile uint32_t MR23; /*!< (@ 0x0000007C) Offset:0x7C CT16Bn MR23 Register */
volatile uint32_t MR24; /*!< (@ 0x00000080) Offset:0x80 CT16Bn MR24 Register */
volatile uint32_t CAP0; /*!< (@ 0x00000084) Offset:0x84 CT16Bn CAP0 Register */
volatile uint32_t EM; /*!< (@ 0x00000088) Offset:0x88 CT16Bn External Match Register */
volatile uint32_t EMC; /*!< (@ 0x0000008C) Offset:0x8C CT16Bn External Match Control register */
volatile uint32_t EMC2; /*!< (@ 0x00000090) Offset:0x90 CT16Bn External Match Control register 2 */
volatile uint32_t PWMCTRL; /*!< (@ 0x00000094) Offset:0x94 CT16Bn PWM Control Register */
volatile uint32_t PWMCTRL2; /*!< (@ 0x00000098) Offset:0x98 CT16Bn PWM Control Register 2 */
volatile uint32_t PWMENB; /*!< (@ 0x0000009C) Offset:0x9C CT16Bn PWM Enable register */
volatile uint32_t PWMIOENB; /*!< (@ 0x000000A0) Offset:0xA0 CT16Bn PWM IO Enable register */
volatile uint32_t RIS; /*!< (@ 0x000000A4) Offset:0xA4 CT16Bn Raw Interrupt Status Register */
volatile uint32_t IC; /*!< (@ 0x000000A8) Offset:0xA8 CT16Bn Interrupt Clear Register */
} sn32_ct_t; /*!< Size = 172 (0xac) */
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#endif /* SN32_CT_H */
/** @} */