воскресенье, 19 мая 2013 г.

STM32F407(STM32F4-DISCOVERY) - Нестандартный подход - Подключение библиотек ч2

Часть 2 - Практика

После теории обычно следует практика и здесь мы рассмотрим все возможные варианты подключения библиотек. Начав c простых случаев, перейдем затем к более сложным.



"Hello work"
Если для статьи про стандартные библиотеки мы использовали GPIO, то тут в качестве основного блока будет выступать USART. Мы выведем строку приветствия + длину этой строки.

Простые библиотеки:
В качестве простой библиотеки мы возьмём творение Elm-Сhan'a библиотеку форматированного ввода-вывода xprintf. Использование этой библиотеки расписано не только по ссылке на оригинал, но также и на моём сайте. Библиотека почти не требует настройки, план к её использованию дан, я же опишу сейчас способы её подключения. Инициализацию USART мы сделаем с помощью CMSIS.:
  1. Добавление в inc/ и src/.
    Проект - 002-use-lib-xprintf. Основные файлы xprintf.h в inc/ и xprintf.c в src/. Для использования библиотеки необходимо немного модифицировать xprintf.h включив туда необходимые блоки. Также в проект добавлена драйверная часть - файлы usart.h в inc/ и usart.c в src/. Простейший код в work.c вызывает функцию инициализации последовательного порта и выводит в него сообщение средствами библиотеки:
    /* includes */
    #include "stm32f4xx.h"
    #include "usart.h"
    #include "xprintf.h"
    /* main work function */
    void work(void) {
        const char message[] = "Hello work";
        /* setup serial console */
        usart1_setup();
        /* printf message and it length */
        xprintf("Message: %s, Len: %d\r\n", message, sizeof(message));
        /* infinity loop */
        while (1);
    }
    
  2. Создание отдельной директории в lib/.
    Проект - 003-use-lib-xprintf2. Рабочий код и код инициализации последовательного порта полностью аналогичен предыдущему проекту. Отличия заключаются в следующем:
    1. Файлы библиотеки xprintf.h и xrpintf.c находятся в отдельной поддиректории xprintf/
    2. Makefile для библиотеки:
      # Include common config
      include $(ROOTDIR)/lib/make/Makefile.common
      # Add local includes
      CFLAGS+= -Iinc
      # Sources and objects
      LIB_SRC_PLATFORM=src/$(PLATFORM)
      ## Include lib files
      SRCS=xprintf.c
      OBJS=$(SRCS:.c=.o)
      # Library name
      LIB=libxprintf.a
      # Rules for compile
      all: $(LIB)
      # Create library
      $(LIB): $(OBJS)
       $(AR) -r $(LIB) $(OBJS)
       $(RANLIB) $(LIB)
      # Making objects
      %.o : %.c
       $(CC) $(CFLAGS) -c -o $@ $^
      # Rules for clean
      clean:
       -rm -f $(OBJS)
       -rm -f $(LIB)
      
      .PHONY: all clean
      
       От файла сборки основного исходного кода отличается тем, что на выходе получается не бинарная сборка, а библиотека, которая потом может использоваться в других проектах. 
    3. Makefile для директории libs/ - содержит добавление нашей библиотеки в путь сборки:
      # Build all libraries
      all:
       $(MAKE) -C std_periph
       $(MAKE) -C xprintf
      
      clean:
       $(MAKE) clean -C std_periph
       $(MAKE) -C xprintf
      
    4. Makefile.common для того, чтобы включить нашу библиотеку в проект:
      # Library paths
      LIBPATHS = -Llib/std_periph
      LIBPATHS+= -Llib/xprintf
      # Libraries to link
      LIBS = -lstdperiph -lxprintf
      
Составные библиотеки:
Как уже отмечалось, в теории в качестве составной библиотеки я выбрал SPL. А так как в этом примере мы используем стандартную библиотеку периферии, то инициализацию USART я осуществлю с её помощью.

