其实到这里,只要能保证编译通过,再修改一下链接脚本,其实已经可以跑在at9260的系统上了。因为我没有仿真器,不知道程序的状态,所以必须撰写调试串口的驱动。

RTEMS 的调试串口并没有采用中断输出的方式,而是采用查询输出的方式。相对来说比较容易。

RTEMS里有两个打印函数:

printf 和 printk

printf是由库支持的打印函数,内部比较复杂,主要用于应用程序级别的打印,不能用于内核和中断的打印,特别是中断中不能使用该函数,否则会引起死机。

printk是由rtems的调试打印函数,主要用于内核和中断的打印。任务级别也可以调用,但是最好不要这样做。

printk是调用 BSP_output_char 这个函数指针完成字符的输出。

可以在c/src/lib/lbicpu/arm/at91sam9260/dbgu/Dbgu.c中的末尾的

static void _BSP_put_char( char c ) {
    dbgu_write_polled(0, c);
}

BSP_output_char_function_type BSP_output_char = _BSP_put_char;

那么就是说,printk实际上是调用调试串口驱动完成字符的输出。

既然调用调试串口输出,必须等调试串口初始化完成以后才能输出。

start.S执行完毕后,是跳转到 bootcard 函数中继续执行,bootcard 要完成对内核数据的初始化后,才调用IO的初始化,这时串口的驱动才能工作。也就是说,想在bootcard运行调试串口初始化以前,看到printk的输出,基本上是不可能的。

如果你真的想这个时候也能看到printk的输出,只能提前初始化串口驱动了。

我的做法是,dbgu_write 函数内部会检查调试串口有没有被初始化,如果没有被初始化,先初始化再输出字符。那么这样,即使在start.S汇编文件里调用printk,也是能看到输出的。

这里还要注意一个问题就是调试串口的波特率,调试串口的波特率是通过函数BSP_get_baud获得,

这个函数在c/src/lib/libbsp/arm/at9260/include/bsp.h中。

另外就是修改 c/src/lib/libbsp/arm/at9260/console/uarts.c的代码。

这里的改动主要是一些配置和寄存器,没有什么好讲的。

下面是dbgu.c的源代码:

