调试tty发送的日志问题

tty调试时,在串口终端发送数据流程调用 printk会导致死机 

解决办法


struct mid8250 {
    int line;
    int dma_index;
    struct pci_dev *dma_dev;
    struct uart_8250_dma dma;
    struct mid8250_board *board;
    struct hsu_dma_chip dma_chip;
    void *mid8250_private_data;
    int index;
    int log_cnt;
};


int store_to_buff( struct mid8250 *mid, const char *format, ... )
{   
    unsigned char buffer[2048];
    va_list  vArgs;
    va_start(vArgs, format);
    vsnprintf((char *)buffer, sizeof(buffer), (char const *)format, vArgs);
    va_end(vArgs);
                         
    strcpy( &mid->mid8250_private_data[mid->index], buffer );
    mid->index = mid->index + strlen(buffer) + 1;
    mid->log_cnt++;
    return 0;
}

static void __dma_tx_complete(void *param)
{
    struct uart_8250_port    *p = param;
    struct uart_8250_dma    *dma = p->dma;
    struct circ_buf        *xmit = &p->port.state->xmit;
    unsigned long    flags;
    int        ret;
    int retval;

    struct uart_port *uport;
    struct mid8250 *mid;

    uport = &p->port;

    mid = uport->private_data;
    if (!mid){
        //return;
    }


    //*(unsigned int *)mid->mid8250_private_data = 0x56789;

    
    //seq_printf(m, "mid->mid8250_private_data[0] = 0x%x\n", *(unsigned int *)mid->mid8250_private_data );

扫描二维码关注公众号,回复: 8635870 查看本文章


    //store_to_buff(mid, "in __dma_tx_complete\n" );
    
    

    

    dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
                UART_XMIT_SIZE, DMA_TO_DEVICE);

    spin_lock_irqsave(&p->port.lock, flags);


    //pr_info( "in __dma_tx_complete\n" );
    

    dma->tx_running = 0;

    xmit->tail += dma->tx_size;
    xmit->tail &= UART_XMIT_SIZE - 1;
    p->port.icount.tx += dma->tx_size;

    if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS){
        //store_to_buff(mid, "__dma_tx_complete.1\n" );
        uart_write_wakeup(&p->port);
    }

    ret = serial8250_tx_dma(p);
    if (ret) {
        store_to_buff(mid, "__dma_tx_complete.2\n" );
        p->ier |= UART_IER_THRI;
        serial_port_out(&p->port, UART_IER, p->ier);
    }
    //store_to_buff(mid, "__dma_tx_complete.3\n" );
    spin_unlock_irqrestore(&p->port.lock, flags);
}
 


static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
    struct uart_8250_port uart;
    struct mid8250 *mid;
    unsigned int bar;
    int ret;


    
    //printk(KERN_ERR "in mid8250_probe123\n");
        

    
    ret = pcim_enable_device(pdev);
    if (ret)
        return ret;


    //printk(KERN_ERR "sizeof(*mid) = %d\n", sizeof(*mid) );

    

    mid = devm_kzalloc(&pdev->dev, sizeof(*mid), GFP_KERNEL);
    if (!mid)
        return -ENOMEM;

    mid->mid8250_private_data = devm_kzalloc(&pdev->dev, 0x100000, GFP_KERNEL);
    if (!mid->mid8250_private_data)
        return -ENOMEM;
    

    

    

    printk(KERN_ERR "&dnv_board = 0x%llx\n", &dnv_board );
    printk(KERN_ERR "id->driver_data = 0x%llx\n", id->driver_data );
    printk(KERN_ERR "mid->mid8250_private_data = 0x%llx\n", mid->mid8250_private_data );


    printk(KERN_ERR "mid = 0x%llx\n", mid );
    
    
    *(unsigned int *)mid->mid8250_private_data = 0x11223344;
    printk(KERN_ERR "mid->mid8250_private_data[0] = 0x%x\n", *(unsigned int *)mid->mid8250_private_data );

    mid->board = (struct mid8250_board *)id->driver_data;
    bar = FL_GET_BASE(mid->board->flags);

    memset(&uart, 0, sizeof(struct uart_8250_port));

    uart.port.dev = &pdev->dev;
    uart.port.irq = pdev->irq;
    uart.port.private_data = mid;
    uart.port.type = PORT_16750;
    uart.port.iotype = UPIO_MEM;
    uart.port.uartclk = mid->board->base_baud * 16;
    uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
    uart.port.set_termios = mid8250_set_termios;

    uart.port.mapbase = pci_resource_start(pdev, bar);
    uart.port.membase = pcim_iomap(pdev, bar, 0);
    if (!uart.port.membase)
        return -ENOMEM;

    if (mid->board->setup) {
        ret = mid->board->setup(mid, &uart.port);
        if (ret)
            return ret;
    }

    ret = mid8250_dma_setup(mid, &uart);
    if (ret)
        goto err;

    ret = serial8250_register_8250_port(&uart);
    if (ret < 0)
        goto err;

    mid->line = ret;

    pci_set_drvdata(pdev, mid);
    return 0;
