xmclib/XMCLib/examples/XMC4800_series/DMA/DMA_PWM/main.c
2024-10-17 17:09:59 +02:00

129 lines
4.5 KiB
C

#include "xmc_gpio.h"
#include "xmc_dma.h"
#include "xmc_ccu4.h"
/* Generate a PWM using the DMA
* Using double buffering, while one buffer is used to update the PWM duty cycle the other buffer one can be updated
* using new values.
*/
uint32_t shadow_transfer_enable;
uint32_t duty_cycles[2][48];
/* DMA linked list */
__attribute__((aligned(32))) XMC_DMA_LLI_t dma_ll[2] =
{
{
.block_size = 48,
.src_addr = (uint32_t)&duty_cycles[0][0],
.dst_addr = (uint32_t)&CCU40_CC40->CRS,
.llp = &dma_ll[1],
.src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32,
.dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32,
.src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_INCREMENT,
.dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE,
.src_burst_length = XMC_DMA_CH_BURST_LENGTH_1,
.dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1,
.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA,
.enable_src_linked_list = true,
.enable_dst_linked_list = true,
},
{
.block_size = 48,
.src_addr = (uint32_t)&duty_cycles[1][0],
.dst_addr = (uint32_t)&CCU40_CC40->CRS,
.llp = &dma_ll[0],
.src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32,
.dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32,
.src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_INCREMENT,
.dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE,
.src_burst_length = XMC_DMA_CH_BURST_LENGTH_1,
.dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1,
.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA,
.enable_src_linked_list = true,
.enable_dst_linked_list = true,
}
};
/* DMA channel used to transfer duty cycles using a linked list to achieve a double buffer */
XMC_DMA_CH_CONFIG_t dma_ch0_config =
{
.block_size = 48,
.linked_list_pointer = (XMC_DMA_LLI_t *)&dma_ll[0],
.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA,
.transfer_type = XMC_DMA_CH_TRANSFER_TYPE_MULTI_BLOCK_SRCADR_LINKED_DSTADR_LINKED,
.src_handshaking = XMC_DMA_CH_SRC_HANDSHAKING_SOFTWARE,
.dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE,
.dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_CCU40_SR0_0,
.priority = XMC_DMA_CH_PRIORITY_0,
};
/* DMA channel used to transfer the shadow transfer request */
XMC_DMA_CH_CONFIG_t dma_ch1_config =
{
.block_size = 48,
.src_addr = (uint32_t)&shadow_transfer_enable,
.dst_addr = (uint32_t)&CCU40->GCSS,
.src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32,
.dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_32,
.src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE,
.dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE,
.src_burst_length = XMC_DMA_CH_BURST_LENGTH_1,
.dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1,
.transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA,
.transfer_type = XMC_DMA_CH_TRANSFER_TYPE_MULTI_BLOCK_SRCADR_RELOAD_DSTADR_RELOAD,
.src_handshaking = XMC_DMA_CH_SRC_HANDSHAKING_SOFTWARE,
.dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE,
.dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_CCU40_SR0_0,
.priority = XMC_DMA_CH_PRIORITY_0
};
XMC_CCU4_SLICE_COMPARE_CONFIG_t ccu4_slice_compare =
{
.prescaler_mode = XMC_CCU4_SLICE_PRESCALER_MODE_NORMAL,
.timer_mode = XMC_CCU4_SLICE_TIMER_COUNT_MODE_EA,
};
int main(void)
{
for (int i = 0; i < 48; ++i)
{
duty_cycles[0][i] = 1365 * i ;
duty_cycles[1][i] = (1365 * 47) - (1365 * i);
}
shadow_transfer_enable = CCU4_GCSS_S0SE_Msk;
XMC_DMA_Init(XMC_DMA0);
XMC_DMA_CH_Init(XMC_DMA0, 0, &dma_ch0_config);
XMC_DMA_CH_Init(XMC_DMA0, 1, &dma_ch1_config);
XMC_CCU4_Init(CCU40, XMC_CCU4_SLICE_MCMS_ACTION_TRANSFER_PR_CR);
XMC_CCU4_EnableClock(CCU40, 0);
XMC_CCU4_StartPrescaler(CCU40);
XMC_CCU4_SLICE_CompareInit(CCU40_CC40, &ccu4_slice_compare);
XMC_CCU4_SLICE_EnableEvent(CCU40_CC40, XMC_CCU4_SLICE_IRQ_ID_COMPARE_MATCH_UP);
XMC_CCU4_SLICE_SetInterruptNode(CCU40_CC40, XMC_CCU4_SLICE_IRQ_ID_COMPARE_MATCH_UP, XMC_CCU4_SLICE_SR_ID_0);
XMC_CCU4_SLICE_SetTimerPeriodMatch(CCU40_CC40, 65535);
XMC_CCU4_SLICE_SetTimerCompareMatch(CCU40_CC40, 65535);
XMC_CCU4_EnableShadowTransfer(CCU40, XMC_CCU4_SHADOW_TRANSFER_SLICE_0);
XMC_GPIO_SetMode(P0_15, XMC_GPIO_MODE_OUTPUT_PUSH_PULL | P0_15_AF_CCU40_OUT0);
XMC_DMA_CH_Enable(XMC_DMA0, 0);
XMC_DMA_CH_Enable(XMC_DMA0, 1);
XMC_CCU4_SLICE_StartTimer(CCU40_CC40);
/* Placeholder for user application code. The while loop below can be replaced with user application code. */
while(1U)
{
}
}