README.md

mik32_picolibc


Зачем?

Собственно для использования Picolibc в проектах для MIK32 “Амур”


Сборка

Понадобится установленная сборочная система meson
Понадобится установленный инструментарий riscv64-unknown-elf (например, установить пакет gcc-riscv64-unknown-elf)
Подготовка к сборке

  • создать временный директорий, например mkdir -p ${HOME}/temp
  • перейти в созданный директорий, например cd ${HOME}/temp
  • склонировать проект, например git clone https://gitflic.ru/project/rabidrabbit/mik32_picolibc.git
  • создать директорий для сборки build-picolibc, например mkdir -p ${HOME}/temp/build-picolibc
  • перейти в созданный директорий, например cd ${HOME}/temp/build-picolibc
  • создать директорий для установки, например mkdir -p ${HOME}/tools/picolibc-mik32
  • запустить сборочную систему, например meson setup --cross-file ${HOME}/temp/mik32_picolibc/picolibc-mik32/scripts/cross-mik32-amur.txt -Dtests=false -Dmultilib=false -Dsemihost=false -Dnewlib-multithread=false -Dnewlib-retargetable-locking=false -Dprefix=${HOME}/tools/picolibc-mik32 -Dbuildtype=debugoptimized ${HOME}/temp/mik32_picolibc/picolibc-mik32
  • при отсутствии ошибок запустить сборку, команда ninja
  • при отсутствии ошибок запустить установку, команда ninja install (может потребовать ввод пароля для получения доступа к директорию инструментария riscv64-unknown-elf, т.к. устанавливается файл спецификации и скрипты линкера)
  • если установилось, то директорий с проектом ${HOME}/temp/mik32_picolibc и директорий для сборки ${HOME}/temp/build-picolibc можно удалить

Применение

Есть готовый пример
А так, “для общего применения”, в файл с функцией main() нужно добавить следующее (можно в другой, но не забыть):

#include <mik32_memory_map.h>  // это заголовок с описанием оборудования Mik32
#include <uart.h>              // это заголовок с описанием блока UART

#include <stdio.h>
#include <string.h>

__attribute__((used)) FILE __sf[2];
__attribute__((used)) FILE * const stdin = &__sf[0];
__attribute__((used)) FILE * const stdout = &__sf[1];
__attribute__((used)) FILE * const stderr = &__sf[1];

int mik32_putchar( char a_char, struct __file * ) {
  while ( 0 == (UART_0->FLAGS & UART_FLAGS_TXE_M) ) {}
  UART_0->TXDATA = a_char;
  return a_char;
}

int mik32_getchar( struct __file * ) {
  while ( 0 == (UART_0->FLAGS & UART_FLAGS_RXNE_M) ) {}
  return UART_0->RXDATA;
}

void local_init() {
  bzero( __sf, sizeof(__sf) );
  fdev_setup_stream( stdin, NULL, mik32_getchar, NULL, __SRD );
  fdev_setup_stream( stdout, mik32_putchar, NULL, NULL, __SWR );
}

И в самое начало функции main() добавить вызов функции local_init()
Кроме этого, конечно, должна быть проведена инициализация UART_0, и это нужно сделать до первого использования функций из stdio.h
Для сборки проектов под Mik32 с picolibc можно использовать такие параметры: riscv64-unknown-elf-gcc –specs=picolibc.specs -crt0=minimal -march=rv32imc_zicsr -mabi=ilp32 -L/usr/lib/gcc/riscv64-unknown-elf/14.2.0/rv32im/ilp32/
Путь к библиотеке -L/usr/lib/gcc/riscv64-unknown-elf/14.2.0/rv32im/ilp32/ указывается для того, чтобы линкер нашёл libgcc.a (вроде необходимое оттуда перенесено в picolibc). Этот путь не потребуется, если для riscv64-unknown-elf есть цель сборки rv32imc. В другой версии gcc путь может отличаться.


Полезные ссылки

Описание
Picolibc для Mik32 "Амур", совсем чуть-чуть подпилено для совместимости с Mik32.
Конвейеры
0 успешных
0 с ошибкой
Разработчики