/* * Console driver for AT91SAM9260 DBGU port * */ #include <bsp.h> #include <rtems/libio.h> #include <termios.h> #include <at91sam9260.h> #include <rtems/bspIo.h> #include <libchip/serial.h> #include <libchip/sersupp.h> #define AT91SAM9260_DBGU_NUM 1 static volatile int _gIsInitDbgu[AT91SAM9260_DBGU_NUM] = {0}; volatile int dbg_dly; /* static function prototypes */ static int dbgu_first_open(int major, int minor, void *arg); static int dbgu_last_close(int major, int minor, void *arg); static int dbgu_read(int minor); static int dbgu_write(int minor, const char *buf, int len); static void dbgu_init(int minor); static void dbgu_write_polled(int minor, char c); static int dbgu_set_attributes(int minor, const struct termios *t); /* Pointers to functions for handling the UART. */ console_fns dbgu_fns = { libchip_serial_default_probe, dbgu_first_open, dbgu_last_close, dbgu_read, dbgu_write, dbgu_init, dbgu_write_polled, /* not used in this driver */ dbgu_set_attributes, FALSE /* TRUE if interrupt driven, FALSE if not. */ }; /*********************************************************************/ /* Functions called via callbacks (i.e. the ones in uart_fns */ /*********************************************************************/ /* * This is called the first time each device is opened. Since * the driver is polled, we don't have to do anything. If the driver * were interrupt driven, we'd enable interrupts here. */ static int dbgu_first_open(int major, int minor, void *arg) { return 0; } /* * This is called the last time each device is closed. Since * the driver is polled, we don't have to do anything. If the driver * were interrupt driven, we'd disable interrupts here. */ static int dbgu_last_close(int major, int minor, void *arg) { return 0; } /* * Read one character from UART. * * return -1 if there's no data, otherwise return * the character in lowest 8 bits of returned int. */ static int dbgu_read(int minor) { char c; console_tbl *console_entry; AT91S_DBGU *dbgu; if ((minor < AT91SAM9260_DBGU_NUM) && (0 == _gIsInitDbgu[minor])) dbgu_init(minor); console_entry = BSP_get_uart_from_minor(minor); if (console_entry == NULL) { return -1; } dbgu = (AT91S_DBGU *)console_entry->ulCtrlPort1; if (!(dbgu->DBGU_CSR & AT91C_US_RXRDY)) { return -1; } c = dbgu->DBGU_RHR & 0xff; return c; } /* * Write buffer to UART * * return 1 on success, -1 on error */ static int dbgu_write(int minor, const char *buf, int len) { int i, x; char c; console_tbl *console_entry; AT91S_DBGU *dbgu; if ((minor < AT91SAM9260_DBGU_NUM) && (0 == _gIsInitDbgu[minor])) dbgu_init(minor); console_entry = BSP_get_uart_from_minor(minor); if (console_entry == NULL) { return -1; } dbgu = (AT91S_DBGU *)console_entry->ulCtrlPort1; for (i = 0; i < len; i++) { /* Wait for fifo to have room */ while(1) { if (dbgu->DBGU_CSR & AT91C_US_TXRDY) { break; } } c = (char) buf[i]; dbgu->DBGU_THR = c; /* the TXRDY flag does not seem to update right away (is this true?) */ /* so we wait a bit before continuing */ for (x = 0; x < 10; x++) { dbg_dly++; /* using a global so this doesn't get optimized out */ } } return 1; } /* Set up the UART. */ static void dbgu_init(int minor) { console_tbl *console_entry; AT91S_DBGU *dbgu; if ((minor >= AT91SAM9260_DBGU_NUM) || (_gIsInitDbgu[minor] > 0)) return ; console_entry = BSP_get_uart_from_minor(minor); if (console_entry == NULL) { return; } _gIsInitDbgu[minor] = 1; dbgu = (AT91S_DBGU *)console_entry->ulCtrlPort1; AT91C_BASE_PIOB->PIO_IDR = (1<<14) | (1<<15); AT91C_BASE_PIOB->PIO_ASR = (1<<14) | (1<<15); AT91C_BASE_PIOB->PIO_BSR = 0; AT91C_BASE_PIOB->PIO_PDR = (1<<14) | (1<<15); AT91C_BASE_PIOB->PIO_PPUDR = (1<<14) | (1<<15); /* Clear error bits, and reset */ dbgu->DBGU_CR = (AT91C_US_RSTSTA | AT91C_US_RSTTX | AT91C_US_RSTRX); /* Clear pending interrupts */ dbgu->DBGU_IDR = (AT91C_US_RXRDY | AT91C_US_TXRDY | AT91C_US_ENDRX | AT91C_US_ENDTX | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_TXEMPTY | AT91C_US_TXBUFE | AT91C_US_RXBUFF | AT91C_US_COMM_TX | AT91C_US_COMM_RX); dbgu->DBGU_IMR = 0; /* Set port to no parity, no loopback */ dbgu->DBGU_MR = AT91C_US_PAR_NONE | AT91C_US_CHMODE_NORMAL; /* Set the baud rate */ dbgu->DBGU_BRGR = (at91sam9260_get_mck() / 16) / BSP_get_baud(); /* Enable the DBGU */ dbgu->DBGU_CR = (AT91C_US_RXEN | AT91C_US_TXEN); } /* I'm not sure this is needed for the shared console driver. */ static void dbgu_write_polled(int minor, char c) { dbgu_write(minor, &c, 1); } /* This is for setting baud rate, bits, etc. */ static int dbgu_set_attributes(int minor, const struct termios *t) { return 0; } /***********************************************************************/ /* * The following functions are not used by TERMIOS, but other RTEMS * functions use them instead. */ /***********************************************************************/ /* * Read from UART. This is used in the exit code, and can't * rely on interrupts. */ int dbgu_poll_read(int minor) { return dbgu_read(minor); } /* * Write a character to the console. This is used by printk() and * maybe other low level functions. It should not use interrupts or any * RTEMS system calls. It needs to be very simple */ static void _BSP_put_char( char c ) { dbgu_write_polled(0, c); } BSP_output_char_function_type BSP_output_char = _BSP_put_char;

下面是uarts.c的代码:

/* * Console driver for AT9260 * * This driver uses the shared console driver in * ...../libbsp/shared/console.c * */ #include <bsp.h> #include <rtems/libio.h> #include <termios.h> #include <rtems/bspIo.h> #include <at91sam9260.h> #include <libchip/serial.h> #include <libchip/sersupp.h> /* How many serial ports? */ #define NUM_DEVS 1 /* These are used by code in console.c */ unsigned long Console_Port_Count = NUM_DEVS; console_data Console_Port_Data[NUM_DEVS]; /* rtems console uses the following minor number */ rtems_device_minor_number Console_Port_Minor = 0; extern console_fns dbgu_fns; /* * There's one item in array for each UART. * * Some of these fields are marked "NOT USED". They are not used * by console.c, but may be used by drivers in libchip * * when we add other types of UARTS we will need to move this * structure to a generic uart.c file with only this in it */ console_tbl Console_Port_Tbl[] = { { "/dev/console", /* sDeviceName */ SERIAL_CUSTOM, /* deviceType */ &dbgu_fns, /* pDeviceFns */ NULL, /* deviceProbe */ NULL, /* pDeviceFlow */ 0, /* ulMargin - NOT USED */ 0, /* ulHysteresis - NOT USED */ NULL, /* pDeviceParams */ AT91C_BASE_DBGU, /* ulCtrlPort1 - Pointer to DBGU regs */ 0, /* ulCtrlPort2 - NOT USED */ 0, /* ulDataPort - NOT USED */ NULL, /* getRegister - NOT USED */ NULL, /* setRegister - NOT USED */ NULL, /* getData - NOT USED */ NULL, /* setData - NOT USED */ 0, /* ulClock - NOT USED */ 0 /* ulIntVector - NOT USED */ }}; console_tbl *BSP_get_uart_from_minor(int minor) { return &Console_Port_Tbl[minor]; }

