How can set serial driver in interrupt mode?
Ricardo Derbes
rmderbes at gmail.com
Wed Jul 8 10:56:04 UTC 2015
Hello.
I'm trying to build an rtems application for leon3 with apbuart in
interrupt mode, but polled mode is always used
My setup is:
RTEMS-4.10.2 (rtems-4.10-1.2.16-src.tar.bz2)
RCC-1.2.16 RTEMS-4.10, GCC 4.4.6
(sparc-rtems-4.10-gcc-4.4.6-1.2.16b-linux.tar.bz2)
Both from Gaisler's site.
The BSP is the default for RCC, leon3. (-qleon3)
My system.h file is:
#include <rtems.h>
#define CONFIGURE_INIT
#include <bsp.h>
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_MAXIMUM_TASKS 4
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32
#define CONFIGURE_EXTRA_TASK_STACKS (3 * RTEMS_MINIMUM_STACK_SIZE)
#define CONFIGURE_MAXIMUM_DRIVERS 4
#include <rtems/confdefs.h>
#ifdef RTEMS_DRVMGR_STARTUP
#ifdef LEON3
#include <drvmgr/ambapp_bus.h>
/* Add Timer and UART Driver */
#ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_DRIVER_AMBAPP_GAISLER_GPTIMER
#endif
#ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_DRIVER_AMBAPP_GAISLER_APBUART
#endif
/* APBUART0 */
struct drvmgr_key grlib_drv_res_apbuart0[] =
{
{ "mode", KEY_TYPE_INT, { (unsigned int) 0 } },
{ "syscon", KEY_TYPE_INT, { (unsigned int) 1 } },
{ "dbgcon", KEY_TYPE_INT, { (unsigned int) 1 } },
KEY_EMPTY
};
/* APBUART1 */
struct drvmgr_key grlib_drv_res_apbuart1[] =
{
{ "mode", KEY_TYPE_INT, { (unsigned int) 1 } },
{ "syscon", KEY_TYPE_INT, { (unsigned int) 0 } },
{ "dbgcon", KEY_TYPE_INT, { (unsigned int) 0 } },
KEY_EMPTY
};
struct drvmgr_drv_res grlib_drv_resources[] =
{
{DRIVER_AMBAPP_GAISLER_APBUART_ID, 0, &grlib_drv_res_apbuart0[0]},
{DRIVER_AMBAPP_GAISLER_APBUART_ID, 1, &grlib_drv_res_apbuart1[0]},
RES_EMPTY
};
#endif
#include <drvmgr/drvmgr_confdefs.h>
And the code of my test application;
#include "system.h"
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#define BUFFSIZE 256
rtems_task Init(rtems_task_argument ignored)
{
#define RXSIZE (ssize_t)1024
int rxLen = 1;
char rxBuf[RXSIZE];
struct termios term;
static char *uart_name = { "/dev/console_b" };
int fd;
int32_t outCons; /* console file descriptor */
char outBuf[BUFFSIZE];
uint32_t nRead;
(void)(ignored);
if( (outCons = open("/dev/console", O_RDWR | O_NOCTTY)) < 0 )
exit(1);
sprintf(outBuf, "Starting\n");
write(outCons, outBuf, strlen(outBuf));
if( (fd = open(uart_name, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0 )
{
sprintf(outBuf, "Error opening %s: [%d] %s\n", uart_name,
errno, strerror(errno));
write(outCons, outBuf, strlen(outBuf));
exit(1);
}
tcgetattr(fd, &term);
cfsetospeed(&term, B115200);
cfsetispeed(&term, B115200);
term.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT
| ECHOCTL | ECHOKE | IEXTEN | ISIG);
term.c_cflag |= (CLOCAL | CREAD);
term.c_cflag |= CS8;
term.c_oflag &= ~OPOST;
term.c_iflag = IGNBRK;
tcsetattr(fd, TCSANOW, &term);
tcflush(fd, TCIOFLUSH);
while (1)
{
rxLen = read(fd, rxBuf, RXSIZE);
if( rxLen < 0)
{
sprintf(outBuf, "Error %d in read(): %s\n", errno, strerror(errno));
write(outCons, outBuf, strlen(outBuf));
exit(1);
}
nRead += rxLen;
if(rxLen == 0)
write(outCons, ".", 1);
else
{
sprintf(outBuf, "\nnRead: %d\n", (int)nRead);
write(outCons, outBuf, strlen(outBuf));
}
}
}
But debugging it, it always uses polled mode for apbuart[1] (and apbuart[0]
I've found that in function
apbuart_init1(struct drvmgr_dev *dev)
when it gets keys value for "mode", it returns NULL, so mode is
TERMIOS_POLLED and
so the callbacks to be used are rtems_termios_callbacks = Callbacks_poll.
How can I set up the serial driver in interrupt mode, without
modifying apbuart_cons.c code
and rebuild the BSP?
Thank you.
More information about the users
mailing list