• AVR Freaks

Hot!PIC32MZ UART Interrupts - constantly asserted? How are you supposed to get them to stop?

Author
TonyShell
Junior Member
  • Total Posts : 84
  • Reward points : 0
  • Joined: 2016/05/22 20:51:01
  • Location: 0
  • Status: offline
2019/03/21 22:56:24 (permalink)
0

PIC32MZ UART Interrupts - constantly asserted? How are you supposed to get them to stop?

Hi all,
  Hopefully a quick question about the PIC32MZ UART interrupts.  I noticed the following in the manuals:
 
In DS60001361E (PIC32MZ DA Manual) page 374 for UxSTA.UTXISEL/URXISEL:
"Interrupt is generated and asserted while [interrupt condition]"
and in DS61107G (section 21 UART) page 21-18, section 21.5.2:
"For UART modules having 8-level-deep FIFO, an interrupt is generated and asserted when the
 interrupt condition specified by the UTXISEL control bits is true. This means, to clear an interrupt
 for these modules, before clearing the corresponding UxTXIF flag bit, the user application must
 ensure that the interrupt condition specified by the UTXISEL control bits is no longer true."
 
I've done UARTs with the 8/16-bit PICS and this seems way different from them.  According to this, if I don't want to transmit again for a while, I would have to turn the UART off to stop the interrupt from continually triggering and it seems that way in the code that I'm doing.  I have successfully transmitted from the UART using DMA, but I need to set a GPIO to tell the RS-485 transceiver chip when to transmit, so I set the output (RE4) before I transmit (DCH6CONbits.CHEN = 1) by enabling the DMA channel.  I need to turn RE4 off again as soon as the transmission is complete so I can listen for the slave to respond.  Simple enough, I thought, I've done it before.  However, the PIC32MZ is different.  When I enable the transmit interrupt, the PIC locks up like it's continuously on interrupt.  I guess that's my question - do I need to disable the UART (U1MODEbits.ON = 0) or at least disable the transmit (U1STAbits.UTXEN = 0) in order to stop the asserted interrupt?  Please let me know.  Is there a more graceful way to stop the interrupt from constantly being asserted?  Actually, I just tried disabling the transmit while not transmitting and it STILL doesn't work!  Why would they have an interrupt constantly asserted?  Any help would be appreciated.  Here's my code:
  
uart.c:
#include "main.h"
volatile IOCmdBlockFIFO IOFIFO; 
void InitUART(void)
{
    /* UART 1
     * UxBRG = ((Fpb/Desired Baud Rate)/16) - 1 (UxMODE.BRGH = 0)
     *                  or
     * UxBRG = ((Fpb/Desired Baud Rate)/4) - 1 (UxMODE.BRGH = 1)
     *
     * Fpb is determined by UxMODE.CLKSEL
     * 11 = BRG clock is PBCLK2
     * 10 = BRG clock is FRC
     * 01 = BRG clock is SYSCLK (turned off in Sleep mode)
     * 00 = BRG clock is PBCLK2 (turned off in Sleep mode) */
    IEC3bits.U1EIE = 0; // disable all error interrupts
    IEC3bits.U1RXIE = 0; // disable all receive interrupts
    IEC3bits.U1TXIE = 0; // disable all transmit interrupts
    U1MODEbits.ON = 0; // disable the UART before configuring
    while (U1MODEbits.ACTIVE); // wait until not active so the U1MODE registers can be updated
    U1MODEbits.BRGH = 1; // set to high speed mode
    //U1BRG = ((PBCLK2_FREQ / UART_BAUD_RATE) >> 4) - 1; // set the baud rate
    U1BRG = ((PBCLK2_FREQ / UART_BAUD_RATE) >> 2) - 1; // set the baud rate
    U1STA = 0; // clear all bits
    U1STAbits.URXEN = 1; // enable receive
    //U1STAbits.UTXEN = 1; // enable transmit
    IFS3bits.U1EIF = 0; // clear any existing error event
    IFS3bits.U1RXIF = 0; // clear any existing receive event
    IFS3bits.U1TXIF = 0; // clear any existing transmit event
    IPC28bits.U1EIP = 3; // error priority
    IPC28bits.U1EIS = 1; // error sub-priority
    IPC28bits.U1RXIP = 3; // receive priority
    IPC28bits.U1RXIS = 1; // receive sub-priority
    IPC28bits.U1TXIP = 3; // transmit priority
    IPC28bits.U1TXIS = 1; // transmit sub-priority
    //IEC3bits.U1RXIE = 1; // enable all receive interrupts
    IEC3bits.U1TXIE = 1; // enable all transmit interrupts
    U1STAbits.UTXISEL = 0b01; // interrupt is generated and asserted when all characters have been transmitted
    U1MODEbits.ON = 1; // enable the UART
}
 
