Other Parts Discussed in Thread: DM3730
Hi all,
I've been trying to modify uartEcho.c to receive input from UART4 and to output on UART0. I know that the Beagleboard is getting information on UART4 (checked with a scope), which is connected to the RS485 cape, but it doesn't seem to be getting the correct interrupt. In the Interrupt Service Routine (UARTIsr) the only interrupt I get is the case where UART_INTID_TX_THRES_REACH. If I get rid of the line disabling this interrupt then the program will constantly receive this interrupt, regardless of whether or not I'm inputting anything. This is odd as I'm not trying to transmit anything on UART4, just receive data. The irritating thing is I can receive data from UART0 and output it onto UART4, but not the other way round. I've multiplexed for RXD and everything, so it suggests my code is incorrect, or is this type of operation just not supported by the board? Basically, are there any specific steps I need to follow or is it just an error in my code?
I'll include my uartEcho.c:
#include "uart_irda_cir.h"
#include "soc_AM335x.h"
#include "interrupt.h"
#include "beaglebone.h"
#include "consoleUtils.h"
#include "hw_types.h"
#include "uartNew.h"
#include "gpio_v2.h"
#include "pin_mux.h"
#include "GPIO485.h"
/******************************************************************************
** INTERNAL MACRO DEFINITIONS
******************************************************************************/
#define BAUD_RATE_115200 (115200)
#define UART_MODULE_INPUT_CLK (48000000)
/*
** The number of data bytes to be transmitted to Transmit FIFO of UART
** per generation of the Transmit Empty interrupt. This can take a maximum
** value of TX Trigger Space which is 'TX FIFO size - TX Threshold Level'.
*/
#define NUM_TX_BYTES_PER_TRANS (56)
/******************************************************************************
** INTERNAL FUNCTION PROTOTYPES
******************************************************************************/
static void UartInterruptEnable(void);
//static void UART0AINTCConfigure(void);
static void UART4AINTCConfigure(void);
static void UartFIFOConfigure(void);
static void UartBaudRateSet(void);
//static void UARTIsr(void);
static void UART4Isr(void);
/******************************************************************************
** GLOBAL VARIABLE DEFINITIONS
******************************************************************************/
unsigned char txArray[] = "StarterWare AM335X UART Interrupt application\r\n";
/* A flag used to signify the application to transmit data to UART TX FIFO. */
unsigned int txEmptyFlag = FALSE;
/*
** A variable which holds the number of bytes of the data block transmitted to
** UART TX FIFO until the current instant.
*/
unsigned int currNumTxBytes = 0;
/******************************************************************************
** FUNCTION DEFINITIONS
******************************************************************************/
int main()
{
unsigned int numByteChunks = 0;
unsigned int remainBytes = 0;
unsigned int bIndex = 0;
/* Configuring the system clocks for UART0 instance. */
UART0ModuleClkConfig();
/* Alternative UART4 clock setup */
HWREG(SOC_CM_PER_REGS + CM_PER_UART4_CLKCTRL) |=
CM_PER_UART4_CLKCTRL_MODULEMODE_ENABLE;
/* Waiting for MODULEMODE field to reflect the written value. */
while(CM_PER_UART4_CLKCTRL_MODULEMODE_ENABLE !=
(HWREG(SOC_CM_PER_REGS + CM_PER_UART4_CLKCTRL) &
CM_PER_UART4_CLKCTRL_MODULEMODE));
/* The following script sets up the GPIO1_0 and GPIO1_4 to give high to enable the RS485 chip*/
GPIOInit();
GPIORec();
/* -------------------------------GPIO Setup ends--------------------------------------*/
/* Performing the Pin Multiplexing for UART0 instance. */
UARTPinMuxSetup(0);
/* Performing the Pin Multiplexing for UART4 instance. */
UARTPinMuxSetupNew(1);
/* Performing a module reset. */
UARTModuleReset(SOC_UART_0_REGS);
UARTModuleReset(SOC_UART_4_REGS);
/* Performing FIFO configurations. */
UartFIFOConfigure();
/* Performing Baud Rate settings. */
UartBaudRateSet();
/* Switching to Configuration Mode B. */
UARTRegConfigModeEnable(SOC_UART_0_REGS, UART_REG_CONFIG_MODE_B);
UARTRegConfigModeEnable(SOC_UART_4_REGS, UART_REG_CONFIG_MODE_B);
/* Programming the Line Characteristics. */
UARTLineCharacConfig(SOC_UART_0_REGS,
(UART_FRAME_WORD_LENGTH_8 | UART_FRAME_NUM_STB_1),
UART_PARITY_NONE);
UARTLineCharacConfig(SOC_UART_4_REGS,
(UART_FRAME_WORD_LENGTH_8 | UART_FRAME_NUM_STB_1),
UART_PARITY_NONE);
/* Disabling write access to Divisor Latches. */
UARTDivisorLatchDisable(SOC_UART_0_REGS);
UARTDivisorLatchDisable(SOC_UART_4_REGS);
/* Disabling Break Control. */
UARTBreakCtl(SOC_UART_0_REGS, UART_BREAK_COND_DISABLE);
UARTBreakCtl(SOC_UART_4_REGS, UART_BREAK_COND_DISABLE);
/* Switching to UART16x operating mode. */
UARTOperatingModeSelect(SOC_UART_0_REGS, UART16x_OPER_MODE);
UARTOperatingModeSelect(SOC_UART_4_REGS, UART16x_OPER_MODE);
/* Select the console type based on compile time check */
ConsoleUtilsSetType(CONSOLE_UART);
/* Performing Interrupt configurations. */
UartInterruptEnable();
numByteChunks = (sizeof(txArray) - 1) / NUM_TX_BYTES_PER_TRANS;
remainBytes = (sizeof(txArray) - 1) % NUM_TX_BYTES_PER_TRANS;
while(1)
{
/* This branch is entered if the transmission is not yet complete. */
if(TRUE == txEmptyFlag)
{
if(bIndex < numByteChunks)
{
/* Transmitting bytes in chunks of NUM_TX_BYTES_PER_TRANS. */
currNumTxBytes += UARTFIFOWrite(SOC_UART_0_REGS,
&txArray[currNumTxBytes],
NUM_TX_BYTES_PER_TRANS);
bIndex++;
}
else
{
/* Transmitting remaining data from the data block. */
currNumTxBytes += UARTFIFOWrite(SOC_UART_0_REGS,
&txArray[currNumTxBytes],
remainBytes);
}
txEmptyFlag = FALSE;
/*
** Re-enables the Transmit Interrupt. This interrupt
** was disabled in the Transmit section of the UART ISR.
*/
//UARTIntEnable(SOC_UART_0_REGS, UART_INT_THR);
UARTIntEnable(SOC_UART_4_REGS, UART_INT_THR);
}
}
}
/*
** A wrapper function performing FIFO configurations.
*/
static void UartFIFOConfigure(void)
{
unsigned int fifoConfig = 0;
/*
** - Transmit Trigger Level Granularity is 4
** - Receiver Trigger Level Granularity is 1
** - Transmit FIFO Space Setting is 56. Hence TX Trigger level
** is 8 (64 - 56). The TX FIFO size is 64 bytes.
** - The Receiver Trigger Level is 1.
** - Clear the Transmit FIFO.
** - Clear the Receiver FIFO.
** - DMA Mode enabling shall happen through SCR register.
** - DMA Mode 0 is enabled. DMA Mode 0 corresponds to No
** DMA Mode. Effectively DMA Mode is disabled.
*/
fifoConfig = UART_FIFO_CONFIG(UART_TRIG_LVL_GRANULARITY_4,
UART_TRIG_LVL_GRANULARITY_1,
UART_FCR_TX_TRIG_LVL_56,
1,
1,
1,
UART_DMA_EN_PATH_SCR,
UART_DMA_MODE_0_ENABLE);
/* Configuring the FIFO settings. */
UARTFIFOConfig(SOC_UART_4_REGS, fifoConfig);
UARTFIFOConfig(SOC_UART_0_REGS, fifoConfig);
}
/*
** A wrapper function performing Baud Rate settings.
*/
static void UartBaudRateSet(void)
{
unsigned int divisorValue = 0;
/* Computing the Divisor Value. */
divisorValue = UARTDivisorValCompute(UART_MODULE_INPUT_CLK,
BAUD_RATE_115200,
UART16x_OPER_MODE,
UART_MIR_OVERSAMPLING_RATE_42);
/* Programming the Divisor Latches. */
UARTDivisorLatchWrite(SOC_UART_0_REGS, divisorValue);
UARTDivisorLatchWrite(SOC_UART_4_REGS, divisorValue);
}
/*
** A wrapper function performing Interrupt configurations.
*/
static void UartInterruptEnable(void)
{
/* Enabling IRQ in CPSR of ARM processor. */
IntMasterIRQEnable();
/* Configuring AINTC to receive UART0 interrupts. */
UART4AINTCConfigure();
/* Enabling the specified UART interrupts. */
UARTIntEnable(SOC_UART_4_REGS, (UART_INT_LINE_STAT | UART_INT_THR |
UART_INT_RHR_CTI));
}
/*
** Interrupt Service Routine for UART.
*/
static void UART4Isr(void)
{
unsigned int rxErrorType = 0;
unsigned char rxByte = 0;
unsigned int intId = 0;
unsigned int idx = 0;
/* Checking ths source of UART interrupt. */
intId = UARTIntIdentityGet(SOC_UART_4_REGS);
switch(intId)
{
case UART_INTID_TX_THRES_REACH:
/*
** Checking if the entire transmisssion is complete. If this
** condition fails, then the entire transmission has been completed.
*/
if(currNumTxBytes < (sizeof(txArray) - 1))
{
txEmptyFlag = TRUE;
}
/*
** Disable the THR interrupt. This has to be done even if the
** transmission is not complete so as to prevent the Transmit
** empty interrupt to be continuously generated.
*/
UARTIntDisable(SOC_UART_4_REGS, UART_INT_THR);
break;
case UART_INTID_RX_THRES_REACH:
rxByte = UARTCharGetNonBlocking(SOC_UART_4_REGS);
UARTCharPutNonBlocking(SOC_UART_0_REGS, rxByte);
break;
case UART_INTID_RX_LINE_STAT_ERROR:
rxErrorType = UARTRxErrorGet(SOC_UART_4_REGS);
/* Check if Overrun Error has occured. */
if(rxErrorType & UART_LSR_RX_OE)
{
ConsoleUtilsPrintf
("\r\nUART Overrun Error occured."
" Reading and Echoing all data in RX FIFO.\r\n");
/* Read the entire RX FIFO and the data in RX Shift register. */
for(idx = 0; idx < (RX_FIFO_SIZE + 1); idx++)
{
rxByte = UARTFIFOCharGet(SOC_UART_4_REGS);
UARTFIFOCharPut(SOC_UART_0_REGS, rxByte);
}
break;
}
/* Check if Break Condition has occured. */
else if(rxErrorType & UART_LSR_RX_BI)
{
ConsoleUtilsPrintf("\r\nUART Break Condition occured.");
}
/* Check if Framing Error has occured. */
else if(rxErrorType & UART_LSR_RX_FE)
{
ConsoleUtilsPrintf("\r\nUART Framing Error occured.");
}
/* Check if Parity Error has occured. */
else if(rxErrorType & UART_LSR_RX_PE)
{
ConsoleUtilsPrintf("\r\nUART Parity Error occured.");
}
ConsoleUtilsPrintf(" Data at the top of RX FIFO is: ");
rxByte = UARTFIFOCharGet(SOC_UART_4_REGS);
UARTFIFOCharPut(SOC_UART_0_REGS, rxByte);
break;
case UART_INTID_CHAR_TIMEOUT:
ConsoleUtilsPrintf("\r\nUART Character Timeout Interrupt occured."
" Reading and Echoing all data in RX FIFO.\r\n");
/* Read all the data in RX FIFO. */
while(TRUE == UARTCharsAvail(SOC_UART_4_REGS))
{
rxByte = UARTFIFOCharGet(SOC_UART_4_REGS);
UARTFIFOCharPut(SOC_UART_0_REGS, rxByte);
}
break;
default:
break;
}
}
/*
** This function configures the AINTC to receive UART0 interrupts.
*/
/*
** This function configures the AINTC to receive UART4 interrupts.
*/
static void UART4AINTCConfigure(void)
{
/* Initializing the ARM Interrupt Controller. */
IntAINTCInit();
/* Registering the Interrupt Service Routine(ISR) on UART4. */
IntRegister(SYS_INT_UART4INT, UART4Isr);
/* Setting the priority for the system interrupt in AINTC. */
IntPrioritySet(SYS_INT_UART4INT, 0, AINTC_HOSTINT_ROUTE_IRQ);
/* Enabling the system interrupt in AINTC. */
IntSystemEnable(SYS_INT_UART4INT);
}
/******************************* End of file *********************************/