Hello,
I have the Hercules USB development board running Halcogen generated code based on the 950ZWT FreeRTOS example. I am using version 3.06 of Halcogen and 5.3.0 of Code Composer Studio.
I have two tasks, a Blinky Task which toggles an LED and an SCI Transmission task which outputs messages which I view on the Code Composer Studio Terminal. The Blinky Task sends messages to the SCI Transmission task to be printed via an sci_printf call (which does simple printf style formatting and sends the message via a FreeRTOS message queue to the SCI Transmission task). Everything works fine, until the taskDelay() function executes in the Blinky Task, after it executes, although a message is sent to the SCI Transmission task, and the task attempts to send the message out, the message does not go out. It's as if the DMA transfer completely fails.
If I set the taskDelay to 1, for 1 clock tick, instead of 3000, for 3 seconds. Everything works and all the messages are correctly sent via DMA transfer to the SCI. I am confused.
Here is the Blinky Task:
static portTASK_FUNCTION( BlinkyTask, pvParameters )
{
const portTickType delay = 3000/portTICK_RATE_MS; // 3 second delay?
portTickType lastTickCount;
sci_printf("Blinky task up and running\r\n");
SET_LED(LED_MIDDLE_TOP);
while(1)
{
lastTickCount = xTaskGetTickCount();
sci_printf("Blinky Task ... before task delay, tick count is %d\r\n", lastTickCount);
vTaskDelay(1);
sci_printf("Blinky Task ... after task delay\r\n");
TOGGLE_LED(LED_MIDDLE_TOP);
sci_printf("Blinky Task ... toggled led\r\n");
}
}
Here is code to set up the DMA Control Packet.
void dmaConfigTxCtrlPacket( uint32 sourceAddress,
uint32 destinationAddress,
uint32 length) {
dmaTxCtrlPacket.SADD = sourceAddress; // RAM address
dmaTxCtrlPacket.DADD = destinationAddress; // peripheral address
dmaTxCtrlPacket.CHCTRL = 0; // channel control
dmaTxCtrlPacket.FRCNT = length; // source address length
dmaTxCtrlPacket.ELCNT = 1; // 1 byte
dmaTxCtrlPacket.ELDOFFSET = 0; // element destination offset
dmaTxCtrlPacket.ELSOFFSET = 0; // element source offset
dmaTxCtrlPacket.FRDOFFSET = 0; // frame destination offset
dmaTxCtrlPacket.FRSOFFSET = 0; // frame source offset
dmaTxCtrlPacket.PORTASGN = 4; // port b
dmaTxCtrlPacket.RDSIZE = ACCESS_8_BIT; // read element size
dmaTxCtrlPacket.WRSIZE = ACCESS_8_BIT; // write element size
dmaTxCtrlPacket.TTYPE = FRAME_TRANSFER; // transfer type: frame
dmaTxCtrlPacket.ADDMODERD = ADDR_INC1; // read address mode: post increment
dmaTxCtrlPacket.ADDMODEWR = ADDR_FIXED; // write address mode: fixed
dmaTxCtrlPacket.COMBO = AUTOINIT_OFF; // autoinit off
}
And here is the code to send the message via DMA. Note that I added the FTC interrupt enable to see if I got an FTC interrupt on the first message that fails, I didn't. And note that those first lines of code were executed before the task was started and the behavior was the same. I put the code here to see if maybe the DMA set up was corrupted, but the behavior is the same:
static void sciDMASend(int length, uint8 *data)
{
dmaEnable();
dmaEnableInterrupt(DMA_CH0, BTC); // enable interrupt after receipt of data
dmaEnableInterrupt(DMA_CH0, FTC);
dmaReqAssign(DMA_CH0, 29);
dmaConfigTxCtrlPacket( // First transmission control packet
(uint32)(data), // source address is message
(uint32)(&scilinREG->TD), // destination address transmit buffer of SCI LIN
length); // number of byte to transmit
dmaSetCtrlPacket(DMA_CH0, dmaTxCtrlPacket);
dmaSetChEnable(DMA_CH0, DMA_HW); // set dma chan 0 to trigger on h/w request
scilinREG->SETINT = (1 << 16); // enable TX DMA
}
Any ideas or suggestions would be great. Thank you.
Ruth