static int sw_uart_request_port(struct uart_port *port) { struct sw_uart_port *sw_uport = UART_TO_SPORT(port); int ret; SERIAL_DBG("request port(ioremap & request io) %d\n", port->line); /* request memory resource */ if (!request_mem_region(port->mapbase, SUNXI_UART_MEM_RANGE, SUNXI_UART_DEV_NAME)) { SERIAL_MSG("uart%d, request mem region failed\n", sw_uport->id); return -EBUSY; } port->membase = ioremap(port->mapbase, SUNXI_UART_MEM_RANGE); if (!port->membase) { SERIAL_MSG("uart%d, ioremap failed\n", sw_uport->id); release_mem_region(port->mapbase, SUNXI_UART_MEM_RANGE); return -EBUSY; } /* request io resource */ ret = sw_uart_request_gpio(sw_uport); if (ret < 0) { release_mem_region(port->mapbase, SUNXI_UART_MEM_RANGE); return ret; } return 0; }
static int sw_uart_request_resource(struct sw_uart_port* sw_uport, struct sw_uart_pdata *pdata) { struct uart_port *port = &sw_uport->port; SERIAL_DBG("get system resource(clk & IO)\n"); if (sw_uart_regulator_request(sw_uport, pdata) < 0) { SERIAL_MSG("uart%d request regulator failed!\n", sw_uport->id); return -ENXIO; } sw_uart_regulator_enable(pdata); sw_uport->mclk = clk_get(port->dev, sw_uport->name); if (IS_ERR_OR_NULL(sw_uport->mclk)) { SERIAL_MSG("uart%d get mclk failed\n", sw_uport->id); return PTR_ERR(sw_uport->mclk); } #ifdef CONFIG_SW_UART_DUMP_DATA sw_uport->dump_buff = (char*)kmalloc(MAX_DUMP_SIZE, GFP_KERNEL); if (!sw_uport->dump_buff) { SERIAL_MSG("uart%d fail to alloc dump buffer\n", sw_uport->id); } #endif return 0; }
/** * Print calibration results for plotting or manual frame adjustment. */ void Bed_level::print_2d_array(const uint8_t sx, const uint8_t sy, const uint8_t precision, float (*fn)(const uint8_t, const uint8_t)) { #if DISABLED(SCAD_MESH_OUTPUT) SERIAL_STR(ECHO); for (uint8_t x = 0; x < sx; x++) { for (uint8_t i = 0; i < precision + 2 + (x < 10 ? 1 : 0); i++) SERIAL_CHR(' '); SERIAL_VAL((int)x); } SERIAL_EOL(); #endif #if ENABLED(SCAD_MESH_OUTPUT) SERIAL_EM("measured_z = ["); // open 2D array #endif for (uint8_t y = 0; y < sy; y++) { #if ENABLED(SCAD_MESH_OUTPUT) SERIAL_MSG(" ["); // open sub-array #else SERIAL_STR(ECHO); if (y < 10) SERIAL_CHR(' '); SERIAL_VAL((int)y); #endif for (uint8_t x = 0; x < sx; x++) { SERIAL_CHR(' '); const float offset = fn(x, y); if (!isnan(offset)) { if (offset >= 0) SERIAL_CHR('+'); SERIAL_VAL(offset, precision); } else { #if ENABLED(SCAD_MESH_OUTPUT) for (uint8_t i = 3; i < precision + 3; i++) SERIAL_CHR(' '); SERIAL_MSG("NAN"); #else for (uint8_t i = 0; i < precision + 3; i++) SERIAL_CHR(i ? '=' : ' '); #endif } #if ENABLED(SCAD_MESH_OUTPUT) if (x < sx - 1) SERIAL_CHR(','); #endif } #if ENABLED(SCAD_MESH_OUTPUT) SERIAL_CHR(' '); SERIAL_CHR(']'); // close sub-array if (y < sy - 1) SERIAL_CHR(','); #endif SERIAL_EOL(); } #if ENABLED(SCAD_MESH_OUTPUT) SERIAL_MSG("\n];"); // close 2D array #endif SERIAL_EOL(); }
static void sw_uart_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { struct sw_uart_port *sw_uport = UART_TO_SPORT(port); int ret; SERIAL_DBG("PM state %d -> %d\n", oldstate, state); switch (state) { case 0: /* Power up */ if (sw_uport->mclk->enable_count > 0) { SERIAL_MSG("uart%d clk is already enable\n", sw_uport->id); break; } ret = clk_prepare_enable(sw_uport->mclk); if (ret) { SERIAL_MSG("uart%d release reset failed\n", sw_uport->id); } break; case 3: /* Power down */ if (sw_uport->mclk->enable_count == 0) { SERIAL_MSG("uart%d clk is already disable\n", sw_uport->id); break; } clk_disable_unprepare(sw_uport->mclk); break; default: SERIAL_MSG("uart%d, Unknown PM state %d\n", sw_uport->id, state); } }
static int sw_uart_startup(struct uart_port *port) { struct sw_uart_port *sw_uport = UART_TO_SPORT(port); int ret; SERIAL_DBG("start up ...\n"); ret = request_irq(port->irq, sw_uart_irq, 0, sw_uport->name, port); if (unlikely(ret)) { SERIAL_MSG("uart%d cannot get irq %d\n", sw_uport->id, port->irq); return ret; } sw_uport->msr_saved_flags = 0; /* * PTIME mode to select the THRE trigger condition: * if PTIME=1(IER[7]), the THRE interrupt will be generated when the * the water level of the TX FIFO is lower than the threshold of the * TX FIFO. and if PTIME=0, the THRE interrupt will be generated when * the TX FIFO is empty. * In addition, when PTIME=1, the THRE bit of the LSR register will not * be set when the THRE interrupt is generated. You must check the * interrupt id of the IIR register to decide whether some data need to * send. */ sw_uport->ier = SW_UART_IER_RLSI | SW_UART_IER_RDI; #ifdef CONFIG_SW_UART_PTIME_MODE sw_uport->ier |= SW_UART_IER_PTIME; #endif return 0; }
static int sw_uart_resume(struct device *dev) { #ifdef CONFIG_EVB_PLATFORM unsigned long flags = 0; #endif struct uart_port *port = dev_get_drvdata(dev); struct sw_uart_port *sw_uport = UART_TO_SPORT(port); if (port) { if (SW_UART_NEED_SUSPEND(port)) { sw_uart_regulator_enable(dev->platform_data); sw_uart_select_gpio_state(sw_uport->pctrl, PINCTRL_STATE_DEFAULT, sw_uport->id); } #ifdef CONFIG_EVB_PLATFORM /* It's used only in super-standby mode. FPGA maybe fall into sw_uart_force_lcr(), so comment it. */ if (sw_is_console_port(port) && !console_suspend_enabled) { spin_lock_irqsave(&port->lock, flags); sw_uart_reset(sw_uport); serial_out(port, sw_uport->fcr, SW_UART_FCR); serial_out(port, sw_uport->mcr, SW_UART_MCR); serial_out(port, sw_uport->lcr|SW_UART_LCR_DLAB, SW_UART_LCR); serial_out(port, sw_uport->dll, SW_UART_DLL); serial_out(port, sw_uport->dlh, SW_UART_DLH); serial_out(port, sw_uport->lcr, SW_UART_LCR); serial_out(port, sw_uport->ier, SW_UART_IER); spin_unlock_irqrestore(&port->lock, flags); } #endif uart_resume_port(&sw_uart_driver, port); SERIAL_MSG("uart%d resume. DLH: %d, DLL: %d. \n", port->line, sw_uport->dlh, sw_uport->dll); } return 0; }
static int __init sw_console_setup(struct console *co, char *options) { struct uart_port *port = NULL; struct sw_uart_port *sw_uport; int baud = 115200; int bits = 8; int parity = 'n'; int flow = 'n'; if (unlikely(co->index >= SUNXI_UART_NUM || co->index < 0)) return -ENXIO; port = sw_console_get_port(co); if (port == NULL) return -ENODEV; sw_uport = UART_TO_SPORT(port); if (!port->iobase && !port->membase) return -ENODEV; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); SERIAL_MSG("console setup baud %d parity %c bits %d, flow %c\n", baud, parity, bits, flow); return uart_set_options(port, co, baud, parity, bits, flow); }
static int __init sunxi_uart_init(void) { int ret; u32 i; struct sw_uart_pdata *pdata; sunxi_uart_device_scan(); ret = sw_uart_get_devinfo(); if (unlikely(ret)) return ret; ret = uart_register_driver(&sw_uart_driver); if (unlikely(ret)) { SERIAL_MSG("driver initializied\n"); return ret; } for (i=0; i<SUNXI_UART_NUM; i++) { pdata = &sw_uport_pdata[i]; if (!pdata->used) continue; platform_device_register(&sw_uport_device[i]); sunxi_uart_sysfs(&sw_uport_device[i]); } return platform_driver_register(&sw_uport_platform_driver); }
static inline int sw_uart_check_baudset(struct uart_port *port, unsigned int baud) { struct sw_uart_port *sw_uport = UART_TO_SPORT(port); static struct baudset baud_set[] = { {115200, 24000000, 120000000}, {230400, 30000000, 120000000}, {380400, 24000000, 120000000}, {460800, 30000000, 120000000}, {921600, 30000000, 120000000}, {1000000, 31000000, 120000000}, //31578947 {1500000, 24000000, 120000000}, {1750000, 54000000, 120000000}, //54545454 {2000000, 31000000, 120000000}, //31578947 {2500000, 40000000, 120000000}, //40000000 {3000000, 46000000, 120000000}, //46153846 {3250000, 54000000, 120000000}, //54545454 {3500000, 54000000, 120000000}, //54545454 {4000000, 66000000, 120000000}, //66666666 }; struct baudset *setsel; int i; if (baud < 115200) { if (port->uartclk < 24000000) { SERIAL_MSG("uart%d, uartclk(%d) too small for baud %d\n", sw_uport->id, port->uartclk, baud); return -1; } } else { for (i=0; i<sizeof(baud_set)/sizeof(baud_set[0]) && baud != baud_set[i].baud; i++); if (i==sizeof(baud_set)/sizeof(baud_set[0])) { SERIAL_MSG("uart%d, baud %d beyond rance\n", sw_uport->id, baud); return -1; } setsel = &baud_set[i]; if (port->uartclk < setsel->uartclk_min || port->uartclk > setsel->uartclk_max) { SERIAL_MSG("uart%d, select set %d, baud %d, uartclk %d beyond rance[%d, %d]\n", sw_uport->id, i, baud, port->uartclk, setsel->uartclk_min, setsel->uartclk_max); return -1; } } return 0; }
static int sw_uart_select_gpio_state(struct pinctrl *pctrl, char *name, u32 no) { int ret = 0; struct pinctrl_state *pctrl_state = NULL; pctrl_state = pinctrl_lookup_state(pctrl, name); if (IS_ERR(pctrl_state)) { SERIAL_MSG("UART%d pinctrl_lookup_state(%s) failed! return %p \n", no, name, pctrl_state); return -1; } ret = pinctrl_select_state(pctrl, pctrl_state); if (ret < 0) SERIAL_MSG("UART%d pinctrl_select_state(%s) failed! return %d \n", no, name, ret); return ret; }
static void __exit sunxi_uart_exit(void) { SERIAL_MSG("driver exit\n"); #ifdef CONFIG_SERIAL_SUNXI_CONSOLE unregister_console(&sw_console); #endif platform_driver_unregister(&sw_uport_platform_driver); uart_unregister_driver(&sw_uart_driver); }
static int __devinit sw_uart_probe(struct platform_device *pdev) { struct uart_port *port; struct sw_uart_port *sw_uport; int ret = -1; port = &sw_uart_ports[pdev->id].port; port->dev = &pdev->dev; sw_uport = UART_TO_SPORT(port); sw_uport->id = pdev->id; sw_uport->ier = 0; sw_uport->lcr = 0; sw_uport->mcr = 0; sw_uport->fcr = 0; sw_uport->dll = 0; sw_uport->dlh = 0; snprintf(sw_uport->name, 16, SUNXI_UART_DEV_NAME"%d", pdev->id); pdev->dev.init_name = sw_uport->name; SERIAL_DBG("uart.%d probe ... \n", pdev->id); /* request system resource and init them */ ret = sw_uart_request_resource(sw_uport, pdev->dev.platform_data); if (unlikely(ret)) { SERIAL_MSG("uart%d error to get resource\n", pdev->id); return -ENXIO; } port->uartclk = clk_get_rate(sw_uport->mclk); /* bug: clk_get_rate can't get s_uart clk rate in real-time, so set it to actual value */ #ifdef SUNXI_S_UART #ifdef CONFIG_ARCH_SUN8IW5P1 if (pdev->id == (SUNXI_UART_NUM - 1)) port->uartclk = 200000000; #endif #endif port->type = PORT_SUNXI; port->flags = UPF_BOOT_AUTOCONF; port->mapbase = sw_uport->pdata->base; port->irq = sw_uport->pdata->irq; port->line = sw_uport->pdata->port_no; platform_set_drvdata(pdev, port); SERIAL_DBG("add uart%d port, port_type %d, uartclk %d\n", pdev->id, port->type, port->uartclk); return uart_add_one_port(&sw_uart_driver, port); }
static int sw_uart_regulator_request(struct sw_uart_port* sw_uport, struct sw_uart_pdata *pdata) { struct regulator *regu = NULL; /* Consider "n***" as nocare. Support "none", "nocare", "null", "" etc. */ if ((pdata->regulator_id[0] == 'n') || (pdata->regulator_id[0] == 0)) return 0; regu = regulator_get(NULL, pdata->regulator_id); if (IS_ERR(regu)) { SERIAL_MSG("get regulator %s failed!\n", pdata->regulator_id); return -1; } pdata->regulator = regu; return 0; }
static int sw_uart_suspend(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); struct sw_uart_port *sw_uport = UART_TO_SPORT(port); if (port) { SERIAL_MSG("uart%d suspend\n", port->line); uart_suspend_port(&sw_uart_driver, port); if (SW_UART_NEED_SUSPEND(port)) { sw_uart_select_gpio_state(sw_uport->pctrl, PINCTRL_STATE_SUSPEND, sw_uport->id); sw_uart_regulator_disable(dev->platform_data); } } return 0; }
/** * Extrapolate a single point from its neighbors */ void Bed_level::extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir) { #if ENABLED(DEBUG_LEVELING_FEATURE) if (DEBUGGING(LEVELING)) { SERIAL_MSG("Extrapolate ["); if (x < 10) SERIAL_CHR(' '); SERIAL_VAL((int)x); SERIAL_CHR(xdir ? (xdir > 0 ? '+' : '-') : ' '); SERIAL_CHR(' '); if (y < 10) SERIAL_CHR(' '); SERIAL_VAL((int)y); SERIAL_CHR(ydir ? (ydir > 0 ? '+' : '-') : ' '); SERIAL_CHR(']'); } #endif if (!isnan(z_values[x][y])) { #if ENABLED(DEBUG_LEVELING_FEATURE) if (DEBUGGING(LEVELING)) SERIAL_EM(" (done)"); #endif return; // Don't overwrite good values. } SERIAL_EOL(); // Get X neighbors, Y neighbors, and XY neighbors const uint8_t x1 = x + xdir, y1 = y + ydir, x2 = x1 + xdir, y2 = y1 + ydir; float a1 = z_values[x1][y ], a2 = z_values[x2][y ], b1 = z_values[x ][y1], b2 = z_values[x ][y2], c1 = z_values[x1][y1], c2 = z_values[x2][y2]; // Treat far unprobed points as zero, near as equal to far if (isnan(a2)) a2 = 0.0; if (isnan(a1)) a1 = a2; if (isnan(b2)) b2 = 0.0; if (isnan(b1)) b1 = b2; if (isnan(c2)) c2 = 0.0; if (isnan(c1)) c1 = c2; const float a = 2 * a1 - a2, b = 2 * b1 - b2, c = 2 * c1 - c2; // Take the average instead of the median z_values[x][y] = (a + b + c) / 3.0; // Median is robust (ignores outliers). // z_values[x][y] = (a < b) ? ((b < c) ? b : (c < a) ? a : c) // : ((c < b) ? b : (a < c) ? a : c); }
void GCodeParser::debug() { SERIAL_MV("Command: ", command_ptr); SERIAL_MV(" (", command_letter); SERIAL_VAL(codenum); SERIAL_EM(")"); #if ENABLED(FASTER_GCODE_PARSER) SERIAL_MSG(" args: \""); for (char c = 'A'; c <= 'Z'; ++c) if (seen(c)) { SERIAL_CHR(c); SERIAL_CHR(' '); } #else SERIAL_MV(" args: \"", command_args); #endif SERIAL_MSG("\""); if (string_arg) { SERIAL_MSG(" string: \""); SERIAL_TXT(string_arg); SERIAL_CHR('"'); } SERIAL_MSG("\n\n"); for (char c = 'A'; c <= 'Z'; ++c) { if (seen(c)) { SERIAL_MV("Code '", c); SERIAL_MSG("':"); if (has_value()) { SERIAL_MV("\n float: ", value_float()); SERIAL_MV("\n long: ", value_long()); SERIAL_MV("\n ulong: ", value_ulong()); SERIAL_MV("\n millis: ", value_millis()); SERIAL_MV("\n sec-ms: ", value_millis_from_seconds()); SERIAL_MV("\n int: ", value_int()); SERIAL_MV("\n ushort: ", value_ushort()); SERIAL_MV("\n byte: ", (int)value_byte()); SERIAL_MV("\n bool: ", (int)value_bool()); SERIAL_MV("\n linear: ", value_linear_units()); SERIAL_MV("\n celsius: ", value_celsius()); } else SERIAL_MSG(" (no value)"); SERIAL_MSG("\n\n"); } } }
static int sw_uart_request_gpio(struct sw_uart_port *sw_uport) { #ifdef SUNXI_S_UART if (sw_uport->id == (SUNXI_UART_NUM - 1)) { /* use name s_uart0 to get pinctrl */ snprintf(sw_uport->name, 16, SUNXI_S_UART_DEV_NAME"%d", 0); } #endif sw_uport->pctrl = devm_pinctrl_get(sw_uport->port.dev); #ifdef SUNXI_S_UART if (sw_uport->id == (SUNXI_UART_NUM - 1)) { snprintf(sw_uport->name, 16, SUNXI_UART_DEV_NAME"%d", sw_uport->id); } #endif if (IS_ERR_OR_NULL(sw_uport->pctrl)) { SERIAL_MSG("UART%d devm_pinctrl_get() failed! return %ld\n", sw_uport->id, PTR_ERR(sw_uport->pctrl)); return -1; } return sw_uart_select_gpio_state(sw_uport->pctrl, PINCTRL_STATE_DEFAULT, sw_uport->id); }
static int sw_uart_get_devinfo(void) { u32 i; char uart_para[16] = {0}; struct sw_uart_pdata *pdata = NULL; script_item_u val = {0}; script_item_value_type_e type = 0; for (i=0; i<SUNXI_UART_NUM; i++) { pdata = &sw_uport_pdata[i]; sprintf(uart_para, SUNXI_UART_DEV_NAME"%d", i); /* get used information */ type = script_get_item(uart_para, "uart_used", &val); if (type != SCIRPT_ITEM_VALUE_TYPE_INT) { SERIAL_MSG("get uart%d's usedcfg failed\n", i); continue; } pdata->used = val.val; if (pdata->used == 0) continue; /* get type information */ type = script_get_item(uart_para, "uart_type", &val); if (type != SCIRPT_ITEM_VALUE_TYPE_INT) { SERIAL_MSG("get uart%d's type failed\n", i); return -1; } if (val.val > pdata->max_ios) { SERIAL_MSG("io type error: (%d > max_io_num %d)\n", val.val, pdata->max_ios); return -1; } pdata->io_num = val.val; /* get port information */ type = script_get_item(uart_para, "uart_port", &val); if (type != SCIRPT_ITEM_VALUE_TYPE_INT) { //SERIAL_MSG("get uart%d's port failed\n", i); pdata->port_no = i; } else pdata->port_no = val.val; type = script_get_item(uart_para, "uart_regulator", &val); if (SCIRPT_ITEM_VALUE_TYPE_STR != type) { SERIAL_MSG("uart%d has no uart_regulator.\n", i); continue; } strncpy(pdata->regulator_id, val.str, 16); } #ifdef SUNXI_S_UART do { pdata = &sw_uport_pdata[SUNXI_UART_NUM - 1]; sprintf(uart_para, SUNXI_S_UART_DEV_NAME"%d", 0); /* get used information */ type = script_get_item(uart_para, "s_uart_used", &val); if (type != SCIRPT_ITEM_VALUE_TYPE_INT) { SERIAL_MSG("get s_uart0 usedcfg failed\n"); continue; } if (val.val == 2) pdata->used = 1; pdata->io_num = gs_uart_io_num[SUNXI_UART_NUM - 1]; } while(0); #endif return 0; }
static void sw_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sw_uart_port *sw_uport = UART_TO_SPORT(port); unsigned long flags; unsigned int baud, quot, lcr = 0, dll, dlh; unsigned int lcr_fail = 0; SERIAL_DBG("set termios ...\n"); switch (termios->c_cflag & CSIZE) { case CS5: lcr |= SW_UART_LCR_WLEN5; break; case CS6: lcr |= SW_UART_LCR_WLEN6; break; case CS7: lcr |= SW_UART_LCR_WLEN7; break; case CS8: default: lcr |= SW_UART_LCR_WLEN8; break; } if (termios->c_cflag & CSTOPB) lcr |= SW_UART_LCR_STOP; if (termios->c_cflag & PARENB) lcr |= SW_UART_LCR_PARITY; if (!(termios->c_cflag & PARODD)) lcr |= SW_UART_LCR_EPAR; /* set buadrate */ baud = uart_get_baud_rate(port, termios, old, port->uartclk / 16 / 0xffff, port->uartclk / 16); sw_uart_check_baudset(port, baud); quot = uart_get_divisor(port, baud); dll = quot & 0xff; dlh = quot >> 8; SERIAL_DBG("set baudrate %d, quot %d\n", baud, quot); spin_lock_irqsave(&port->lock, flags); uart_update_timeout(port, termios->c_cflag, baud); /* Update the per-port timeout. */ port->read_status_mask = SW_UART_LSR_OE | SW_UART_LSR_THRE | SW_UART_LSR_DR; if (termios->c_iflag & INPCK) port->read_status_mask |= SW_UART_LSR_FE | SW_UART_LSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= SW_UART_LSR_BI; /* Characteres to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= SW_UART_LSR_PE | SW_UART_LSR_FE; if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= SW_UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= SW_UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= SW_UART_LSR_DR; /* * if lcr & baud are changed, reset controller to disable transfer */ if (lcr != sw_uport->lcr || dll != sw_uport->dll || dlh != sw_uport->dlh) { // SERIAL_DBG("LCR & BAUD changed, reset controller...\n"); sw_uart_reset(sw_uport); } sw_uport->dll = dll; sw_uport->dlh = dlh; /* flow control */ sw_uport->mcr &= ~SW_UART_MCR_AFE; if (termios->c_cflag & CRTSCTS) sw_uport->mcr |= SW_UART_MCR_AFE; serial_out(port, sw_uport->mcr, SW_UART_MCR); /* * CTS flow control flag and modem status interrupts */ sw_uport->ier &= ~SW_UART_IER_MSI; if (UART_ENABLE_MS(port, termios->c_cflag)) sw_uport->ier |= SW_UART_IER_MSI; serial_out(port, sw_uport->ier, SW_UART_IER); sw_uport->fcr = SW_UART_FCR_RXTRG_1_2 | SW_UART_FCR_TXTRG_1_2 | SW_UART_FCR_FIFO_EN; serial_out(port, sw_uport->fcr, SW_UART_FCR); sw_uport->lcr = lcr; serial_out(port, sw_uport->lcr|SW_UART_LCR_DLAB, SW_UART_LCR); if (serial_in(port, SW_UART_LCR) != (sw_uport->lcr|SW_UART_LCR_DLAB)) { lcr_fail = 1; } else { sw_uport->lcr = lcr; serial_out(port, sw_uport->dll, SW_UART_DLL); serial_out(port, sw_uport->dlh, SW_UART_DLH); serial_out(port, sw_uport->lcr, SW_UART_LCR); if (serial_in(port, SW_UART_LCR) != sw_uport->lcr) { lcr_fail = 2; } } #ifdef CONFIG_SW_UART_FORCE_LCR if (lcr_fail) { sw_uart_force_lcr(sw_uport, 50); serial_in(port, SW_UART_USR); } #endif /* clear rxfifo after set lcr & baud to discard redundant data */ serial_out(port, sw_uport->fcr|SW_UART_FCR_RXFIFO_RST, SW_UART_FCR); port->ops->set_mctrl(port, port->mctrl); /* Must save the current config for the resume of console(no tty user). */ if (sw_is_console_port(port)) port->cons->cflag = termios->c_cflag; spin_unlock_irqrestore(&port->lock, flags); /* lately output force lcr information */ if (lcr_fail == 1) { SERIAL_MSG("uart%d write LCR(pre-dlab) failed, lcr %x reg %x\n", sw_uport->id, sw_uport->lcr|(u32)SW_UART_LCR_DLAB, serial_in(port, SW_UART_LCR)); } else if (lcr_fail == 2) { SERIAL_MSG("uart%d write LCR(post-dlab) failed, lcr %x reg %x\n", sw_uport->id, sw_uport->lcr, serial_in(port, SW_UART_LCR)); } /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); SERIAL_DBG("termios lcr 0x%x fcr 0x%x mcr 0x%x dll 0x%x dlh 0x%x\n", sw_uport->lcr, sw_uport->fcr, sw_uport->mcr, sw_uport->dll, sw_uport->dlh); }
// Populate all fields by parsing a single line of GCode // 58 bytes of SRAM are used to speed up seen/value void GCodeParser::parse(char *p) { reset(); // No codes to report // Skip spaces while (*p == ' ') ++p; // Skip N[-0-9] if included in the command line if (*p == 'N' && NUMERIC_SIGNED(p[1])) { #if ENABLED(FASTER_GCODE_PARSER) //set('N', p + 1); // (optional) Set the 'N' parameter value #endif p += 2; // skip N[-0-9] while (NUMERIC(*p)) ++p; // skip [0-9]* while (*p == ' ') ++p; // skip [ ]* } // *p now points to the current command, which should be G, M, or T command_ptr = p; // Get the command letter, which must be G, M, or T const char letter = *p++; // Nullify asterisk and trailing whitespace char *starpos = strchr(p, '*'); if (starpos) { --starpos; // * while (*starpos == ' ') --starpos; // spaces... starpos[1] = '\0'; } // Bail if the letter is not G, M, or T switch (letter) { case 'G': case 'M': case 'T': break; default: return; } // Skip spaces to get the numeric part while (*p == ' ') p++; // Bail if there's no command code number if (!NUMERIC(*p)) return; // Save the command letter at this point // A '?' signifies an unknown command command_letter = letter; // Get the code number - integer digits only codenum = 0; do { codenum *= 10, codenum += *p++ - '0'; } while (NUMERIC(*p)); // Allow for decimal point in command #if USE_GCODE_SUBCODES if (*p == '.') { p++; while (NUMERIC(*p)) subcode *= 10, subcode += *p++ - '0'; } #endif // Skip all spaces to get to the first argument, or nul while (*p == ' ') p++; // The command parameters (if any) start here, for sure! #if DISABLED(FASTER_GCODE_PARSER) command_args = p; // Scan for parameters in seen() #endif // Only use string_arg for these M codes if (letter == 'M') switch (codenum) { case 23: case 28: case 30: case 117: case 118: case 928: string_arg = p; return; default: break; } #if ENABLED(DEBUG_GCODE_PARSER) const bool debug = codenum == 800; #endif /** * Find all parameters, set flags and pointers for fast parsing * * Most codes ignore 'string_arg', but those that want a string will get the right pointer. * The following loop assigns the first "parameter" having no numeric value to 'string_arg'. * This allows M0/M1 with expire time to work: "M0 S5 You Win!" */ string_arg = NULL; while (char code = *p++) { // Get the next parameter. A NUL ends the loop // Special handling for M32 [P] !/path/to/file.g# // The path must be the last parameter if (code == '!' && letter == 'M' && codenum == 32) { string_arg = p; // Name starts after '!' char * const lb = strchr(p, '#'); // Already seen '#' as SD char (to pause buffering) if (lb) *lb = '\0'; // Safe to mark the end of the filename return; } // Arguments MUST be uppercase for fast GCode parsing #if ENABLED(FASTER_GCODE_PARSER) #define PARAM_TEST WITHIN(code, 'A', 'Z') #else #define PARAM_TEST true #endif if (PARAM_TEST) { while (*p == ' ') p++; // skip spaces between parameters & values const bool has_num = DECIMAL_SIGNED(*p); // The parameter has a number [-+0-9.] #if ENABLED(DEBUG_GCODE_PARSER) if (debug) { SERIAL_MV("Got letter ", code); // DEBUG SERIAL_MV(" at index ", (int)(p - command_ptr - 1)); // DEBUG if (has_num) SERIAL_MSG(" (has_num)"); } #endif if (!has_num && !string_arg) { // No value? First time, keep as string_arg string_arg = p - 1; #if ENABLED(DEBUG_GCODE_PARSER) if (debug) SERIAL_MV(" string_arg: ", hex_address((void*)string_arg)); // DEBUG #endif } #if ENABLED(DEBUG_GCODE_PARSER) if (debug) SERIAL_EOL(); #endif #if ENABLED(FASTER_GCODE_PARSER) set(code, has_num ? p : NULL // Set parameter exists and pointer (NULL for no number) #if ENABLED(DEBUG_GCODE_PARSER) , debug #endif ); #endif } else if (!string_arg) { // Not A-Z? First time, keep as the string_arg string_arg = p - 1; #if ENABLED(DEBUG_GCODE_PARSER) if (debug) SERIAL_MV(" string_arg: ", hex_address((void*)string_arg)); // DEBUG #endif } if (!WITHIN(*p, 'A', 'Z')) { while (*p && NUMERIC(*p)) p++; // Skip over the value section of a parameter while (*p == ' ') p++; // Skip over all spaces } } }