STM32でNUTTXを使ってみる

NuttxのAPI


NuttxのAPIはこ ちらに 詳しく公開されています。
Linuxのアプリを開発したことがある方ならば、同じ関数が使えることに気が付くと思います。
マルチタスクのアプリを作るときに必須の以下のAPIが普通に使えます。
Named Message Queue Interfaces
Counting Semaphore Interfaces

ただし、Flat address spaceモデル(仮想アドレス空間を使わずに全てのアドレスを物理アドレスで処理するモデル)では、
タスク起動のやり方がLinuxとは違って、forkやposix_spawn interfacesは使えません。

Network Interfacesもサポートしていますが、Ethernetが実装されているボードは
STM32F7 Discoveryなど一部のボードに限られます。



ヘッダーファイルをincludeすることで、以下のAPIやマクロが使えるようになります。
もう完全にLinuxです。
#ifdefで囲まれたAPIは、menuconfigで該当する項目を有効にする必要が有ります。
これらのAPIは 7.26 2018-09-08 版の物です。
$HOME/nuttxspace/nuttx/ChangeLogを見ると、かなり頻繁にアップデートされています。

#include <fcntl.h>

int creat(const char *path, mode_t mode);
int open(const char *path, int oflag, ...);
int fcntl(int fd, int cmd, ...);

#include <unistd.h>

int     close(int fd);
int     dup(int fd);
int     dup2(int fd1, int fd2);
off_t   lseek(int fd, off_t offset, int whence);
ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset);
ssize_t read(int fd, void *buf, size_t nbytes);
int     unlink(const char *path);
ssize_t write(int fd, const void *buf, size_t nbytes);

#include <sys/ioctl.h>

#ifdef CONFIG_LIBC_IOCTL_VARIADIC
int ioctl(int fd, int req, ...);
#else
int ioctl(int fd, int req, unsigned long arg);
#endif

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

#include <sys/select.h>

int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds,
           FAR fd_set *exceptfds, FAR struct timeval *timeout);

#include <dirent.h>

int        closedir(DIR *dirp);
FAR DIR   *opendir(const char *path);
FAR struct dirent *readdir(FAR DIR *dirp);
int        readdir_r(FAR DIR *dirp, FAR struct dirent *entry, FAR struct dirent **result);
void       rewinddir(FAR DIR *dirp);
void       seekdir(FAR DIR *dirp, int loc);
int        telldir(FAR DIR *dirp);

#include <unistd.h>

/* Task Control Interfaces */

pid_t   vfork(void);
pid_t   getpid(void);
void    _exit(int status) noreturn_function;
unsigned int sleep(unsigned int seconds);
void    usleep(unsigned long usec);
int     pause(void);

/* File descriptor operations */

int     close(int fd);
int     dup(int fd);
int     dup2(int fd1, int fd2);
int     fsync(int fd);
off_t   lseek(int fd, off_t offset, int whence);
ssize_t read(int fd, FAR void *buf, size_t nbytes);
ssize_t write(int fd, FAR const void *buf, size_t nbytes);
ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset);
ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset);

/* Check if a file descriptor corresponds to a terminal I/O file */

int     isatty(int fd);

/* Memory management */

#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_MM_PGALLOC) && \
    defined(CONFIG_ARCH_USE_MMU)
FAR void *sbrk(intptr_t incr);
#endif

/* Special devices */

int     pipe(int fd[2]);

/* Working directory operations */

int     chdir(FAR const char *path);
FAR char *getcwd(FAR char *buf, size_t size);

/* File path operations */

int     access(FAR const char *path, int amode);
int     rmdir(FAR const char *pathname);
int     unlink(FAR const char *pathname);

#ifdef CONFIG_PSEUDOFS_SOFTLINKS
int     link(FAR const char *path1, FAR const char *path2);
ssize_t readlink(FAR const char *path, FAR char *buf, size_t bufsize);
#endif