err:
    if (mid->board->exit)
        mid->board->exit(mid);
    return ret;
}


static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
{
    struct uart_state *state = drv->state + i;
    struct tty_port *port = &state->port;
    enum uart_pm_state pm_state;
    struct uart_port *uport;
    char stat_buf[32];
    unsigned int status;
    int mmio;
    struct mid8250 *mid;
    int j,index;
    char *p_index;

    mutex_lock(&port->mutex);
    uport = uart_port_check(state);
    if (!uport)
        goto out;


    if( i != 5 ){
        goto out;
    }
    
    seq_printf(m, "uport->name = %s\n", uport->name  );
    seq_printf(m, "i = %d\n", i  );
    seq_printf(m, "uport->private_data = %llx\n", uport->private_data  );
    mid = uport->private_data;
    if (!mid){
        goto out;
    }
    seq_printf(m, "mid->mid8250_private_data[0] = 0x%x\n", *(unsigned int *)mid->mid8250_private_data );

    index = 0x00;
    p_index = (char *)mid->mid8250_private_data;
    seq_printf(m, "mid->index = 0x%x\n", mid->index );
    
    for( j=0x00; j<mid->log_cnt; j++ ){ 
         seq_printf(m, "%s", p_index );
         index = strlen(p_index);
         p_index = p_index + index + 1;
    }
    //macdbg_dmphex(mid->mid8250_private_data,200,m);

    
    

    mmio = uport->iotype >= UPIO_MEM;
    seq_printf(m, "%d: uart:%s %s%08llX irq:%d",
            uport->line, uart_type(uport),
            mmio ? "mmio:0x" : "port:",
            mmio ? (unsigned long long)uport->mapbase
                 : (unsigned long long)uport->iobase,
            uport->irq);

    if (uport->type == PORT_UNKNOWN) {
        seq_putc(m, '\n');
        goto out;
    }

    if (capable(CAP_SYS_ADMIN)) {
        pm_state = state->pm_state;
        if (pm_state != UART_PM_STATE_ON)
            uart_change_pm(state, UART_PM_STATE_ON);
        spin_lock_irq(&uport->lock);
        status = uport->ops->get_mctrl(uport);
        spin_unlock_irq(&uport->lock);
        if (pm_state != UART_PM_STATE_ON)
            uart_change_pm(state, pm_state);

        seq_printf(m, " tx:%d rx:%d",
                uport->icount.tx, uport->icount.rx);
        if (uport->icount.frame)
            seq_printf(m, " fe:%d",    uport->icount.frame);
        if (uport->icount.parity)
            seq_printf(m, " pe:%d",    uport->icount.parity);
        if (uport->icount.brk)
            seq_printf(m, " brk:%d", uport->icount.brk);
        if (uport->icount.overrun)
            seq_printf(m, " oe:%d", uport->icount.overrun);

#define INFOBIT(bit, str) \
    if (uport->mctrl & (bit)) \
        strncat(stat_buf, (str), sizeof(stat_buf) - \
            strlen(stat_buf) - 2)
#define STATBIT(bit, str) \
    if (status & (bit)) \
        strncat(stat_buf, (str), sizeof(stat_buf) - \
               strlen(stat_buf) - 2)

        stat_buf[0] = '\0';
        stat_buf[1] = '\0';
        INFOBIT(TIOCM_RTS, "|RTS");
        STATBIT(TIOCM_CTS, "|CTS");
        INFOBIT(TIOCM_DTR, "|DTR");
        STATBIT(TIOCM_DSR, "|DSR");
        STATBIT(TIOCM_CAR, "|CD");
        STATBIT(TIOCM_RNG, "|RI");
        if (stat_buf[0])
            stat_buf[0] = ' ';

        seq_puts(m, stat_buf);
    }
    seq_putc(m, '\n');
#undef STATBIT
#undef INFOBIT
out:
    mutex_unlock(&port->mutex);
}


