Hi,
I'm setting up my project using PE. I have a UART, DMA controller, 2 DMA channels, etc... I can transmit data using DMA and receive it. However I haven't found a decent way of transmitting a variable amount of bytes. Say my DMA TX buffer is 512 bytes, and I want to send a 20 byte packet, I need to change the request count size, which is easy to do using: UART_TX_DMA_SetRequestCount(). However I also want to change the "after transfer complete source address adjustment" to go back to the beginning of my buffer.
I could do this manually, IE. disable this option in PE, and when I receive my dma complete event, change the source address using UART_TX_DMA_SetSourceAddress(). Or I can change the address adjust manually using register writes: DMA_TCD4_SLAST = DMA_SLAST_SLAST(0-size); (note this may be the wrong code to use, I can't test it until Monday). However this makes the assumption that I'm using DMA Channel 4 for this. Which is fine until I change that and forget to change this line of code.
I would like to be able to do one of:
1) UART_TX_DMA_SetAfterTransferSourceAddressAdjust(..., 0-size);
2) DMA_SLAST_REG(DMA_BASE_PTR, UART_TX_DMA_CHANNEL_NUM) = DMA_SLAST_SLAST(0-size); // Note the CHANNEL_NUM define doesn't exist like this. I could try and get access to the DMAController_TChnInit struct and get the logical channel number, and from the physical channel number, but that's quite messy, and that data is largely defined in .c files Including the DMAController_TDevConst struct, which would make it a bit nasty to get the info.
Am I missing something? Or is PE missing this feature?
Using KDS 1.1.0, PE 1.1.0.RT6_b1428-0121, windows 7.
Thanks,
Andy
Solved! Go to Solution.
Hi Andy,
try this:
void UART_TX_DMA_SetAfterTransferSourceAddressAdjust(LDD_TDeviceData *DeviceDataPtr, int32_t AddressAdjustment)
{
(*((DMA1_TTCD **)DeviceDataPtr))->DMA_TCD_SLAST_Reg = (uint32_t)AddressAdjustment;
}
int main(void) {
LDD_TDeviceData* hDmaChannel;
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. ***/
hDmaChannel = UART_TX_DMA_Init(NULL);
UART_TX_DMA_SetSourceAddress(hDmaChannel, (LDD_DMA_TData *)0x12345678);
UART_TX_DMA_SetAfterTransferSourceAddressAdjust(hDmaChannel, -2);
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/
Note: hDmaChannel returned by UART_TX_DMA_Init() method is pointer to DMA1_TChnDevData structure:
/* Channel device data structure prototype */
typedef struct DMA1_TChnDevData_stuct {
DMA1_TTCD *TCDPtr; /*!< Channel TCD address */
DMA1_TChnDevConst const *ChnDevConstPtr; /*!< Channel device constants structure address */
LDD_DMA_TErrorFlags ErrorFlags; /*!< Channel error flags */
LDD_TUserData *UserDataPtr; /*!< User data pointer */
DMA1_TEvents Events; /*!< Events state variable */
} DMA1_TChnDevData, *DMA1_TChnDevDataPtr;
As you can see the first item in the TChnDevData structure is:
DMA1_TTCD *TCDPtr; /*!< Channel TCD address */
This TCDPtr pointer is initialized in the UART_TX_DMA_Init() method to the TCD address of the selected DMA channel (=address of real HW registers for this DMA channel).
Best Regards
Marek Varecha
Hi Andy,
try this:
void UART_TX_DMA_SetAfterTransferSourceAddressAdjust(LDD_TDeviceData *DeviceDataPtr, int32_t AddressAdjustment)
{
(*((DMA1_TTCD **)DeviceDataPtr))->DMA_TCD_SLAST_Reg = (uint32_t)AddressAdjustment;
}
int main(void) {
LDD_TDeviceData* hDmaChannel;
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. ***/
hDmaChannel = UART_TX_DMA_Init(NULL);
UART_TX_DMA_SetSourceAddress(hDmaChannel, (LDD_DMA_TData *)0x12345678);
UART_TX_DMA_SetAfterTransferSourceAddressAdjust(hDmaChannel, -2);
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/
Note: hDmaChannel returned by UART_TX_DMA_Init() method is pointer to DMA1_TChnDevData structure:
/* Channel device data structure prototype */
typedef struct DMA1_TChnDevData_stuct {
DMA1_TTCD *TCDPtr; /*!< Channel TCD address */
DMA1_TChnDevConst const *ChnDevConstPtr; /*!< Channel device constants structure address */
LDD_DMA_TErrorFlags ErrorFlags; /*!< Channel error flags */
LDD_TUserData *UserDataPtr; /*!< User data pointer */
DMA1_TEvents Events; /*!< Events state variable */
} DMA1_TChnDevData, *DMA1_TChnDevDataPtr;
As you can see the first item in the TChnDevData structure is:
DMA1_TTCD *TCDPtr; /*!< Channel TCD address */
This TCDPtr pointer is initialized in the UART_TX_DMA_Init() method to the TCD address of the selected DMA channel (=address of real HW registers for this DMA channel).
Best Regards
Marek Varecha
Thanks, that's much neater than my methods, so I'll move to that.
However it still would be nice to have an auto-generated method for this, or alternatively an auto-generated #define for the channel number.
I get that you can't add everything possible to every component, but this seems like quite an important one, seeing as it's quite likely you'll want to transmit different amounts of data every time.
EDIT 2: After testing and debugging, I found the correct line to use was: (*(DMAController_TTCDPtr *)IUART_TX_DMA_DeviceData)->DMA_TCD_SLAST_Reg = DMA_SLAST_SLAST(0-size);
We must be using slightly different versions of PE since my struct had a different name.
Thanks again,
Andy