/* Execution of programs from files */

#ifdef CONFIG_LIBC_EXECFUNCS
int     execl(FAR const char *path, ...);
int     execv(FAR const char *path, FAR char *const argv[]);
#endif

/* Networking */

#ifdef CONFIG_NET
int     gethostname(FAR char *name, size_t size);
int     sethostname(FAR const char *name, size_t size);
#endif

/* Other */

int     getopt(int argc, FAR char *const argv[], FAR const char *optstring);

#include <stdio.h>

/* Operations on streams (FILE) */

void   clearerr(register FILE *stream);
int    fclose(FILE *stream);
int    fflush(FILE *stream);
int    feof(FILE *stream);
int    ferror(FILE *stream);
int    fileno(FAR FILE *stream);
int    fgetc(FILE *stream);
int    fgetpos(FILE *stream, fpos_t *pos);
char  *fgets(char *s, int n, FILE *stream);
FILE  *fopen(const char *path, const char *type);
int    fprintf(FILE *stream, const char *format, ...);
int    fputc(int c, FILE *stream);
int    fputs(const char *s, FILE *stream);
size_t fread(void *ptr, size_t size, size_t n_items, FILE *stream);
FAR FILE *freopen(FAR const char *path, FAR const char *mode,
         FAR FILE *stream);
int    fseek(FILE *stream, long int offset, int whence);
int    fsetpos(FILE *stream, fpos_t *pos);
long   ftell(FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t n_items, FILE *stream);
FAR char *gets(char *s);
FAR char *gets_s(FAR char *s, rsize_t n);
void   setbuf(FAR FILE *stream, FAR char *buf);
int    setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size);
int    ungetc(int c, FAR FILE *stream);

/* Operations on the stdout stream, buffers, paths, and the whole printf-family *    /

int    printf(const char *format, ...);
int    puts(const char *s);
int    rename(const char *source, const char *target);
int    sprintf(char *dest, const char *format, ...);
int    asprintf (FAR char **ptr, FAR const char *fmt, ...);
int    snprintf(FAR char *buf, size_t size, const char *format, ...);
int    sscanf(const char *buf, const char *fmt, ...);
void   perror(FAR const char *s);

int    vprintf(const char *s, va_list ap);
int    vfprintf(FILE *stream, const char *s, va_list ap);
int    vsprintf(char *buf, const char *s, va_list ap);
int    vasprintf(FAR char **ptr, const char *fmt, va_list ap);
int    vsnprintf(FAR char *buf, size_t size, const char *format, va_list ap);
int    vsscanf(char *buf, const char *s, va_list ap);

/* Operations on file descriptors including:
 *
 * POSIX-like File System Interfaces (fdopen), and
 * Extensions from the Open Group Technical Standard, 2006, Extended API Set
 *   Part 1 (dprintf and vdprintf)
 */

FAR FILE *fdopen(int fd, FAR const char *type);
int    dprintf(int fd, FAR const char *fmt, ...);
int    vdprintf(int fd, FAR const char *fmt, va_list ap);

/* Operations on paths */

FAR char *tmpnam(FAR char *s);
FAR char *tempnam(FAR const char *dir, FAR const char *pfx);
int       remove(FAR const char *path);

#include <sys/stat.h>

int mkdir(FAR const char *pathname, mode_t mode);
int mkfifo(FAR const char *pathname, mode_t mode);
int stat(const char *path, FAR struct stat *buf);
int fstat(int fd, FAR struct stat *buf);

#include <sys/statfs.h>

int statfs(FAR const char *path, FAR struct statfs *buf);
int fstatfs(int fd, FAR struct statfs *buf);

#include <stdlib.h>

int mktemp(FAR char *template);
int mkstemp(FAR char *template);

#include <aio.h>