u8 * g_debug_buff;
int g_debug_buff_index;
#define macdbg_prser Ser_Printf

//#define Ser_WrStr do{ LOGI("%s", buffer); }while(0)
int g_printf_switch = 0x01;
int Ser_Printf (const char *format, ...)
{   
    unsigned char buffer[80 + 1];
    va_list  vArgs;
    if( g_printf_switch == 0x00 ){
        return 1;
    }
    va_start(vArgs, format);
    vsnprintf((char *)buffer, sizeof(buffer), (char const *)format, vArgs);
    va_end(vArgs);
    //Ser_WrStr;
    strcpy( &g_debug_buff[g_debug_buff_index], buffer );
    g_debug_buff_index = g_debug_buff_index + strlen(buffer);
    return 0;
}


int macdbg_dmphex(const char* buff, int len, struct seq_file *m)
{
    int retval = 0; 
    int x, y, tot, lineoff;
    const char* curr;
    
    g_debug_buff = kzalloc(1024, GFP_KERNEL);
    if (!g_debug_buff){
        return NULL;
    }
    
    lineoff = 0;
    curr = buff;
    tot = 0;
    for( x = 0; x+16 < len; ){  
         memset( g_debug_buff, 0x00, 1024 );
         g_debug_buff_index = 0x00;
         Ser_Printf("%x\t", lineoff);
         for( y = 0; y < 16; y++ ){
              macdbg_prser("%02x ", (unsigned char)*(curr + y));
         }
         macdbg_prser("  ");
         for( y = 0; y < 16; y++ ){
              char c;
              c = *(curr + y);
              if( c > 31 && c < 127 ){
                  macdbg_prser("%c", c);
              }else{
                  macdbg_prser("%c", '.');
              }
              tot++;
         }
         curr += 16;
         x += 16;
         lineoff+=16;
         //macdbg_prser("\r\n");
         //print_log( "%s", g_debug_buff );

         seq_printf(m, "%s", g_debug_buff );
         seq_putc(m, '\n');
         
    }
    
    //do last line
    //Ser_Printf( "tot %d.\r\n", tot );                   
    //Ser_Printf( "len %d.\r\n", len );                                                                                                            
    memset( g_debug_buff, 0x00, 1024 );
    g_debug_buff_index = 0x00;     
    if( tot < len ){
        curr = (buff + tot);
        macdbg_prser("%x\t", lineoff);
        for( y = 0; y < (len - tot); y++ ){
             macdbg_prser("%02x ", (unsigned char)*(curr + y));
        }
        //padding with spaces
        //Ser_Printf("(len - tot) %d.\r\n", (len - tot) );
        if( (len - tot) < 16 ){
            for( y = 0; y < (32 - ((len - tot)*2)); y++ ){
                 macdbg_prser(" ");
            }
        }
        for( y = 0; y < 16-(len - tot); y++ ){
             macdbg_prser(" ");
        }
        macdbg_prser("  "); 
       //Ser_Printf("(len - tot) %d.\r\n", (len - tot) );
        for( y = 0; y < (len - tot); y++ ){
            char c;
            c = *(curr + y);
            if( c >31 && c < 127 ){
                macdbg_prser("%c", c);
            }else{
                macdbg_prser("%c", '.');
            }
        }
    }
    //macdbg_prser("\r\n");
    seq_printf(m, "%s", g_debug_buff );
    seq_putc(m, '\n');
    
    kfree(g_debug_buff);
    return retval;
}      

#ifndef __8250_H__
#define __8250_H__

#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
#include <linux/dmaengine.h>

#include <linux/dma/hsu.h>
//#include <linux/8250_pci.h>