void __ISR(_UART1_TX_VECTOR, IPL7SRS) __UART1Interrupt(void)
{
    if ((IFS3bits.U1TXIF) && (U1STAbits.TRMT)) // if the transmit interrupt flag is set and the shift register is empty, all characters have been transmitted
    {
        U1STACLR = 0x400; // disable transmit to shut the interrupt off
        LATECLR = 0x10; // turn off the transmit enable output to the RS-485 transceiver
        IFS3CLR = 0x4000; // be sure to clear the UART 1 Transmit interrupt status.
    }
}

 
main.c:
/* send a command to the I/O board, if there are any in the FIFO and the timer is expired */
if ((!IOXmitTimer) && (!IOFIFO.empty)) // check for any commands in the FIFO
{
    LATESET = 0x10; // turn on the transmit enable to the RS485 transceiver
    *ptrIOCmdBuffer = IOFIFOUnload(&IOFIFO); // unload the FIFO
    if (ptrIOCmdBuffer->address) DCH6CONbits.CHEN = 1; // turn DMA Channel 6 on (.CHEN is turned off after the number of bytes in DCH6SSIZ is transferred)
    U1STASET = 0x400; // enable UART transmit
    IOXmitTimer = IO_TIME_BETWEEN_POLLS; // reset the transmit timer
}

 
dma.c -> InitDMA:
/* DMA Channel 6 */
IEC4bits.DMA6IE = 0; // disable DMA Channel 6 interrupts
IFS4bits.DMA6IF = 0; // clear any existing DMA Channel 6 interrupt flag
DCH6CONbits.CHPRI = 3; // priority 3 (highest)
DCH6ECON = 0; // no start or stop IRQ, no pattern match
DCH6SSA = _VirtToPhys((const void*)&UART1TxBuffer); // set transfer source physical address of the transmit buffer for DMA Channel 6
DCH6DSA = _VirtToPhys((const void*)&U1TXREG); // set transfer destination physical address of the UART 1 Write Buffer address
DCH6SSIZ = sizeof(IOCmdBlock); // source size in bytes
DCH6DSIZ = UART_DMA_CELL_SIZE; // destination size in bytes
DCH6CSIZ = UART_DMA_CELL_SIZE; // 1 byte transferred per event
DCH6ECONbits.CHSIRQ = _UART1_TX_VECTOR; // transfer another byte on every UART successful transmit
DCH6ECONbits.SIRQEN = 1; // enable start on matching IRQ
DCH6INTCLR = 0x00ff00ff; // clear existing events, disable all interrupts
DCH6INT = _DCH3INT_CHSDIE_MASK; // enable Source Done interrupt
IPC35bits.DMA6IP = 5; // set DMA Channel 6 priority to 5
IPC35bits.DMA6IS = 2; // set DMA Channel 6 sub-priority to 2
IEC4bits.DMA6IE = 1; // enable DMA Channel 6 interrupt

 
post edited by TonyShell - 2019/03/21 23:03:02
#1

4 Replies Related Threads

    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: PIC32MZ UART Interrupts - constantly asserted? How are you supposed to get them to st 2019/03/21 23:18:02 (permalink)
    4 (1)
    Wouldn't you just clear U1TXIE when you have nothing to transmit, the same as you would in the 8 and 16 bit parts?
     

    Nearly there...
    #2
    aschen0866
    Super Member
    • Total Posts : 4459
    • Reward points : 0
    • Joined: 2006/01/08 22:18:32
    • Location: San Diego
    • Status: offline
    Re: PIC32MZ UART Interrupts - constantly asserted? How are you supposed to get them to st 2019/03/22 08:02:53 (permalink)
    0
    Don't enable UART TX interrupt flag if you are using DMA for UART TX. I am questioning if you even need to use DMA at all. DMA works the best if the transmit side can simply fire and forget.
    #3
    TonyShell
    Junior Member
    • Total Posts : 84
    • Reward points : 0
    • Joined: 2016/05/22 20:51:01
    • Location: 0
    • Status: offline
    Re: PIC32MZ UART Interrupts - constantly asserted? How are you supposed to get them to st 2019/03/22 10:23:11 (permalink)
    0
    Hey thanks to the both of you for the responses!  I'll respond to both replies here.
     
    qhb, I'll try that tonight, but I suspect that the result will be the same.  I'm already disabling the transmit (U1STASET/CLR = 0x400) when I'm not using it, I thought that would shut the interrupt up long enough to get a few bytes to transmit, but it doesn't - as soon as I enable the transmit, it gets locked up, constantly calling the interrupt before it even gets one byte out.  Maybe disabling the interrupt instead of the transmit will have a different result - I'll let you know.  BTW, sorry to hear about HAL.
     
    aschen, I'm using DMA because there are a lot of things happening and I'm just doing the 'fire and forget' with the MPU.  This is for a pinball machine I'm designing.  The main board is handling RGB LED lighting, communication with the I/O boards and communication with sound/video cards.  The DMA is working perfectly, the ONLY reason I'm trying to use the interrupt is so that I can turn a GPIO off that tells the RS-485 transceiver chip that I'm done transmitting and switch to receive.  I did it this way with 8/16-bit PICs and it worked because their interrupts worked differently.  Maybe I should look into the CTS/RTS Simplex mode instead.
     
    I guess my point also is that this is a lousy way to do the interrupts.  To have them constantly asserted doesn't seem very flexible.
    post edited by TonyShell - 2019/03/22 13:35:06
    #4
    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: PIC32MZ UART Interrupts - constantly asserted? How are you supposed to get them to st 2019/03/22 13:50:49 (permalink)
    0
    The transmit interrupt in an 8 bit part is always asserted when the TXBUF is empty.

    Nearly there...
    #5
    Jump to:
    © 2019 APG vNext Commercial Version 4.5