Проект - 004-use-lib-xprintf-spl. Проект представляет собой расширение предыдущего. Отличие заключается в том, что в этом проекте мы используем составную библиотеку SPL.
Makefile сборки составной библиотеки отличается структурой:
# Include common config
include $(ROOTDIR)/lib/make/Makefile.common
# Add local includes
CFLAGS+= -Iinc
# Sources and objects
LIB_SRC_PLATFORM=src/$(PLATFORM)
## Include lib files
# SRCS+=$(LIB_SRC_PLATFORM)_adc.c
# SRCS+=$(LIB_SRC_PLATFORM)_can.c
# SRCS+=$(LIB_SRC_PLATFORM)_crc.c
# SRCS+=$(LIB_SRC_PLATFORM)_cryp.c
# SRCS+=$(LIB_SRC_PLATFORM)_cryp_aes.c
# SRCS+=$(LIB_SRC_PLATFORM)_cryp_des.c
# SRCS+=$(LIB_SRC_PLATFORM)_cryp_tdes.c
# SRCS+=$(LIB_SRC_PLATFORM)_dac.c
# SRCS+=$(LIB_SRC_PLATFORM)_dbgmcu.c
# SRCS+=$(LIB_SRC_PLATFORM)_dcmi.c
# SRCS+=$(LIB_SRC_PLATFORM)_dma.c
# SRCS+=$(LIB_SRC_PLATFORM)_exti.c
# SRCS+=$(LIB_SRC_PLATFORM)_flash.c
# SRCS+=$(LIB_SRC_PLATFORM)_fsmc.c
SRCS+=$(LIB_SRC_PLATFORM)_gpio.c
# SRCS+=$(LIB_SRC_PLATFORM)_hash.c
# SRCS+=$(LIB_SRC_PLATFORM)_hash_md5.c
# SRCS+=$(LIB_SRC_PLATFORM)_hash_sha1.c
# SRCS+=$(LIB_SRC_PLATFORM)_i2c.c
# SRCS+=$(LIB_SRC_PLATFORM)_iwdg.c
# SRCS+=$(LIB_SRC_PLATFORM)_pwr.c
SRCS+=$(LIB_SRC_PLATFORM)_rcc.c
# SRCS+=$(LIB_SRC_PLATFORM)_rng.c
# SRCS+=$(LIB_SRC_PLATFORM)_rtc.c
# SRCS+=$(LIB_SRC_PLATFORM)_sdio.c
# SRCS+=$(LIB_SRC_PLATFORM)_syscfg.c
# SRCS+=$(LIB_SRC_PLATFORM)_tim.c
SRCS+=$(LIB_SRC_PLATFORM)_usart.c
# SRCS+=$(LIB_SRC_PLATFORM)_wwdg.c
OBJS=$(SRCS:.c=.o)
# Library name
LIB=libstdperiph.a
# Rules for compile
all: $(LIB)
# Create library
$(LIB): $(OBJS)
 $(AR) -r $(LIB) $(OBJS)
 $(RANLIB) $(LIB)
# Making objects
%.o : %.c
 $(CC) $(CFLAGS) -c -o $@ $^
# Rules for clean
clean:
 -rm -f $(OBJS)
 -rm -f $(LIB)

.PHONY: all clean
Но в целом аналогичен. Также, отличие заключается в файле usart.c в функции инициализации:
/*USART1 setup */
void usart1_setup(void) {
    GPIO_InitTypeDef  GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    /* Enable USART1 and GPIOB clock              */
    RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    /* Configure USART1 Tx (PB6) as af            */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    /* Setup AF fuctions for Tx, pin */
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
    /* USART1 configured as follow:
 - BaudRate = 115200 baud
 - Word Length = 8 Bits
 - One Stop Bit
 - No parity
 - Hardware flow control disabled (RTS and CTS signals)
 - Receive and transmit enabled
 - USART Clock disabled
 - USART CPOL: Clock is active low
 - USART CPHA: Data is captured on the middle
 - USART LastBit: The clock pulse of the last data bit is not output to
 the SCLK pin
    */
    USART_InitStructure.USART_BaudRate            = 115200;
    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;
    USART_InitStructure.USART_Parity              = USART_Parity_No ;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);
    /* preinit xprintf lib
     * route xprintf output function to ser1_sendb function
     */
    xdev_out(ser1_sendb);
}

Итак, на этом я закончил описание подключения сторонних библиотек.
В дополнение привожу фото работы программы:
По любым вопросам касательно подключения библиотек вы можете обращаться ко мне в комментариях.

Подключение библиотек ч1