从AC5向AC6迁移,已经有很多人给出了迁移的教程,AC6的编译速度着实非常有吸引力,我也尝试根据网上的教程从AC5向AC6迁移,但程序执行到printf的时候便会有问题。
有问题的重定向代码:
/* ------------------通过重定向将printf函数映射到串口1上-------------------*/
#if !defined(__MICROLIB)
#pragma import(__use_no_semihosting)
void _sys_exit(int x) //避免使用半主机模式
{
x = x;
}
//__use_no_semihosting was requested, but _ttywrch was
void _ttywrch(int ch)
{
ch = ch;
}
struct __FILE
{
int handle;
};
FILE __stdout;
#endif
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
/* 实现串口发送一个字节数据的函数 */
//serial_write(&serial1, (uint8_t)ch); //发送一个自己的数据到串口
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
return ch;
}
要修改的地方:
#pragma import(__use_no_semihosting)
为AC5支持的语法格式,到了AC6不再支持改语法格式。
在”编译器用户指导“中找到了如下内容:
因此需要将该句内容替换为__asm (".global __use_no_semihosting\n\t");
- 理论上keil MDK不会定义
__GNUC__
,但自从AC5改为AC6后,keil MDK中#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
便会处于高亮的模式,不知道这__GNUC__
到底定义在哪了。但实际应该使用下面那条语句才对,从工程中搜索发现基本使用AC6的时候都会用到__clang__
因此这里修改一下这里的判定条件defined ( __GNUC__ ) && !defined (__clang__)
。这样便可以正确定位到下面应该使用的语句了。在没有改判定条件之前,如果编译的话,编译器会报一些奇怪的错误,改了判定条件后这些奇怪的错误也就没有了。
正确的重定向printf代码:
/* ------------------通过重定向将printf函数映射到串口1上-------------------*/
#if !defined(__MICROLIB)
//#pragma import(__use_no_semihosting)
__asm (".global __use_no_semihosting\n\t");
void _sys_exit(int x) //避免使用半主机模式
{
x = x;
}
//__use_no_semihosting was requested, but _ttywrch was
void _ttywrch(int ch)
{
ch = ch;
}
//struct __FILE
//{
// int handle;
//};
FILE __stdout;
#endif
#if defined ( __GNUC__ ) && !defined (__clang__)
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
/* 实现串口发送一个字节数据的函数 */
//serial_write(&serial1, (uint8_t)ch); //发送一个自己的数据到串口
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
return ch;
}