# HG changeset patch # User Florian Pose # Date 1264165818 -3600 # Node ID 2ba454c790c579462896420cfd7b848b2391891a # Parent e3346de75612930e79eba98cf81e9988ab1e7e19 Implemented setting of baud rate, data frame and RTS/CTS. diff -r e3346de75612 -r 2ba454c790c5 examples/tty/serial.c --- a/examples/tty/serial.c Fri Jan 22 11:02:04 2010 +0100 +++ b/examples/tty/serial.c Fri Jan 22 14:10:18 2010 +0100 @@ -39,6 +39,8 @@ // Optional features #define PFX "ec_tty_example: " +#define DEBUG 0 + /*****************************************************************************/ #define VendorIdBeckhoff 0x00000002 @@ -48,7 +50,10 @@ typedef enum { SER_REQUEST_INIT, SER_WAIT_FOR_INIT_RESPONSE, - SER_READY + SER_READY, + SER_SET_RTSCTS, + SER_SET_BAUD_RATE, + SER_SET_DATA_FRAME, } serial_state_t; typedef struct { @@ -78,7 +83,19 @@ u32 off_status; u32 off_rx; - u8 data_frame_config; + ec_sdo_request_t *rtscts_sdo; + u8 requested_rtscts; + u8 current_rtscts; + + ec_sdo_request_t *baud_sdo; + u8 requested_baud_rate; + u8 current_baud_rate; + + ec_sdo_request_t *frame_sdo; + u8 requested_data_frame; + u8 current_data_frame; + + unsigned int config_error; } el6002_t; @@ -210,12 +227,12 @@ typedef struct { u8 value; - unsigned short data_bits; + unsigned int data_bits; parity_t parity; - unsigned short stop_bits; + unsigned int stop_bits; } el600x_data_frame_t; -/** EL600x supported values for SDO 4074. +/** EL600x supported values for data frame SDO. */ el600x_data_frame_t el600x_data_frame[] = { {0x01, 7, PAR_EVEN, 1}, @@ -230,17 +247,64 @@ {0x0d, 8, PAR_ODD, 2}, }; +typedef struct { + u8 value; + unsigned int baud; + tcflag_t cbaud; +} el600x_baud_rate_t; + +/** EL600x supported values for baud rate SDO. + */ +el600x_baud_rate_t el600x_baud_rate[] = { + {1, 300, B300}, + {2, 600, B600}, + {3, 1200, B1200}, + {4, 2400, B2400}, + {5, 4800, B4800}, + {6, 9600, B9600}, + {7, 19200, B19200}, + {8, 38400, B38400}, + {9, 57600, B57600}, + {10, 115200, B115200} +}; + /****************************************************************************/ -int el6002_cflag_changed(void *data, unsigned short cflag) +int el6002_cflag_changed(void *data, tcflag_t cflag) { el6002_t *ser = (el6002_t *) data; - unsigned short data_bits, stop_bits; + unsigned int data_bits, stop_bits; + tcflag_t cbaud, rtscts; parity_t par; unsigned int i; + el600x_baud_rate_t *b_to_use = NULL; el600x_data_frame_t *df_to_use = NULL; +#if DEBUG printk(KERN_INFO PFX "%s(data=%p, cflag=%x).\n", __func__, ser, cflag); +#endif + + rtscts = cflag & CRTSCTS; + printk(KERN_INFO PFX "Requested rts/cts: %s.\n", rtscts ? "yes" : "no"); + + cbaud = cflag & CBAUD; + + for (i = 0; i < sizeof(el600x_baud_rate) / sizeof(el600x_baud_rate_t); + i++) { + el600x_baud_rate_t *b = el600x_baud_rate + i; + if (b->cbaud == cbaud) { + b_to_use = b; + break; + } + } + + if (b_to_use) { + printk(KERN_INFO PFX "Requested baud rate: %u.\n", b_to_use->baud); + } else { + printk(KERN_ERR PFX "Error: Baud rate index %x not supported.\n", + cbaud); + return -EINVAL; + } switch (cflag & CSIZE) { case CS5: @@ -267,7 +331,7 @@ stop_bits = (cflag & CSTOPB) ? 2 : 1; - printk(KERN_INFO PFX "Requested Data frame type %u%c%u.\n", + printk(KERN_INFO PFX "Requested Data frame: %u%c%u.\n", data_bits, (par == PAR_NONE ? 'N' : (par == PAR_ODD ? 'O' : 'E')), stop_bits); @@ -288,8 +352,10 @@ return -EINVAL; } - printk(KERN_ERR PFX "Reconfiguring.\n"); - ser->data_frame_config = df_to_use->value; + ser->requested_rtscts = rtscts != 0; + ser->requested_baud_rate = b_to_use->value; + ser->requested_data_frame = df_to_use->value; + ser->config_error = 0; return 0; } @@ -320,6 +386,13 @@ ser->off_tx = 0; ser->off_status = 0; ser->off_rx = 0; + ser->requested_rtscts = 0x00; // no hardware handshake + ser->current_rtscts = 0xff; + ser->requested_baud_rate = 6; // 9600 + ser->current_baud_rate = 0; + ser->requested_data_frame = 0x03; // 8N1 + ser->current_data_frame = 0x00; + ser->config_error = 0; if (!(ser->sc = ecrt_master_slave_config( master, 0, position, Beckhoff_EL6002))) { @@ -328,6 +401,27 @@ goto out_free_tty; } + if (!(ser->rtscts_sdo = ecrt_slave_config_create_sdo_request(ser->sc, + 0x8000, 0x01, 1))) { + printk(KERN_ERR PFX "Failed to create SDO request.\n"); + ret = -ENOMEM; + goto out_free_tty; + } + + if (!(ser->baud_sdo = ecrt_slave_config_create_sdo_request(ser->sc, + 0x8000, 0x11, 1))) { + printk(KERN_ERR PFX "Failed to create SDO request.\n"); + ret = -ENOMEM; + goto out_free_tty; + } + + if (!(ser->frame_sdo = ecrt_slave_config_create_sdo_request(ser->sc, + 0x8000, 0x15, 1))) { + printk(KERN_ERR PFX "Failed to create SDO request.\n"); + ret = -ENOMEM; + goto out_free_tty; + } + if (ecrt_slave_config_pdos(ser->sc, EC_END, el6002_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; @@ -403,6 +497,36 @@ switch (ser->state) { case SER_READY: + /* Check, if hardware handshaking has to be configured. */ + if (!ser->config_error && + ser->requested_rtscts != ser->current_rtscts) { + EC_WRITE_U8(ecrt_sdo_request_data(ser->rtscts_sdo), + ser->requested_rtscts); + ecrt_sdo_request_write(ser->rtscts_sdo); + ser->state = SER_SET_RTSCTS; + break; + } + + /* Check, if the baud rate has to be configured. */ + if (!ser->config_error && + ser->requested_baud_rate != ser->current_baud_rate) { + EC_WRITE_U8(ecrt_sdo_request_data(ser->baud_sdo), + ser->requested_baud_rate); + ecrt_sdo_request_write(ser->baud_sdo); + ser->state = SER_SET_BAUD_RATE; + break; + } + + /* Check, if the data frame has to be configured. */ + if (!ser->config_error && + ser->requested_data_frame != ser->current_data_frame) { + EC_WRITE_U8(ecrt_sdo_request_data(ser->frame_sdo), + ser->requested_data_frame); + ecrt_sdo_request_write(ser->frame_sdo); + ser->state = SER_SET_DATA_FRAME; + break; + } + /* Send data */ tx_accepted_toggle = status & 0x0001; @@ -410,7 +534,9 @@ ser->tx_data_size = ectty_tx_data(ser->tty, ser->tx_data, ser->max_tx_data_size); if (ser->tx_data_size) { +#if DEBUG printk(KERN_INFO PFX "Sending %u bytes.\n", ser->tx_data_size); +#endif ser->tx_request_toggle = !ser->tx_request_toggle; ser->tx_accepted_toggle = tx_accepted_toggle; } @@ -422,7 +548,9 @@ if (rx_request_toggle != ser->rx_request_toggle) { uint8_t rx_data_size = status >> 8; ser->rx_request_toggle = rx_request_toggle; +#if DEBUG printk(KERN_INFO PFX "Received %u bytes.\n", rx_data_size); +#endif ectty_rx_data(ser->tty, rx_data, rx_data_size); ser->rx_accepted_toggle = !ser->rx_accepted_toggle; } @@ -444,12 +572,63 @@ case SER_WAIT_FOR_INIT_RESPONSE: if (!(status & (1 << 2))) { - printk(KERN_INFO PFX "Init successful.\n"); + printk(KERN_INFO PFX "EL600x init successful.\n"); ser->tx_accepted_toggle = 1; ser->control = 0x0000; ser->state = SER_READY; } break; + + case SER_SET_RTSCTS: + switch (ecrt_sdo_request_state(ser->rtscts_sdo)) { + case EC_REQUEST_SUCCESS: + printk(KERN_INFO PFX "Slave accepted rts/cts.\n"); + ser->current_rtscts = ser->requested_rtscts; + ser->state = SER_REQUEST_INIT; + break; + case EC_REQUEST_ERROR: + printk(KERN_INFO PFX "Failed to set rts/cts!\n"); + ser->state = SER_REQUEST_INIT; + ser->config_error = 1; + break; + default: + break; + } + break; + + case SER_SET_BAUD_RATE: + switch (ecrt_sdo_request_state(ser->baud_sdo)) { + case EC_REQUEST_SUCCESS: + printk(KERN_INFO PFX "Slave accepted baud rate.\n"); + ser->current_baud_rate = ser->requested_baud_rate; + ser->state = SER_REQUEST_INIT; + break; + case EC_REQUEST_ERROR: + printk(KERN_INFO PFX "Failed to set baud rate!\n"); + ser->state = SER_REQUEST_INIT; + ser->config_error = 1; + break; + default: + break; + } + break; + + case SER_SET_DATA_FRAME: + switch (ecrt_sdo_request_state(ser->frame_sdo)) { + case EC_REQUEST_SUCCESS: + printk(KERN_INFO PFX "Slave accepted data frame.\n"); + ser->current_data_frame = ser->requested_data_frame; + ser->state = SER_REQUEST_INIT; + break; + case EC_REQUEST_ERROR: + printk(KERN_INFO PFX "Failed to set data frame!\n"); + ser->state = SER_REQUEST_INIT; + ser->config_error = 1; + break; + default: + break; + } + break; } EC_WRITE_U16(pd + ser->off_ctrl, ser->control); diff -r e3346de75612 -r 2ba454c790c5 include/ectty.h --- a/include/ectty.h Fri Jan 22 11:02:04 2010 +0100 +++ b/include/ectty.h Fri Jan 22 14:10:18 2010 +0100 @@ -64,7 +64,7 @@ * \return Pointer to the interface object, otherwise an ERR_PTR value. */ ec_tty_t *ectty_create( - int (*cflag_cb)(void *cb_data, unsigned short cflag), + int (*cflag_cb)(void *cb_data, tcflag_t cflag), void *cb_data ); diff -r e3346de75612 -r 2ba454c790c5 tty/module.c --- a/tty/module.c Fri Jan 22 11:02:04 2010 +0100 +++ b/tty/module.c Fri Jan 22 14:10:18 2010 +0100 @@ -108,7 +108,7 @@ struct timer_list timer; struct tty_struct *tty; - int (*cflag_cb)(void *, unsigned short); + int (*cflag_cb)(void *, tcflag_t); void *cb_data; }; @@ -278,7 +278,7 @@ /*****************************************************************************/ int ec_tty_init(ec_tty_t *tty, int minor, - int (*cflag_cb)(void *, unsigned short), void *cb_data) + int (*cflag_cb)(void *, tcflag_t), void *cb_data) { tty->minor = minor; tty->tx_read_idx = 0; @@ -639,7 +639,7 @@ * Public functions and methods *****************************************************************************/ -ec_tty_t *ectty_create(int (*cflag_cb)(void *, unsigned short), void *cb_data) +ec_tty_t *ectty_create(int (*cflag_cb)(void *, tcflag_t), void *cb_data) { ec_tty_t *tty; int minor, ret;