1f69929b0b
This patch adds support for PWM generation using CTIMER on MCXN devices. Each CTIMER provides 4 PWM channels, channels sharing the same CTIMER instance will have the same period settings, and the duty cycle will be maintained if period is changed through one of the four channels. The period channel is automatically assigned and will be transferred to one of the other available channels if that channel is used for PWM generation, no glitches should be expected during the transition. The patch also provides a sample PWM output configuration connected to the on-board green LED which can be enabled through Kconfig. Signed-off-by: Yilin Sun <imi415@imi.moe>
161 lines
3.8 KiB
C
161 lines
3.8 KiB
C
/*
|
|
* Copyright (c) 2006-2024, RT-Thread Development Team
|
|
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Change Logs:
|
|
* Date Author Notes
|
|
* 2024-01-29 yandld first implementation
|
|
*/
|
|
|
|
#include <rthw.h>
|
|
#include <rtthread.h>
|
|
|
|
#include "board.h"
|
|
#include "clock_config.h"
|
|
#include "pin_mux.h"
|
|
#include "drv_uart.h"
|
|
#include "fsl_port.h"
|
|
#include "fsl_cache_lpcac.h"
|
|
|
|
/**
|
|
* This is the timer interrupt service routine.
|
|
*
|
|
*/
|
|
void SysTick_Handler(void)
|
|
{
|
|
/* enter interrupt */
|
|
rt_interrupt_enter();
|
|
|
|
rt_tick_increase();
|
|
|
|
/* leave interrupt */
|
|
rt_interrupt_leave();
|
|
}
|
|
|
|
/**
|
|
* This function will initial board.
|
|
*/
|
|
void rt_hw_board_init()
|
|
{
|
|
/* Hardware Initialization */
|
|
BOARD_InitBootPins();
|
|
L1CACHE_EnableCodeCache();
|
|
|
|
CLOCK_EnableClock(kCLOCK_Freqme);
|
|
CLOCK_EnableClock(kCLOCK_InputMux);
|
|
|
|
CLOCK_EnableClock(kCLOCK_Port0);
|
|
CLOCK_EnableClock(kCLOCK_Port1);
|
|
CLOCK_EnableClock(kCLOCK_Port2);
|
|
CLOCK_EnableClock(kCLOCK_Port3);
|
|
CLOCK_EnableClock(kCLOCK_Port4);
|
|
|
|
CLOCK_EnableClock(kCLOCK_Gpio0);
|
|
CLOCK_EnableClock(kCLOCK_Gpio1);
|
|
CLOCK_EnableClock(kCLOCK_Gpio2);
|
|
CLOCK_EnableClock(kCLOCK_Gpio3);
|
|
CLOCK_EnableClock(kCLOCK_Gpio4);
|
|
|
|
CLOCK_EnableClock(kCLOCK_Pint);
|
|
CLOCK_EnableClock(kCLOCK_Flexcan0);
|
|
CLOCK_EnableClock(kCLOCK_Flexcan1);
|
|
|
|
CLOCK_AttachClk(kFRO_HF_to_ADC0);
|
|
CLOCK_SetClkDiv(kCLOCK_DivAdc0Clk, 1u);
|
|
|
|
/* enable VREF */
|
|
SPC0->ACTIVE_CFG1 |= 0xFFFFFFFF;
|
|
|
|
CLOCK_EnableClock(kCLOCK_Dma0);
|
|
CLOCK_EnableClock(kCLOCK_Dma1);
|
|
|
|
edma_config_t userConfig = {0};
|
|
EDMA_GetDefaultConfig(&userConfig);
|
|
EDMA_Init(DMA0, &userConfig);
|
|
EDMA_Init(DMA1, &userConfig);
|
|
|
|
/* This init has finished in secure side of TF-M */
|
|
BOARD_InitBootClocks();
|
|
|
|
CLOCK_SetupClk16KClocking(kCLOCK_Clk16KToAll);
|
|
|
|
CLOCK_AttachClk(kPLL0_to_CTIMER0);
|
|
CLOCK_AttachClk(kPLL0_to_CTIMER1);
|
|
CLOCK_AttachClk(kPLL0_to_CTIMER2);
|
|
CLOCK_AttachClk(kPLL0_to_CTIMER3);
|
|
CLOCK_AttachClk(kPLL0_to_CTIMER4);
|
|
CLOCK_SetClkDiv(kCLOCK_DivCtimer0Clk, 1u);
|
|
CLOCK_SetClkDiv(kCLOCK_DivCtimer1Clk, 1u);
|
|
CLOCK_SetClkDiv(kCLOCK_DivCtimer2Clk, 1u);
|
|
CLOCK_SetClkDiv(kCLOCK_DivCtimer3Clk, 1u);
|
|
CLOCK_SetClkDiv(kCLOCK_DivCtimer4Clk, 1u);
|
|
|
|
SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
|
|
/* set pend exception priority */
|
|
NVIC_SetPriority(PendSV_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
|
|
|
|
/*init uart device*/
|
|
rt_hw_uart_init();
|
|
|
|
#if defined(BSP_USING_LEDG_PWM) && defined(BSP_USING_PWM)
|
|
PORT_SetPinMux(PORT0, 27, kPORT_MuxAlt4);
|
|
#endif
|
|
|
|
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
|
|
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
|
|
#endif
|
|
|
|
#ifdef RT_USING_COMPONENTS_INIT
|
|
/* initialization board with RT-Thread Components */
|
|
rt_components_board_init();
|
|
#endif
|
|
|
|
#ifdef RT_USING_HEAP
|
|
rt_kprintf("sram heap, begin: 0x%p, end: 0x%p\n", HEAP_BEGIN, HEAP_END);
|
|
rt_system_heap_init((void *)HEAP_BEGIN, (void *)(HEAP_END));
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* This function will called when memory fault.
|
|
*/
|
|
void MemManage_Handler(void)
|
|
{
|
|
extern void HardFault_Handler(void);
|
|
|
|
rt_kprintf("Memory Fault!\n");
|
|
HardFault_Handler();
|
|
}
|
|
|
|
void rt_hw_us_delay(rt_uint32_t us)
|
|
{
|
|
rt_uint32_t ticks;
|
|
rt_uint32_t told, tnow, tcnt = 0;
|
|
rt_uint32_t reload = SysTick->LOAD;
|
|
|
|
ticks = us * reload / (1000000 / RT_TICK_PER_SECOND);
|
|
told = SysTick->VAL;
|
|
while (1)
|
|
{
|
|
tnow = SysTick->VAL;
|
|
if (tnow != told)
|
|
{
|
|
if (tnow < told)
|
|
{
|
|
tcnt += told - tnow;
|
|
}
|
|
else
|
|
{
|
|
tcnt += reload - tnow + told;
|
|
}
|
|
told = tnow;
|
|
if (tcnt >= ticks)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|