1.半主机模式
半主机是用于 ARM 目标的一种机制,可将来自应用程序代码的输入/输出请求传送至运行调试器的主机。 例如,使用此机制可以启用 C 库中的函数,如 printf() 和 scanf(),来使用主机的屏幕和键盘,而不是在目标系统上配备屏幕和键盘。
这种机制很有用,因为开发时使用的硬件通常没有最终系统的所有输入和输出设备。 半主机可让主机来提供这些设备。
半主机是通过一组定义好的软件指令(如 SVC)来实现的,这些指令通过程序控制生成异常。 应用程序调用相应的半主机调用,然后调试代理处理该异常。 调试代理提供与主机之间的必需通信。
2.?微库microlib
microlib?是缺省?C?库的备选库。 它用于必须在极少量内存环境下运行的深层嵌入式应用程序。 这些应用程序不在操作系统中运行。microlib?不会尝试成为符合标准的?ISO C?库。
microlib?进行了高度优化以使代码变得很小。 它的功能比缺省?C?库少,并且根本不具备某些?ISO C?特性。
3.printf函数通过串口外设来实现重定向
方法1.使用微库microlib?,
使用microlib?,会自动关闭半主机模式,重定向仅实现putc和getc即可,代码如下
int fputc(int ch, FILE *f)
{? ?? ?
while((USART1->SR&0X40)==0);
? ? USART1->DR = (u8) ch;? ?? ?
return ch;
}??
方法2.使用标准库,
不使用microlib?,需要手动关闭半主机模式,不使用microlib带来的一个问题是Keil会使用semihosting SWI完成sys_io(如:printf),所以需要一个retarget_io.c来禁止semihosting。
链接:retarget_io.c File (keil.com)
关闭半主机模式(ARM Compiler 5版本):#pragma import(__use_no_semihosting_swi)
关闭半主机模式(ARM Compiler 6版本):__asm(".global __use_no_semihosting\n\t");
ARM Compiler 5版本重定向代码如下
//加如下代码支持printf函数,而不需要选择use MicroLIB
#pragma import(__use_no_semihosting) //不使用半主机模式
//标准库需要的支持函数
struct __FILE
{
int handle;
};
extern FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
void _ttywrch(int x)
{
x = x;
}
int stdin_getchar (void)
{
while((LPUART1->ISR & USART_ISR_RXNE) == 0)
{}
return (int)LPUART1->RDR;
}
int stdout_putchar (int ch)
{
/* 写一个字节到LPUART1 */
LPUART1->TDR = ch;
/* 等待发送结束 */
while((LPUART1->ISR & USART_ISR_TC) == 0){}
return ch;
}
4.Keil5实现File System只支持标准库,不支持微库microlib?
//文件fs_config.h
/* Reject MicroLib since it does not provide retargeting */
#ifdef __MICROLIB
#error "File System does not work with MicroLIB"
#endif
?所以如果使用了File System再使用串口重定向时不能直接使用putc,而是标准库模式加retarget_io.c里的stdout_putchar?
//fs_config.h
/* Standard file I/O retargeting is mandatory */
#ifndef RTE_Compiler_IO_File_FS
#error "Standard file I/O library retarget requires ::Compiler:I/O:File software component from the 'Keil.ARM_Compiler' Pack!"
#endif
|