Итак, имеем STM32F103RB, хотя в данном случае не принципиально, т.к. вопрос о функциях поддержки ввода-вывода (ключевое слово printf()) на консоль с одновременным использованием файловой системы FlashFS из RL-ARM 4.12 от ARM/KEIL. Чтобы дойти до сути вопроса, надо немного рассказать о предыстории и моем понимании понятия retarget. Информация черпалась из помощи, прилагаемой к uVision4 с ARM Tool Chain, и отсюда: RL-ARM
Итак, хотим выводить на Hyperterminal с микроконтроллера. Для этого подсоединяем его UART к COM-порту компа, а в программе микроконтроллера используем printf(). Поскольку библиотека ARM не зависит о периферии конкретного камня, надо бы рассказать ей, что хотим посылать символы, "генерируемые" в недрах printf(), через, скажем, UART1. Для этого, как описывается в помощи и примерах, необходимо реализовать/перехватить функцию fputc(). Как правило, такой "перехват" помещается в retarget.c, а кто хочет стройный код, выделяет все, что касается UART, отдельно в файл serial.c. Примерно так:
RETARGET.C
Код
...
#include <stdio.h>
#pragma import(__use_no_semihosting_swi)
//
// To be implemented elsewhere (here - in Serial.c):
//
extern int sendchar(int c);
extern int getkey(void);
// ...
struct __FILE {
int handle;
// Add whatever you need here
};
FILE __stdout;
void _sys_exit(int return_code)
{
while (1); // endless loop
}
// --------------------------------------------
// Reimplementation for printf()
//
int fputc(int c, FILE *f) {
sendchar(c);
}
#include <stdio.h>
#pragma import(__use_no_semihosting_swi)
//
// To be implemented elsewhere (here - in Serial.c):
//
extern int sendchar(int c);
extern int getkey(void);
// ...
struct __FILE {
int handle;
// Add whatever you need here
};
FILE __stdout;
void _sys_exit(int return_code)
{
while (1); // endless loop
}
// --------------------------------------------
// Reimplementation for printf()
//
int fputc(int c, FILE *f) {
sendchar(c);
}
В SERIAL.C будет имплементирован sendchar(), который работает с железом UART1.
Все получилось и работает, хотя вся эта муть с #pragma import(__use_no_semihosting_swi) и struct __FILE {...} мне до конца не понятна. Это был бы первый подвопрос.
Теперь наступает следующий этап: хотим пользовать RL-ARM FlashFS конкретно с SD-картой на SPI. Смотрим RL-ARM и видим, что, якобы, все просто:
1). Копируем File_Config.* в свой проект, настраиваем File_Config.С
2). Используем SPI_STM32F103.c или пишем что-то свое для реализации функции spi_init (), spi_ss(), spi_hi_speed() и spi_send() (по сути аналог serial.c для UART1)
3). Подстыковываем библиотеку FS_CM3.lib
4). В коде вызываем finit(), когда SD-карточка вставлена, после чего...
5). пользуем файловую систему.
Так вот, пока ограничивался finit(), ffind() и ffree() для посмотреть каталог SD-карточки и количества свободного места, все транслировалось, компоновалось и работало.
Как только захотел что-то читать, то есть ввел в код обращения к fopen(), fread() и fclose(), компоновщик заголосил:
Error: L6915E: Library reports error: __use_no_semihosting_swi was requested, but _sys_open was referenced
А если взять из примера, приданого к RL-ARM FlashFS, реализацию этой самой функции со всеми там для нее важными определениями и заголовками, то компоновщику уже слишком много:
Error: L6200E: Symbol _sys_open multiply defined (by sys_io.o and retarget.o).
Хотя нигде sys_io.o в чистом виде не наблюдается, видать, в какой-то библиотеке сидит.
Прошу совета и разъяснения.
Заранее благодарен.
Игорь.