]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/msp430/usci/Msp430UartDmaP.nc
msp430 usci: fix DMA TX byte overwrite
[tinyos-2.x.git] / tos / chips / msp430 / usci / Msp430UartDmaP.nc
index 99a5c91132537a3e178b26313679526698f023f9..d8a59d9707357c21705951cf54b90e452a8a73bd 100644 (file)
@@ -162,15 +162,25 @@ implementation {
       m_solen = len;
     }
 
-    call Registers.clrIfgTx();
-
     /* Configure DMA to transfer m_solen bytes from m_sobuf */
     call DmaChannel.setupTransfer(DMA_SINGLE_TRANSFER, DMAxTSEL_x,
         DMA_EDGE_SENSITIVE, m_sobuf, (void *)UCxxTXBUF_, m_solen, DMA_BYTE,
         DMA_BYTE, DMA_ADDRESS_INCREMENTED, DMA_ADDRESS_UNCHANGED);
-    call DmaChannel.startTransfer();
 
-    /* Set IFGTX to start DMA transfers */
+    /* DMA writes to UCxxTXBUF each time UCxxTXIFG moves from 0 to 1 as its
+     * trigger is edge sensitive.  Therefore, if UCxxTXIFG is already 1,
+     * indicating the UCxxTXBUF is empty, the trigger is not asserted and the
+     * DMA transfer will hang having done nothing.  The solution is a little
+     * kludgy:
+     *
+     * - Wait for UCxxTXBUF to empty
+     * - Manually clear UCxxTXIFG
+     * - Start the DMA transfer (enable the channel trigger)
+     * - Manually set the UCxxTXIFG
+     */
+    while (!(call Registers.getIfgTx()));
+    call Registers.clrIfgTx();
+    call DmaChannel.startTransfer();
     call Registers.setIfgTx();
     return SUCCESS;
   }