struct uart_8250_dma {
    int (*tx_dma)(struct uart_8250_port *p);
    int (*rx_dma)(struct uart_8250_port *p);

    /* Filter function */
    dma_filter_fn        fn;
    /* Parameter to the filter function */
    void            *rx_param;
    void            *tx_param;

    struct dma_slave_config    rxconf;
    struct dma_slave_config    txconf;

    struct dma_chan        *rxchan;
    struct dma_chan        *txchan;

    /* Device address base for DMA operations */
    phys_addr_t        rx_dma_addr;
    phys_addr_t        tx_dma_addr;

    /* DMA address of the buffer in memory */
    dma_addr_t        rx_addr;
    dma_addr_t        tx_addr;

    dma_cookie_t        rx_cookie;
    dma_cookie_t        tx_cookie;

    void            *rx_buf;

    size_t            rx_size;
    size_t            tx_size;

    unsigned char        tx_running;
    unsigned char        tx_err;
    unsigned char        rx_running;
};

struct old_serial_port {
    unsigned int uart;
    unsigned int baud_base;
    unsigned int port;
    unsigned int irq;
    upf_t        flags;
    unsigned char io_type;
    unsigned char __iomem *iomem_base;
    unsigned short iomem_reg_shift;
};

struct serial8250_config {
    const char    *name;
    unsigned short    fifo_size;
    unsigned short    tx_loadsz;
    unsigned char    fcr;
    unsigned char    rxtrig_bytes[UART_FCR_R_TRIG_MAX_STATE];
    unsigned int    flags;
};

#define UART_CAP_FIFO    (1 << 8)    /* UART has FIFO */
#define UART_CAP_EFR    (1 << 9)    /* UART has EFR */
#define UART_CAP_SLEEP    (1 << 10)    /* UART has IER sleep */
#define UART_CAP_AFE    (1 << 11)    /* MCR-based hw flow control */
#define UART_CAP_UUE    (1 << 12)    /* UART needs IER bit 6 set (Xscale) */
#define UART_CAP_RTOIE    (1 << 13)    /* UART needs IER bit 4 set (Xscale, Tegra) */
#define UART_CAP_HFIFO    (1 << 14)    /* UART has a "hidden" FIFO */
#define UART_CAP_RPM    (1 << 15)    /* Runtime PM is active while idle */
#define UART_CAP_IRDA    (1 << 16)    /* UART supports IrDA line discipline */
#define UART_CAP_MINI    (1 << 17)    /* Mini UART on BCM283X family lacks:
                     * STOP PARITY EPAR SPAR WLEN5 WLEN6
                     */

#define UART_BUG_QUOT    (1 << 0)    /* UART has buggy quot LSB */
#define UART_BUG_TXEN    (1 << 1)    /* UART has buggy TX IIR status */
#define UART_BUG_NOMSR    (1 << 2)    /* UART has buggy MSR status bits (Au1x00) */
#define UART_BUG_THRE    (1 << 3)    /* UART has buggy THRE reassertion */
#define UART_BUG_PARITY    (1 << 4)    /* UART mishandles parity if FIFO enabled */


#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
#define SERIAL8250_SHARE_IRQS 1
#else
#define SERIAL8250_SHARE_IRQS 0
#endif

#define SERIAL8250_PORT_FLAGS(_base, _irq, _flags)        \
    {                            \
        .iobase        = _base,            \
        .irq        = _irq,                \
        .uartclk    = 1843200,            \
        .iotype        = UPIO_PORT,            \
        .flags        = UPF_BOOT_AUTOCONF | (_flags),    \
    }

#define SERIAL8250_PORT(_base, _irq) SERIAL8250_PORT_FLAGS(_base, _irq, 0)


static inline int serial_in(struct uart_8250_port *up, int offset)
{
    return up->port.serial_in(&up->port, offset);
}

static inline void serial_out(struct uart_8250_port *up, int offset, int value)
{
    up->port.serial_out(&up->port, offset, value);
}

void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p);

static inline int serial_dl_read(struct uart_8250_port *up)
{
    return up->dl_read(up);
}

static inline void serial_dl_write(struct uart_8250_port *up, int value)
{
    up->dl_write(up, value);
}

struct uart_8250_port *serial8250_get_port(int line);

