Serial port at 921600 bad

microt
I am testing the board at 921600 board rate.
It sends junk characters. Would any body please try this.
I have the source code below
B460800 works correctly. Does the board support 921600. Please help
--
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#include "/home/saju/target_fs/home/include/s3c2410-regs.h"
# include <time.h>
# include <errno.h>
# include <string.h>

#define COMPORT "/dev/ttySAC1"

#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n",
\
  __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)

int running = 1;

void done (int sig)
/*
    Signal handler to stop the program gracefully
*/
{
    running = 0;
}

static void Error(const char *Msg)
{
    fprintf (stderr, "%s\n", Msg);
    fprintf (stderr, "strerror() is %s\n", strerror(errno));
    exit(1);
}
static void Warning(const char *Msg)
{
     fprintf (stderr, "Warning: %s\n", Msg);
}

int main(int argc, void *argv[])
{
    int fd;
    struct termios COMAttr;
    char SerKeyOut[5] = "12345";
    char SerKeyIn[10000];
    int CntSerKeyIn;

    printf ("Serial port test program\n");
    printf ("Settings: %s B921600 8 N N\n", COMPORT);

    signal (SIGINT, done);  // set up signal handler
    fd = open (COMPORT, O_RDWR | O_NOCTTY | O_NONBLOCK);//Read is non
blocking
    //fd = open (COMPORT, O_RDWR | O_NOCTTY);//Read is blocking
    if (fd == -1) FATAL;

    memset(&COMAttr, 0, sizeof(struct termios));
    COMAttr.c_iflag = IGNPAR;
    //COMAttr.c_cflag = B115200 | HUPCL | CS8 | CREAD | CLOCAL;
    //COMAttr.c_cflag = B460800 | HUPCL | CS8 | CREAD | CLOCAL;  //CS8=>8n1
    COMAttr.c_cflag = B921600 | HUPCL | CS8 | CREAD | CLOCAL;  //CS8=>8n1
    COMAttr.c_cc[VMIN] = 1;

    if (tcsetattr(fd, TCSANOW, &COMAttr) < 0)
        Warning("Unable to set COM port\n");

    write(fd, &SerKeyOut, sizeof(SerKeyOut));

    while (running)
    {
      CntSerKeyIn = read(fd, &SerKeyIn, sizeof(SerKeyIn));

      if (CntSerKeyIn > 0)
      {
           SerKeyIn[CntSerKeyIn] = 0;
        //SerKeyIn[0] = 'b';
        //SerKeyIn[1] = 0;
        printf("Cnt: %d: %s\n", CntSerKeyIn, SerKeyIn);
      }
     }
    return 0;
}

Nor
I don't know how the linux driver handles UART frequency calculation, but
it might be that you can't use 921600 baud on the port.

The default clock source (for the mini2440 at least) seems to be PCLK.
109 #define S3C2410_UCON_DEFAULT      (S3C2410_UCON_TXILEVEL  | \
110                                    S3C2410_UCON_RXILEVEL  | \
111                                    S3C2410_UCON_TXIRQMODE | \
112                                    S3C2410_UCON_RXIRQMODE | \
113                                    S3C2410_UCON_RXFIFO_TOI)

If we calculate using the recommended PCLK freq for 405Mhz FCLK (usually
50.625 Mhz), we get
UBRDIVn = (int)(50625000 / (921600 x 16) ) -1 ~= (int)3.433 - 1

0.433 will be "chopped off" the 3.433 original divisor, so that's an error
rate of 12.6%. 
The S3C2440 manual says that "UART Frame error should be less than
1.87%(3/160)."

With 460800, 
UBRDIVn = (int)(50625000 / (460800 x 16) ) -1 ~= (int)6.8664 - 1
Since we should round it to the nearest integer (to reduce error rate),
it'll be 7, and the error part is 7 - 6.8664 = 0.1336.
Error rate 0.1336 / 7 = 1.908%, that's very close to the margin, i think
that's why it works.

Edgarzg
Attempt with  cfsetispeed and cfsetospeed.how below 


int open_port(char *port,int speed)
{
  int fd;
  struct   termios options,oldtio;

  if ((fd = open(port,O_RDWR |O_NDELAY| O_NOCTTY )) < 0)
  {
    fprintf(stderr,"Error al abrir puerto: %s\n",port);
    exit(0);
  }
  else
  {
    fcntl(fd,F_SETFL,FNDELAY);
    tcgetattr(fd, &oldtio);
    // Set the baud rates ...
    cfsetispeed(&options, speed);
    cfsetospeed(&options, speed);
    options.c_cflag |= (CLOCAL | CREAD);

    // Enable the receiver and set local mode...
    options.c_cflag &= ~CSIZE;
    options.c_cflag |=  CS8;
    options.c_cflag &= ~CSTOPB;        //un bit de stop
    options.c_cflag |= CRTSCTS;
    options.c_cflag &= ~PARENB; // Clear parity enable
    //options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    //options.c_oflag &= ~OPOST;
    options.c_lflag = 0;
    options.c_oflag = 0;
    options.c_iflag = 0;
    options.c_cc[VTIME]= 0;   //temporizador entre caracter, no usado
    options.c_cc[VMIN]= 0;   // bloquea lectura hasta recibir x chars
    // Set the new options for the port...

    tcflush(fd, TCIOFLUSH);
    tcsetattr(fd,TCSANOW, &options);//
  }

  return(fd);
}