int aio_cancel(int, FAR struct aiocb *aiocbp);
int aio_error(FAR const struct aiocb *aiocbp);
int aio_fsync(int, FAR struct aiocb *aiocbp);
int aio_read(FAR struct aiocb *aiocbp);
ssize_t aio_return(FAR struct aiocb *aiocbp);
int aio_suspend(FAR const struct aiocb *const list[], int nent,
                FAR const struct timespec *timeout);
int aio_write(FAR struct aiocb *aiocbp);
int lio_listio(int mode, FAR struct aiocb *const list[], int nent,
               FAR struct sigevent *sig);

#include <string.h>

char  *strchr(const char *s, int c);
FAR char *strdup(const char *s);
const char *strerror(int);
size_t strlen(const char *);
size_t strnlen(const char *, size_t);
char  *strcat(char *, const char *);
char  *strncat(char *, const char *, size_t);
int    strcmp(const char *, const char *);
int    strncmp(const char *, const char *, size_t);
int    strcasecmp(const char *, const char *);
int    strncasecmp(const char *, const char *, size_t);
char  *strcpy(char *dest, const char *src);
char  *strncpy(char *, const char *, size_t);
char  *strpbrk(const char *, const char *);
char  *strchr(const char *, int);
char  *strrchr(const char *, int);
size_t strspn(const char *, const char *);
size_t strcspn(const char *, const char *);
char  *strstr(const char *, const char *);
char  *strtok(char *, const char *);
char  *strtok_r(char *, const char *, char **);

void  *memset(void *s, int c, size_t n);
void  *memcpy(void *dest, const void *src, size_t n);
int    memcmp(const void *s1, const void *s2, size_t n);
void  *memmove(void *dest, const void *src, size_t count);

#include <strings.h>

#define bcmp(b1,b2,len)  memcmp(b1,b2,(size_t)len)
#define bcopy(b1,b2,len) (void)memmove(b2,b1,len)
#define bzero(s,n)       (void)memset(s,0,n)
#define index(s,c)       strchr(s,c)
#define rindex(s,c)      strrchr(s,c)

int    ffs(int j);
int    strcasecmp(const char *, const char *);
int    strncasecmp(const char *, const char *, size_t);



Nuttxサンプル・アプリケーションの中にAPIの使い方を紹介するアプリが登録されています。
多数のソースファイルで構成される大掛かりなアプリです。
$ ls ~/nuttxspace/apps/testing/ostest/
Kconfig     mqueue.c                 restart.c       sigprocmask.c
Make.defs   mutex.c                  rmutex.c        sporadic.c
Make.dep    nsem.c                   robust.c        suspend.c
Makefile    ostest.h                 roundrobin.c    timedmqueue.c
aio.c       ostest_main.c            sem.c           timedwait.c
barrier.c   posixtimer.c             semtimed.c      tls.c
cancel.c    prioinherit.c            setvbuf.c       vfork.c
cond.c      pthread_cleanup.c        sigev_thread.c  waitpid.c
dev_null.c  pthread_rwlock.c         sighand.c
fpu.c       pthread_rwlock_cancel.c  signest.c

メニューから
Application Configuration ---> Testing ---> OS Test example
を選んでファームをビルドすると、このアプリケーションを追加することができます。




このソースと実行ログを見比べれば、ほとんどのAPIの機能を理解することができます。
実行結果のログは結構大きいので、TeraTermのログ機能を有効にして、ログをteraterm.logに落として
じっくり見た方がいいです。
こちらから実行結果のログを見れるようにしておきます。

なお、BluePill BlackPillではSRAMが小さいので途中で以下のエラーになります。




ファームの書き込み方法と、nshへの接続方法はこちらに紹介しています。

STM32F4 Discovery
STM32F3 Discovery
STM32F103RB Nucleo
STM32F103 BluePill/BlackPill
STM32F103 VEボード
STM32F407 VGボード

次回は、Nuttxの提供するAPIの一部の機能を少し詳しく紹介する予定です。

続く....