至此,搞定调试串口驱动。

转载于:https://blog.51cto.com/coolbacon/1280034

RTEMS 的 AT91SAM9260 移植(5): 调试串口驱动相关推荐

  1. ESP32在WIN7下USB调试串口驱动安装 解决USB JTAG/serial debug unit (Interface 0)无法安装驱动的问题

    使用WIN7开发ESP32, 但一直不能解决USB烧录问题,  就是USB serial 总是无法安装, 虽然可以在WIN10下使用, 但切换虚拟机也麻烦 经常仔细对比查找分析, 问题解决, 顺利安装 ...

  2. RTEMS 的 AT91SAM9260 移植(8): 编译

    到这里,代码部分就修改完毕了,还需要修改该的就是Autotools的宏和链接脚本. 为了宏生成速度快,我把其他所有无关的BSP全部删除了. Autotools宏的修改相对比较简单,文件位置参考以上的连 ...

  3. ns16550串口驱动

    之前学习的STM32F103的串口时,特点是:没有FIFO.参考手册写的很棒. 这里主要介绍一下a20的串口模块,之前把printf重定向分析了个大概,没有具体到ns16550的驱动,今天还是网上找了 ...

  4. omap3530 linux串口驱动,omap3530(Cortex-A8)硬件平台软件调试笔记

    内容简介:描述调试过程中所遇问题及其解决办法和过程,可作为新手的FAQ使用. 1. Issue: 不能从SD卡启动. Fixed: 自己疏忽造成,手册已经提到要先用"HP Disk Stor ...

  5. linux串口驱动机制,Linux串口驱动移植的一些心得总结

    串口驱动的源文件一般是使用drivers/serial/8250.c文件,或该文件的稍作修改.这是因为大多的串口接口的操作寄存器都是符合相关的定义,都是基本一样的.那么在移植串口驱动时,一般是为该驱动 ...

  6. 从串口驱动的移植看linux2.6内核中的驱动模型 platform device platform driver【转】...

    转自:http://blog.csdn.net/bonnshore/article/details/7979705 写在前面的话: 博主新开了个人站点:你也可以在这里看到这篇文章,点击打开链接 本文是 ...

  7. Linux---wifi驱动移植及调试(SSV6x5x)

    一.背景说明及驱动移植 本文主要简述南方硅谷ssv6x5x wifi驱动的移植及调试,官方实际是有一份南方硅谷ssv6x5x 驱动移植用户指南,需要的话可以下载,官方指南对于移植过程描述的很清楚. 移 ...

  8. linux8250驱动支持5路串口,LINUX串口驱动(8250)的编写与调试

    串口控制器都是大同小异,用3条地址线就可以完全对串口控制器进行控制.针对ST554芯片来说,控制寄存器主要有THR(发送保持寄存器),RHR(接收保持寄存器),IER(中断使能寄存器),FCR(缓冲控 ...

  9. 从零开始之驱动发开、linux驱动(六十五、内核调试篇--串口驱动)

    上一节我们分析了bootoader中传过来的cmdline中的命令是如何解析并执行的. 同时也是对bootloader中传过来的console进行了记录. console也就是我们所说的控制台,可以是 ...

最新文章

  1. CentOS7 虚拟机最小化安装
  2. c语言编译时字符黑色,C语言黑与白问题
  3. 图神经网络 | BrainGNN: 用于功能磁共振成像分析的可解释性脑图神经网络
  4. java 图形用什么组件标题_java图形用户界面设计Swing常用组件(阅读).ppt
  5. c++ new[] delete[]底层分析
  6. 前端学习(1338):mongoDB删除文档
  7. 数据结构之查找算法:B+树
  8. 京东java开发面经_面经|京东技术中台Java开发面经
  9. 编程语言对比 字符串
  10. 什么是HDMIARC
  11. “box-shadow”属性(转)
  12. LeetCode 530二叉搜索树的最小绝对差
  13. JAVA秒杀mysql层实现_一文搞懂MySQL的Join,聊一聊秒杀架构设计
  14. android ui设计最新字体,手机ui设计常用字体一般有哪些,UI设计中的字体有什么规范要求...
  15. Java回调函数callback
  16. Hbase官方文档中文版
  17. 如何建立数据指标体系
  18. python图片logo_Python logo
  19. nar神经网络_NAR 神经网络多步和单步预测
  20. 三体归零者和盘龙鸿蒙,三体中的神级文明 归零者 到底是一种怎样的存在?

热门文章

  1. 开机后台运行jupyter_手机重启=关机再开机?原来差别竟这么大,很多人都不知道!...
  2. Java中如何引用另一个类里的集合_【18期】Java序列化与反序列化三连问:是什么?为什么要?如何做?...
  3. 【深度学习】ReLU激活函数的缺点
  4. 深入解析Java AtomicInteger 原子类型
  5. 面试必备:ArrayList源码解析(JDK8)
  6. 性能指标TP99之我解
  7. OpenCV中SUFR、SIFT无法使用的原因及解决办法
  8. 一些C语言学习的国外资源
  9. 编写高效的C程序与C代码优化
  10. 理解Spark的核心RDD