Hello everyone, it's my first post of this forum
I have no experience with Freescale microcontrollers and currently I write some small programs to get some knowledge and experience about them.
Now I want to prepare a small program using DMA channel 1 to send data by UART0.
Here is my function which in my intention configures DMA1 to send data via UART0 (based on CMRM, section 28.5.1.2):
void uartDMA_TX(unsigned char* data, uint32 dataLen)
{
// Enable DMA channel 1 - UART0 Tx
MCF_SCM_DMAREQC = MCF_SCM_DMAREQC_DMAC1(0x0C);
// Enable interrupt on transfer completed
MCF_INTC0_ICR10 = MCF_INTC_ICR_IL(0x3) | MCF_INTC_ICR_IP(0x3);
MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_INT_MASK10 | MCF_INTC_IMRL_MASKALL);
// DMA1 reset
MCF_DMA1_DSR = 0x01;
// Setting MPR (if not set - program behaves the same)
MCF_SCM_MPR |= 0x04;
// Setting PACRs
MCF_SCM_PACR2 |= MCF_SCM_PACR_ACCESS_CTRL1(0b110); // PACR2 - UART0
MCF_SCM_PACR1 |= MCF_SCM_PACR_ACCESS_CTRL0(0b110); // PACR1 - DMA
// SCM RAMBAR - Backdoor enable
MCF_SCM_RAMBAR |= MCF_SCM_RAMBAR_BDE;
/* DMA1 - Control register (enable interrupt on transfer complete, CycleSteal mode, Data size: 1 byte for, source increment, disable request on BCR == 0) */
MCF_DMA1_DCR = MCF_DMA_DCR_INT | MCF_DMA_DCR_CS | MCF_DMA_DCR_SSIZE(MCF_DMA_DCR_SSIZE_BYTE) | MCF_DMA_DCR_SINC | MCF_DMA_DCR_DSIZE(MCF_DMA_DCR_DSIZE_BYTE) | MCF_DMA_DCR_D_REQ;
// Data source address
MCF_DMA1_SAR = (uint32)data;
// Destination address - TransferBuffer UART0
MCF_DMA1_DAR = (uint32)&MCF_UART0_UTB;
// Byte count
MCF_DMA1_BCR = MCF_DMA_BCR_BCR(dataLen);
// Start transfer
MCF_DMA1_DCR |= MCF_DMA_DCR_START;
}
I also set core RAMBAR in function void __initialize_hardware(void):
asm
{
move.l #0x20000221,d0
movec d0,RAMBAR
}
I also created the function handling interrupt:
__declspec(interrupt) void _DMA1_TransferComplete() which I entered into vector at position 74.
UART0 is initiated by function void uart_init (int,unsigned long, unsigned long) available in uart_support.c (defaulty added to my project by CodeWarrior).
And when I run my function by the code:
.....
unsigned char data[5] = {1,2,3,4,5};
uartDMA_TX(data,5);
....
I receive data on terminal, but it is only one byte (AFAIK it should be one in CS mode, so it's OK) with value: 0xFF. When I disable CycleSteal mode (clear CS in DCR) i receive two bytes: 0xFF 0xFF. I receive them independently from the declared bytes count to send when it's > 1. For data length == 1 I receive one byte 0xFF, for more - two bytes 0xFF.
And the interrupt isn't generated by DMA1.
I have no idea what I'm doing bad - can anybody help me?
Thanks.
Greetings from Poland.
Tom.
Hi Tom
The biggest potential problem when using the DMA controller are access rights. It is always interesting to check the DAM controller registers after a transfer to check whether it is signalling an error due to such difficulties.
- don't forget to allow general peripheral access to SRAM (in GPACR0)
If you don't make progress you can also look at the uTasker project. This contains full support for DMA operation on the UARTs: http://www.utasker.com/docs/uTasker/uTaskerUART.PDF
It also allows you to simulate the DMA operation - making study and real development work much easier and efficient. For non-commerical use it is completely free of charge and works on all V2 MCU devices. This will give you everything you need to simulate projects with the device, from drivers to TCP/IP stack and USB, all documented, working out-of-the box and fully supported. It is small footprint and a full-blown project will easily fit in the smallest devices without need for anything more than the CW special edition.
Regards
Mark
www.uTasker.com
- OS, TCP/IP stack, USB, device drivers and simulator for M521X, M521XX, M5221X, M5222X, M5223X, M5225X. One package does them all - "Embedding it better..."