void serial8250_rpm_get(struct uart_8250_port *p);
void serial8250_rpm_put(struct uart_8250_port *p);

void serial8250_rpm_get_tx(struct uart_8250_port *p);
void serial8250_rpm_put_tx(struct uart_8250_port *p);

int serial8250_em485_init(struct uart_8250_port *p);
void serial8250_em485_destroy(struct uart_8250_port *p);

static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)
{
    serial_out(up, UART_MCR, value);
}

static inline int serial8250_in_MCR(struct uart_8250_port *up)
{
    return serial_in(up, UART_MCR);
}

#if defined(__alpha__) && !defined(CONFIG_PCI)
/*
 * Digital did something really horribly wrong with the OUT1 and OUT2
 * lines on at least some ALPHA's.  The failure mode is that if either
 * is cleared, the machine locks up with endless interrupts.
 */
#define ALPHA_KLUDGE_MCR  (UART_MCR_OUT2 | UART_MCR_OUT1)
#else
#define ALPHA_KLUDGE_MCR 0
#endif

#ifdef CONFIG_SERIAL_8250_PNP
int serial8250_pnp_init(void);
void serial8250_pnp_exit(void);
#else
static inline int serial8250_pnp_init(void) { return 0; }
static inline void serial8250_pnp_exit(void) { }
#endif

#ifdef CONFIG_SERIAL_8250_FINTEK
int fintek_8250_probe(struct uart_8250_port *uart);
#else
static inline int fintek_8250_probe(struct uart_8250_port *uart) { return 0; }
#endif

#ifdef CONFIG_ARCH_OMAP1
static inline int is_omap1_8250(struct uart_8250_port *pt)
{
    int res;

    switch (pt->port.mapbase) {
    case OMAP1_UART1_BASE:
    case OMAP1_UART2_BASE:
    case OMAP1_UART3_BASE:
        res = 1;
        break;
    default:
        res = 0;
        break;
    }

    return res;
}

static inline int is_omap1510_8250(struct uart_8250_port *pt)
{
    if (!cpu_is_omap1510())
        return 0;

    return is_omap1_8250(pt);
}
#else
static inline int is_omap1_8250(struct uart_8250_port *pt)
{
    return 0;
}
static inline int is_omap1510_8250(struct uart_8250_port *pt)
{
    return 0;
}
#endif

#ifdef CONFIG_SERIAL_8250_DMA
extern int serial8250_tx_dma(struct uart_8250_port *);
extern int serial8250_rx_dma(struct uart_8250_port *);
extern void serial8250_rx_dma_flush(struct uart_8250_port *);
extern int serial8250_request_dma(struct uart_8250_port *);
extern void serial8250_release_dma(struct uart_8250_port *);
#else
static inline int serial8250_tx_dma(struct uart_8250_port *p)
{
    return -1;
}
static inline int serial8250_rx_dma(struct uart_8250_port *p)
{
    return -1;
}
static inline void serial8250_rx_dma_flush(struct uart_8250_port *p) { }
static inline int serial8250_request_dma(struct uart_8250_port *p)
{
    return -1;
}
static inline void serial8250_release_dma(struct uart_8250_port *p) { }
#endif

static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
{
    unsigned char status;

    status = serial_in(up, 0x04); /* EXCR2 */
#define PRESL(x) ((x) & 0x30)
    if (PRESL(status) == 0x10) {
        /* already in high speed mode */
        return 0;
    } else {
        status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
        status |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
        serial_out(up, 0x04, status);
    }
    return 1;
}

static inline int serial_index(struct uart_port *port)
{
    return port->minor - 64;
}

struct mid8250;

struct mid8250_board {
    unsigned int flags;
    unsigned long freq;
    unsigned int base_baud;
    int (*setup)(struct mid8250 *, struct uart_port *p);
    void (*exit)(struct mid8250 *);
};

struct mid8250 {
    int line;
    int dma_index;
    struct pci_dev *dma_dev;
    struct uart_8250_dma dma;
    struct mid8250_board *board;
    struct hsu_dma_chip dma_chip;
    void *mid8250_private_data;
    int index;
    int log_cnt;
};

#endif
 

发布了136 篇原创文章 · 获赞 19 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/dp__mcu/article/details/103999972
tty