I was trying to create a UART driver for the PIC32MX320F128H, when I noticed that any time the UART IRQ occured, it would crash the system.
The Debugger told me that the program was halting at these lines(119 - 21)? of ctr0.s every time.
\_reset:
jal \_startup
nop
Here is the BOARD setup
// BOARD Setup
\#pragma config POSCMOD = XT // Set oscillator to XT, crystal mode.
\#pragma config FPBDIV = DIV_2 // Set peripheral clock to run at half sys clock
\#pragma config FWDTEN = OFF // Disable watchdog timer
\#pragma config CP = OFF // Disable Code protect, ensures all memory is available
\#pragma config FPLLMUL = MUL_20 // PLL Multiplier
\#pragma config FPLLODIV = DIV_1 // System PLL Output Clock Divide
\#define SYSTEM_CLOCK 80000000L
\#define PB_CLOCK SYSTEM_CLOCK/2
\#define TRUE 1
\#define FALSE 0
// UART DEFINES
\#define UART_IBITS 0x1C000000 // ERR, RX, TX interrupt bits
\#define ERR_IBITS 0x4000000
\#define RX_IBITS 0x8000000
\#define TX_IBITS 0x10000000
\#define STA_OERR_BIT 2 // U1STA bit assosciated with OERR
\#define TEST_CHAR 0x41 // char to send and test stuff, A in ascii
\#define U1_PRIORITY 0b110 // don't know what this should be
\#define U1_SUBPRIORITY 0b01 // don't know what this should be either
Here is the UART setup
void Uart_Init(unsigned long baudRate) {
AD1PCFG = 0xffff; // Set PORTs to digital mode
// Disable interrupts to avoid crazy malloc errors while initing CBuffs
__builtin_disable_interrupts();
// Initialize CBuffers
RXBuff = InitCBuff();
TXBuff = InitCBuff();
// Enable interrupts after cbuffs are initialized
__builtin_enable_interrupts();
// Disable stdout to UART2
setbuf(stdout, NULL);
// Clear control registers
U1MODECLR = 1;
U1STACLR = 1;
// Clear RX, TX registers
U1RXREG = 0;
U1TXREG = 0;
// Set Baudrate, U1BRG should be 20 or 21. In this case it is 21.
U1MODEbits.BRGH = 0; // enable high baudrate mode
U1BRG = (PB_CLOCK / (16 * baudRate)) - 1;
// Turn on the UART
// Note, that by default the UART is configured for 8 data bits, 1 stop bit, and no parity.
U1MODEbits.ON = 1; // 8 bit 1 stop bit
// Enable RX and TX pins
U1STAbits.URXEN = 1;
U1STAbits.UTXEN = 1;
// Enable interrupts RX and ERR interrupts. TX will enable when TXBuff has chars
IEC0bits.U1RXIE = 1;
IEC0bits.U1EIE = 1;
IEC0bits.U1TXIE = 0;
// Set Interrupt priority and subpriority
IPC6bits.U1IP = U1_PRIORITY;
IPC6bits.U1IS = U1_SUBPRIORITY;
// Set interrupt modes
U1STAbits.URXISEL = 0b00; // flag when char received
U1STAbits.UTXISEL = 0b10; // flag when buffer is empty
}
Finally, here is the ISR definition
void __ISR(_UART1_VECTOR, IPL4AUTO) IntUart1Handler(void) {
I also tried to use a deprecated method to enable the interrupts, but I couldn't even figure out how to get the plib library working so that didn't get far.
// Depreceated method.
void __attribute__ ((nomips16)) INTEnableSystemMultiVectoredInt(void)
{
unsigned int val;
// set the CP0 cause IV bit high
asm volatile("mfc0 %0,$13" : "=r"(val));
val |= 0x00800000;
asm volatile("mtc0 %0,$13" : "+r"(val));
INTCONSET = _INTCON_MVEC_MASK;
// set the CP0 status IE bit high to turn on interrupts
INTEnableInterrupts();
}
I was really at the end of my wits until Rich TBCO from the MPLAB forums pointed me in the right direction.
I wasn't enabling interrupts correctly. Here is how I enabled the UART interrupts following this guide.
There's really just seven steps for this. Steps 3 through 7 should be done in order in your program.
Here is how I configured the UART following these steps.
#include <xc.h>
#include <sys/attribs.h>
void Uart_Init(unsigned long baudRate) {
// Set Ports to digital mode, configure later to only do UART pins.
AD1PCFG = 0xffff;
// Initialize CBuffers
RXBuff = InitCBuff();
TXBuff = InitCBuff();
// Clear control registers
U1MODECLR = 0xFF;
U1STACLR = 0xFF;
// Clear RX, TX registers
U1RXREG = 0;
U1TXREG = 0;
// Set Baudrate, U1BRG should be 20 or 21. In this case it is 21.
U1MODEbits.BRGH = 0; // enable high baudrate mode
U1BRG = (PB_CLOCK / (16 * baudRate)) ;
// Turn off the UART
U1MODEbits.ON = 0;
// Enable RX and TX pins
U1STAbits.URXEN = 1;
U1STAbits.UTXEN = 1;
// Set interrupt modes
U1STAbits.URXISEL = 0b00; // flag when char received
U1STAbits.UTXISEL = 0b10; // flag when buffer is empty
// Set Interrupt priority and sub-priority
IPC6bits.U1IP = 4;
IPC6bits.U1IS = 1;
// Clear flags
IFS0bits.U1EIF = 0;
IFS0bits.U1RXIF = 0;
IFS0bits.U1TXIF = 0;
// Enable interrupts RX and ERR interrupts. TX not necessary for this simple program
IEC0bits.U1RXIE = 1;
IEC0bits.U1EIE = 1;
IEC0bits.U1TXIE = 0;
// Enable multi-vector interrupts
INTCONSET = _INTCON_MVEC_MASK;
// Enable Global Interrupts
__builtin_enable_interrupts();
// Enable UART
// Note, that by default the UART is configured for 8 data bits, 1 stop bit, and no parity.
U1MODEbits.ON = 1;
}