129 lines
4.5 KiB
C
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)
|
|
{
|
|
|
|
}
|
|
}
|