Added some PWM API (WIP).
Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
parent
5c3e2a0640
commit
e024eb97d4
|
@ -1 +1 @@
|
|||
Subproject commit 7b84e47e26ce6d180057b5c303ba21ac9e92ee9a
|
||||
Subproject commit 850ed007ae5f457ff97989813452e75fce33f833
|
|
@ -16,15 +16,16 @@
|
|||
* LPC55S69 has 5 CTimers, each with 4 Match channels, each channel can route up to 2 pins
|
||||
* Total: 40 PWM capable pins (at most)
|
||||
* Actual: 30 pins (shared).
|
||||
* Match channel 3 is special, normally it will be used as period channel, until
|
||||
* initialized explicitly.
|
||||
* The match channel will be switched to channel 2 if 3 is initialized, or to 1 if channel 2 is initialized
|
||||
* eventually to 0. If all channels are occupied, then channel 3 can not be initialized.
|
||||
* Match channel 3 is special, normally it will be used as period channel
|
||||
* TODO: Find a way to utilize channel 3 as normal PWM outputs
|
||||
*/
|
||||
|
||||
#define PWM_IMPL_INST_COUNT 5
|
||||
#define PWM_IMPL_INST_CH 4
|
||||
|
||||
/* FIXME: A reasonable clock for PWM resolution, could be determined dynamically. */
|
||||
#define PWM_IMPL_REASONABLE_CLK (10000000UL)
|
||||
|
||||
/* Timer channel ID fields */
|
||||
|
||||
#define PWM_IMPL_CT_OFFSET_Pos 0
|
||||
|
@ -68,25 +69,25 @@ static const uint32_t s_pwm_channel_map[PWM_IMPL_INST_COUNT][PWM_IMPL_INST_COUNT
|
|||
PWM_IMPL_PIN(0, 0, 3), PWM_IMPL_PIN(0, 30, 3), // CT0MAT0, Channel ID: 0, 1
|
||||
PWM_IMPL_PIN(0, 3, 2), PWM_IMPL_PIN(0, 31, 3), // CT0MAT1, Channel ID: 2, 3
|
||||
PWM_IMPL_PIN(0, 19, 3), PWM_IMPL_PIN(1, 31, 3), // CT0MAT2, Channel ID: 4, 5
|
||||
PWM_IMPL_PIN(1, 2, 3), PWM_IMPL_PIN(1, 27, 3), // CT0MAT3, Channel ID: 6, 7
|
||||
0x00000000UL, 0x00000000UL, // CT0MAT3, Channel ID: 6, 7
|
||||
},
|
||||
{
|
||||
PWM_IMPL_PIN(0, 18, 3), PWM_IMPL_PIN(1, 10, 3), // CT1MAT0, Channel ID: 8, 9
|
||||
PWM_IMPL_PIN(0, 20, 2), PWM_IMPL_PIN(1, 12, 3), // CT1MAT1, Channel ID: 10, 11
|
||||
PWM_IMPL_PIN(0, 23, 2), PWM_IMPL_PIN(1, 14, 3), // CT1MAT2, Channel ID: 12, 13
|
||||
PWM_IMPL_PIN(1, 16, 3), 0x00000000UL, // CT1MAT3, Channel ID: 14, 15
|
||||
0x00000000UL, 0x00000000UL, // CT1MAT3, Channel ID: 14, 15
|
||||
},
|
||||
{
|
||||
PWM_IMPL_PIN(0, 10, 3), PWM_IMPL_PIN(1, 5, 3), // CT2MAT0, Channel ID: 16, 17
|
||||
PWM_IMPL_PIN(1, 4, 3), PWM_IMPL_PIN(1, 6, 3), // CT2MAT1, Channel ID: 18, 19
|
||||
PWM_IMPL_PIN(0, 11, 2), PWM_IMPL_PIN(1, 7, 3), // CT2MAT2, Channel ID: 20, 21
|
||||
PWM_IMPL_PIN(0, 29, 3), PWM_IMPL_PIN(1, 22, 3), // CT2MAT3, Channel ID: 22, 23
|
||||
PWM_IMPL_PIN(0, 10, 3), PWM_IMPL_PIN(1, 5, 3), // CT2MAT0, Channel ID: 16, 17
|
||||
PWM_IMPL_PIN(1, 4, 3), PWM_IMPL_PIN(1, 6, 3), // CT2MAT1, Channel ID: 18, 19
|
||||
PWM_IMPL_PIN(0, 11, 2), PWM_IMPL_PIN(1, 7, 3), // CT2MAT2, Channel ID: 20, 21
|
||||
0x00000000UL, 0x00000000UL, // CT2MAT3, Channel ID: 22, 23
|
||||
},
|
||||
{
|
||||
PWM_IMPL_PIN(0, 5, 3), 0x00000000UL, // CT3MAT0, Channel ID: 24, 25
|
||||
PWM_IMPL_PIN(1, 19, 3), 0x00000000UL, // CT3MAT1, Channel ID: 26, 27
|
||||
PWM_IMPL_PIN(0, 27, 3), PWM_IMPL_PIN(1, 21, 3), // CT3MAT2, Channel ID: 28, 29
|
||||
PWM_IMPL_PIN(1, 22, 3), PWM_IMPL_PIN(1, 27, 3), // CT3MAT3, Channel ID: 30, 31
|
||||
0x00000000UL, 0x00000000UL, // CT3MAT3, Channel ID: 30, 31
|
||||
},
|
||||
{
|
||||
PWM_IMPL_PIN(0, 6, 3), 0x00000000UL, // CT4MAT0, Channel ID: 32, 33
|
||||
|
@ -96,11 +97,11 @@ static const uint32_t s_pwm_channel_map[PWM_IMPL_INST_COUNT][PWM_IMPL_INST_COUNT
|
|||
},
|
||||
};
|
||||
|
||||
static const clock_attach_id_t s_pwm_clk_attach_list[] = {
|
||||
static clock_attach_id_t const s_pwm_clk_attach_list[] = {
|
||||
kMAIN_CLK_to_CTIMER0, kMAIN_CLK_to_CTIMER1, kMAIN_CLK_to_CTIMER2, kMAIN_CLK_to_CTIMER3, kMAIN_CLK_to_CTIMER4,
|
||||
};
|
||||
|
||||
static const CTIMER_Type *s_pwm_ct_list[] = {
|
||||
static CTIMER_Type * const s_pwm_ct_list[] = {
|
||||
CTIMER0, CTIMER1, CTIMER2, CTIMER3, CTIMER4,
|
||||
};
|
||||
|
||||
|
@ -120,17 +121,23 @@ static bool mrb_machine_pwm_ctimer_in_use(uint8_t ctimer_id) {
|
|||
}
|
||||
|
||||
/* Check if this CTIMER is enabled */
|
||||
if((ct_inst->TCR & CTIMER_TCR_CEN_MASK) == 0) {
|
||||
if ((ct_inst->TCR & CTIMER_TCR_CEN_MASK) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check if any MATCH channels are configured as reset.
|
||||
* For a typical PWM setup, a channel needs at least 1 MATCH channel set as reset */
|
||||
if((ct_inst->MCR & (CTIMER_MCR_MR0R_MASK | CTIMER_MCR_MR1R_MASK | CTIMER_MCR_MR2R_MASK | CTIMER_MCR_MR3R_MASK)) == 0) {
|
||||
/* Check if Match channel 3 is configured as reset. */
|
||||
/* TODO: Find a way to utilize channel 3 as normal PWM outputs */
|
||||
if ((ct_inst->MCR & CTIMER_MCR_MR3R_MASK) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Check if any PWM outputs are enabled */
|
||||
/* TODO: Find a way to utilize channel 3 as normal PWM outputs */
|
||||
if ((ct_inst->PWMC & (CTIMER_PWMC_PWMEN0_MASK | CTIMER_PWMC_PWMEN1_MASK | CTIMER_PWMC_PWMEN2_MASK)) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int mrb_machine_pwm_impl_init(uint32_t channel, machine_pwm_config_t *config) {
|
||||
|
@ -150,8 +157,19 @@ int mrb_machine_pwm_impl_init(uint32_t channel, machine_pwm_config_t *config) {
|
|||
return -2;
|
||||
}
|
||||
|
||||
/* FIXME: Check CTIMER status and match channel status before setting pin mode */
|
||||
/* TODO: Set up CTIMER if not configured previously */
|
||||
if(!mrb_machine_pwm_ctimer_in_use(ctimer_id)) {
|
||||
/* CTimer is not in use, initialize timer */
|
||||
|
||||
CLOCK_AttachClk(s_pwm_clk_attach_list[ctimer_id]);
|
||||
|
||||
ctimer_config_t ct_cfg;
|
||||
CTIMER_GetDefaultConfig(&ct_cfg);
|
||||
|
||||
ct_cfg.prescale = CLOCK_GetCTimerClkFreq(ctimer_id) / PWM_IMPL_REASONABLE_CLK;
|
||||
|
||||
CTIMER_Init(s_pwm_ct_list[ctimer_id], &ct_cfg);
|
||||
}
|
||||
|
||||
/* FIXME: How to determine whether CTIMER is set up previously? Tips: CTIMER might be used by other gems... */
|
||||
|
||||
/* Function is retrieved from const array. */
|
||||
|
|
Loading…
Reference in New Issue