How to handle the interrupt_uart interrupt on imx6 ?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to handle the interrupt_uart interrupt on imx6 ?

2,294 Views
f_gaudon
Contributor II

Hello,

I am using UART 3 on imx6 and I want to know when my first byte is being sent.

At the moment, I'm polling the TXDC flag to know it but I want to do it with an interrupt. 

The TCEN bit in UCR4, allows the interrupt to be asserted (interrupt_uart) but I don't know how to catch it !
I've configure many register to generate this interrupt but I don't know how to catch it ...

I you have any answers or tips to help me, it would be nice !

Thank you already ,

Florian

4 Replies

1,777 Views
igorpadykov
NXP Employee
NXP Employee

Hi Florian

description of interrupt configuration and some uart tests can be found in

sect.2.1.2 Interrupts (Operation), sect.4.11 Universal Asynchronous Receiver/Transmitter (UART)

attached Linux Manual, uart test :

mxc_uart_test\test - imx-test - i.MX Driver Test Application Software 

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1,778 Views
neeraj_verma
Contributor II

Hi Guys,

I tried looking the links but didn't find.

Can you please point me the UART code (Interrupt for send/receive each byte) for imx7?

0 Kudos

1,778 Views
igorpadykov
NXP Employee
NXP Employee

1,778 Views
neeraj_verma
Contributor II

Thank for your detailed reply.

I could hook-up SIGIO handler and see handler getting called when there is data on respective UART. but I have few issues:

1. SIGIO handler gets called only when bunch of bytes are available (not on each byte)

2. SIGIO getting called without missing as long as I had only UART_B, when I added UART_C also, i see inconsistency and data loss in handler.

3. I use Colibri iMX7d (emmc) evl board, I can use only 2 UART (B and C), not sure how and what to modify in device tree and rebuild bitbake to get all UART /dev/ttymx3 to 7

Pasting my code:

#define BAUDRATE B115200

#define COMM_PORT_B "/dev/ttymxc1"

#define COMM_PORT_C "/dev/ttymxc1"

#define COMM_PORT_D "/dev/ttymxc1"

#define NO_OF_UART 2
static int fd[NO_OF_UART] = {0};
static int max_fds = 0;
static fd_set read_fd;
static char comm_port[NO_OF_UART][16] = {
{COMM_PORT_B},
{COMM_PORT_C},
// {COMM_PORT_D},
};

static uint8_t uart_buf[UART_DATA_LEN];
volatile uint8_t uart_flag;

static void UART_INT (int sig)
{
char rx_buf[UART_DATA_LEN] = {'\0'};
int res = 0;
int i = 0;

for(i = 0; i < NO_OF_UART; i++)
{
if(FD_ISSET(fd[i], &read_fd)) {
res = read(fd[i], &rx_buf, UART_DATA_LEN);
if(res > 0) {
//data received, copy into buffer with flag and clear the buffer
uart_flag |= (1<<i); //set respective flag
memcpy(uart_buf, rx_buf, res);
memset(rx_buf, '\0', UART_DATA_LEN);
}
}
}
}


int init_uart(int *fd, const char *port)
{
int rc = 0;
char cmd[CMD_STR_LEN] = {'\0'};
struct termios newtio;
struct sigaction saio;

sprintf(cmd, "stty -F %s 115200 -echo", port);
system(cmd);

memset(cmd, '\0', CMD_STR_LEN);
sprintf(cmd, "cat < %s &", port);
system(cmd);

*fd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
if(*fd < 0) {
perror(port);
exit(-1);
}

saio.sa_handler = UART_INT;
sigemptyset(&saio.sa_mask);
saio.sa_flags = SA_SIGINFO;
sigaction(SIGIO, &saio,NULL);

fcntl (*fd, F_SETOWN, getgid());
fcntl(*fd, F_SETFL, FASYNC);

newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD ;
newtio.c_iflag = IGNPAR | IXOFF;
newtio.c_oflag = 0;
newtio.c_lflag = 0;
newtio.c_cc[VMIN] = 0;
newtio.c_cc[VTIME] = 0;
tcflush(*fd, TCIFLUSH);
tcsetattr(*fd, TCSANOW, &newtio);

return rc;

}

static uint8_t cal_crc(uint8_t *byte, size_t len)
{
uint8_t crc = 0xFF;
size_t i, j;

for(i = 0; i < len; i++)
{
crc ^= byte[i];
for(j = 0; j < 8; j++)
{
if((crc & 0x80) != 0) {
crc = (uint8_t) ((crc << 1) ^ 0x31);
} else {
crc <<= 1;
}
}
}
return crc;
}

int send_data(int fd, uint8_t *buf)
{
int rc = 0;
int size = buf[NO_OF_BYTES] + 2;
buf[size] = cal_crc(buf,buf[NO_OF_BYTES] + 1);
rc = write(fd, (char *)buf, size);

return rc;
}

// Keep reentrant as this function runs in serveral instances
static int uart_trigger(void *index)
{
int rc = 0;
do
{
FD_SET(fd[*(int *)index], &read_fd);
pselect(max_fds + 1, &read_fd, NULL, NULL, NULL, NULL);

}while(1);

return rc;
}

static int largest_num(int arr[], int n)
{
int i;
int max = arr[0];

for(i = 1; i < n; i++)
{
if(arr[i] > max) {
max = arr[i];
}
}
return max;
}

int uart_main(void *td)
{
int rc = 0;
int mydata = *(int *)td;
int i = 0;
pthread_t thread_id[NO_OF_UART];
int tr = 0;
int arg[NO_OF_UART] = {0};

printf("%s() called thread ID: %d\n", __FUNCTION__, mydata);

for(i = 0; i < NO_OF_UART; i++) {
init_uart(&fd[i], comm_port[i]);
}

//calculate max fds
max_fds = largest_num(fd, NO_OF_UART);

FD_ZERO(&read_fd);

for(i = 0; i < NO_OF_UART; i++) {
arg[i] = i;
rc |= pthread_create(&(thread_id[i]), NULL, (void *) uart_trigger, (void *)&arg[i]);

}


do {
switch(uart_flag)
{
case UART_B_DATA:
printf("UART_B: %s\n", uart_buf);
memset(uart_buf, '\0', UART_DATA_LEN);
uart_flag &= ~UART_B_DATA;

break;
case UART_C_DATA:
printf("UART_C: %s\n", uart_buf);
memset(uart_buf, '\0', UART_DATA_LEN);
uart_flag &= ~UART_C_DATA;

break;
}

}while(1);


for(i = 0; i < NO_OF_UART; i++) {
rc |=pthread_join(thread_id[i], (void **)&tr);
printf("Thread: %d %s\n", i, tr==0?"SUCCESS":"FAILED");
}


return rc;
}

Please suggest me on this....

0 Kudos