现在的位置: 首页 > 综合 > 正文

uclinux内核的console(4):通过console输出信息

2013年09月20日 ⁄ 综合 ⁄ 共 4596字 ⁄ 字号 评论关闭

rev 0.2

 

快乐虾

http://blog.csdn.net/lights_joy/

lights@hb165.com

 

本文适用于

ADI bf561 DSP

优视BF561EVB开发板

uclinux-2008r1.5-rc3 (smp patch)

Visual DSP++ 5.0 (update 5)

 

欢迎转载,但请保留作者信息

 

在内核中,向console输出信息是通过release_console_sem函数来完成的:

/**

 * release_console_sem - unlock the console system

 *

 * Releases the semaphore which the caller holds on the console system

 * and the console driver list.

 *

 * While the semaphore was held, console output may have been buffered

 * by printk().  If this is the case, release_console_sem() emits

 * the output prior to releasing the semaphore.

 *

 * If there is output waiting for klogd, we wake it up.

 *

 * release_console_sem() may be called from any context.

 */

void release_console_sem(void)

{

     unsigned long flags;

     unsigned long _con_start, _log_end;

     unsigned long wake_klogd = 0;

 

     if (console_suspended) {

         up(&secondary_console_sem);

         return;

     }

 

     console_may_schedule = 0;

 

     for ( ; ; ) {

         spin_lock_irqsave(&logbuf_lock, flags);

         wake_klogd |= log_start - log_end;

         if (con_start == log_end)

              break;             /* Nothing to print */

         _con_start = con_start;

         _log_end = log_end;

         con_start = log_end;        /* Flush */

         spin_unlock(&logbuf_lock);

         call_console_drivers(_con_start, _log_end);

         local_irq_restore(flags);

     }

     console_locked = 0;

     up(&console_sem);

     spin_unlock_irqrestore(&logbuf_lock, flags);

     if (wake_klogd)

         wake_up_klogd();

}

在这里,实际输出通过call_console_drivers函数完成:

/*

 * Call the console drivers, asking them to write out

 * log_buf[start] to log_buf[end - 1].

 * The console_sem must be held.

 */

static void call_console_drivers(unsigned long start, unsigned long end)

{

     unsigned long cur_index, start_print;

     static int msg_level = -1;

 

     BUG_ON(((long)(start - end)) > 0);

 

     cur_index = start;

     start_print = start;

     while (cur_index != end) {

         if (msg_level < 0 && ((end - cur_index) > 2) &&

                   LOG_BUF(cur_index + 0) == '<' &&

                   LOG_BUF(cur_index + 1) >= '0' &&

                   LOG_BUF(cur_index + 1) <= '7' &&

                   LOG_BUF(cur_index + 2) == '>') {

              msg_level = LOG_BUF(cur_index + 1) - '0';

              cur_index += 3;

              start_print = cur_index;

         }

         while (cur_index != end) {

              char c = LOG_BUF(cur_index);

 

              cur_index++;

              if (c == '/n') {

                   if (msg_level < 0) {

                       /*

                        * printk() has already given us loglevel tags in

                        * the buffer.  This code is here in case the

                        * log buffer has wrapped right round and scribbled

                        * on those tags

                        */

                       msg_level = default_message_loglevel;

                   }

                   _call_console_drivers(start_print, cur_index, msg_level);

                   msg_level = -1;

                   start_print = cur_index;

                   break;

              }

         }

     }

     _call_console_drivers(start_print, end, msg_level);

}

继续跟踪_call_console_drivers

/*

 * Write out chars from start to end - 1 inclusive

 */

static void _call_console_drivers(unsigned long start,

                   unsigned long end, int msg_log_level)

{

     if ((msg_log_level < console_loglevel || ignore_loglevel) &&

              console_drivers && start != end) {

         if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {

              /* wrapped write */

              __call_console_drivers(start & LOG_BUF_MASK,

                            log_buf_len);

              __call_console_drivers(0, end & LOG_BUF_MASK);

         } else {

              __call_console_drivers(start, end);

         }

     }

}

继续跟踪__call_console_drivers

/*

 * Call the console drivers on a range of log_buf

 */

static void __call_console_drivers(unsigned long start, unsigned long end)

{

     struct console *con;

 

     for (con = console_drivers; con; con = con->next) {

         if ((con->flags & CON_ENABLED) && con->write &&

                   (cpu_online(smp_processor_id()) ||

                   (con->flags & CON_ANYTIME)))

              con->write(con, &LOG_BUF(start), end - start);

     }

}

嘿嘿,原来是调用console结构体中的write函数!记得我们在内核中是使用了bfin_serial_console做为我们的console,而这个结构体中的write回调函数则初始化为bfin_serial_console_write,这个函数在drivers/serial/bfin_5xx.c

/*

 * Interrupts are disabled on entering

 */

static void

bfin_serial_console_write(struct console *co, const char *s, unsigned int count)

{

     struct bfin_serial_port *uart = &bfin_serial_ports[co->index];

     int flags = 0;

 

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

     uart_console_write(&uart->port, s, count, bfin_serial_console_putchar);

     spin_unlock_irqrestore(&uart->port.lock, flags);

}

再跟踪uart_console_write此函数位于drivers/serial/serial_core.c

/*

 *   uart_console_write - write a console message to a serial port

 *   @port: the port to write the message

 *   @s: array of characters

 *   @count: number of characters in string to write

 *   @write: function to write character to port

 */

void

抱歉!评论已关闭.