From c853f2301d1807b32448981a1acf7fce9e4d7f67 Mon Sep 17 00:00:00 2001 From: Oleg Borodin Date: Thu, 15 Sep 2022 13:15:42 +0200 Subject: [PATCH] added minimal ibis driver example --- ibus/.gitignore | 7 +++ ibus/Makefile | 82 +++++++++++++++++++++++++ ibus/ibus.c | 66 ++++++++++++++++++++ ibus/ibus.h | 24 ++++++++ ibus/main.c | 72 ++++++++++++++++++++++ ibus/main.ld | 71 +++++++++++++++++++++ ibus/syscall.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++ ibus/usartu.c | 19 ++++++ ibus/usartu.h | 7 +++ 9 files changed, 507 insertions(+) create mode 100644 ibus/.gitignore create mode 100644 ibus/Makefile create mode 100644 ibus/ibus.c create mode 100644 ibus/ibus.h create mode 100644 ibus/main.c create mode 100644 ibus/main.ld create mode 100644 ibus/syscall.c create mode 100644 ibus/usartu.c create mode 100644 ibus/usartu.h diff --git a/ibus/.gitignore b/ibus/.gitignore new file mode 100644 index 0000000..3ca5774 --- /dev/null +++ b/ibus/.gitignore @@ -0,0 +1,7 @@ +*.elf +*.bin +*.map +*.geany +*.o +*~ +work diff --git a/ibus/Makefile b/ibus/Makefile new file mode 100644 index 0000000..4c412c7 --- /dev/null +++ b/ibus/Makefile @@ -0,0 +1,82 @@ +# +# Copyright: Oleg Borodin 2018 +# + +.SECONDARY: + +CFLAGS+= -I. -Os -DSTM32F4 #-std=c99 +CFLAGS+= -mfloat-abi=hard +CFLAGS+= -mcpu=cortex-m4 +CFLAGS+= -mthumb +CFLAGS+= -fno-common -ffunction-sections -fdata-sections +CFLAGS+= -g -gdwarf-2 +CFLAGS+= -Wall + + +LDFLAGS+= ${CFLAGS} +LDFLAGS+= --static +#LDFLAGS+= -nostartfiles +LDFLAGS+= -T main.ld + +LDFLAGS+= -Wl,-Map=main.map +LDFLAGS+= -Wl,--cref -Wl,--gc-sections +LDFLAGS+= -lopencm3_stm32f4 +LDFLAGS+= -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group + +TARGET= arm-eabi + +all: main.bin + +OBJS+= main.o +OBJS+= syscall.o +OBJS+= usartu.o +OBJS+= ibus.o + + +main.elf: $(OBJS) + $(TARGET)-gcc $(^F) $(LDFLAGS) -o $@ + $(TARGET)-size --format=berkeley $@ + +%.o: %.c + $(TARGET)-gcc $(CFLAGS) -c -o $@ $< + +%.o: %.S + $(TARGET)-gcc $(CFLAGS) -c -o $@ $< + +%.bin: %.elf + $(TARGET)-objcopy -O binary $< $@ + +%.elf: %.o + $(TARGET)-gcc $(^F) $(LDFLAGS) -o $@ + $(TARGET)-size --format=berkeley $@ + +clean: + rm -f *.i *.o *.elf *.bin *.map *~ *.hex *.d *.s + +flash: main.bin + @openocd \ + -c 'puts "--- START --------------------"' \ + -f 'interface/stlink.cfg' \ + -f 'target/stm32f4x.cfg' \ + -c 'puts "--- INIT --------------------"' \ + -c "init" \ + -c "reset halt" \ + -c 'puts "--- WRITE --------------------"' \ + -c "flash write_image erase $< 0x08000000"\ + -c 'puts "--- VERIFY --------------------"' \ + -c "verify_image $<" \ + -c 'puts "--- RESET --------------------"' \ + -c "reset" \ + -c 'puts "--- DONE --------------------"' \ + -c "shutdown" + +debug: main.bin + @openocd \ + -c 'puts "--- START --------------------"' \ + -f 'interface/stlink.cfg' \ + -f 'target/stm32f4x.cfg' \ + -c 'puts "--- INIT --------------------"' \ + -c "init" \ + -c "halt" \ + -c "poll" +#EOF diff --git a/ibus/ibus.c b/ibus/ibus.c new file mode 100644 index 0000000..c7bc690 --- /dev/null +++ b/ibus/ibus.c @@ -0,0 +1,66 @@ +/* + * Copyright 2022 Oleg Borodin + */ + + + +#include +#include +#include + +#include + +#define IBUS_FRAMESIZE 32 +#define IBUS_CHANNELS 14 + +void ibus_init(ibus_t* bus) { + memset(bus->iframe, 0, sizeof(bus->iframe)); + memset(bus->rcvalue, 0, sizeof(bus->rcvalue)); + bus->findex = 0; +} + + +bool ibus_recv(ibus_t* bus, uint8_t ibyte) { + + if(bus->findex == 0 && ibyte != 0x20) { + return false; + } + if(bus->findex == 1 && ibyte != 0x40) { + bus->findex = 0; + return false; + } + if(bus->findex < IBUS_FRAMESIZE) { + bus->iframe[bus->findex++] = ibyte; + return false; + } + + if(bus->findex == IBUS_FRAMESIZE) { + bus->findex = 0; + uint16_t chksum = 0xFFFF; + for (int i = 0; i < 30; i++) { + chksum -= bus->iframe[i]; + } + uint16_t rxsum = bus->iframe[30] + (bus->iframe[31] << 8); + if (chksum == rxsum) { + for (int c = 0; c < IBUS_CHANNELS; c++) { + int offset = c * 2 + 2; + uint16_t hival = ((bus->iframe[offset + 1] & 0x0F) << 8); + uint16_t loval = bus->iframe[offset] & 0xFF; + bus->rcvalue[c] = hival + loval; + } + return true; + } + } + return false; +} + +int ibus_chcount(ibus_t* bus) { + return IBUS_CHANNELS; +} + +int16_t ibus_getch(ibus_t* bus, int num) { + if (num < IBUS_CHANNELS) { + return (int16_t)bus->rcvalue[num]; + } + return WRONG_RCVAL; +} diff --git a/ibus/ibus.h b/ibus/ibus.h new file mode 100644 index 0000000..9bba6ee --- /dev/null +++ b/ibus/ibus.h @@ -0,0 +1,24 @@ +/* + * Copyright 2022 Oleg Borodin + */ + + +#ifndef IBUS_H_QWERTY +#define IBUS_H_QWERTY + +#define IBUS_FRAMESIZE 32 +#define IBUS_CHANNELS 14 +#define WRONG_RCVAL -1 + +typedef struct { + uint8_t iframe[IBUS_FRAMESIZE]; + uint16_t rcvalue[IBUS_CHANNELS]; + int findex; +} ibus_t; + +void ibus_init(ibus_t* bus); +bool ibus_recv(ibus_t* bus, uint8_t ibyte); +int ibus_chcount(ibus_t* bus); +int16_t ibus_getch(ibus_t* bus, int num); + +#endif diff --git a/ibus/main.c b/ibus/main.c new file mode 100644 index 0000000..ee584c2 --- /dev/null +++ b/ibus/main.c @@ -0,0 +1,72 @@ + +/* + * Copyright 2022 Oleg Borodin + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + + +static void clock_setup(void) { + rcc_clock_setup_pll(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]); + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOD); + rcc_periph_clock_enable(RCC_USART1); + rcc_periph_clock_enable(RCC_USART2); +} + +static void usart_setup(uint32_t usart, uint32_t gpioport, uint32_t gpiopins, uint32_t baudrate) { + usart_disable(usart); + + gpio_mode_setup(gpioport, GPIO_MODE_AF, GPIO_PUPD_NONE, gpiopins); + gpio_set_af(gpioport, GPIO_AF7, gpiopins); + gpio_set_output_options(gpioport, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, gpiopins); + + usart_set_baudrate(usart, baudrate); + usart_set_databits(usart, 8); + usart_set_stopbits(usart, USART_STOPBITS_1); + usart_set_parity(usart, USART_PARITY_NONE); + usart_set_flow_control(usart, USART_FLOWCONTROL_NONE); + usart_set_mode(usart, USART_MODE_TX_RX); + usart_disable_rx_interrupt(usart); + + usart_enable(usart); +} + +int main(void) { + + clock_setup(); + usart_setup(USART1, GPIOA, GPIO9 | GPIO10, 460800); + usart_setup(USART2, GPIOD, GPIO6, 115200); + + ibus_t bus; + ibus_init(&bus); + while (true) { + uint8_t ibyte = usart_recv_blocking(USART2); + bool ready = ibus_recv(&bus, ibyte); + if (ready) { + for (int i = 0; i < ibus_chcount(&bus); i++) { + printf("%2d=%4d ", i, ibus_getch(&bus, i)); + } + printf(" xxx \r\n"); + } + } + + +} diff --git a/ibus/main.ld b/ibus/main.ld new file mode 100644 index 0000000..49c4b7e --- /dev/null +++ b/ibus/main.ld @@ -0,0 +1,71 @@ + +MEMORY { + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K + SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K +} + +EXTERN (vector_table) + +ENTRY(reset_handler) + +SECTIONS +{ + .text : { + *(.vectors) + *(.text*) + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + } >FLASH + + .preinit_array : { + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + } >FLASH + + .init_array : { + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + } >FLASH + + .fini_array : { + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + } >FLASH + + . = ALIGN(4); + _etext = .; + + .data : { + _data = .; + *(.data*) + . = ALIGN(4); + _edata = .; + } >SRAM AT >FLASH + + _data_loadaddr = LOADADDR(.data); + + .bss : { + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } >SRAM + + + . = ALIGN(4); + _end = .; +} + +PROVIDE(_stack = ORIGIN(SRAM) + LENGTH(SRAM)); + +PROVIDE(_heap = _end ); +PROVIDE(_eheap = ORIGIN(SRAM) + LENGTH(SRAM)); diff --git a/ibus/syscall.c b/ibus/syscall.c new file mode 100644 index 0000000..91b4299 --- /dev/null +++ b/ibus/syscall.c @@ -0,0 +1,159 @@ +/* + * Copyright 2022 Oleg Borodin + */ + + +#include + +#include +#include +#include +#include +#include + +#include + +#undef errno +extern int errno; + +char *__env[1] = { 0 }; + +char **environ = __env; + +int _execve(char *name, char **argv, char **env) { + errno = ENOMEM; + return -1; +} + +int _fork(void) { + errno = EAGAIN; + return -1; +} + +int _getpid(void) { + return 1; +} + +int _kill(int pid, int sig) { + errno = EINVAL; + return -1; +} + +void _exit(int i) { + while (1); +} + +int _isatty(int file) { + return 1; +} + +int _fstat(int file, struct stat *st) { + st->st_mode = S_IFCHR; + return 0; +} + +int _link(char *old, char *new) { + errno = EMLINK; + return -1; +} + +int _lseek(int file, int ptr, int dir) { + return 0; +} + +int _open(const char *name, int flags, int mode) { + return -1; +} + +#define STDIN 0 +#define STDOUT 1 +#define STDERR 3 + + +int _read(int file, char *ptr, int len) { + int i = 0; + while (i < len) { + ptr[i++] = 0; + } + return i; +} + + +int _write(int file, char *ptr, int len) { + int i; + + if ((file == STDOUT) || (file == STDERR)) { + for (i = 0; i < len; i++) { + usart_putc(USART1, ptr[i]); + } + return len; + } + return 0; +} + +int _stat(char *file, struct stat *st) { + st->st_mode = S_IFCHR; + return 0; +} + +int _close(int file) { + return -1; +} + + +int _times(struct tms *buf) { + return -1; +} + +int _unlink(char *name) { + errno = ENOENT; + return -1; +} + +int _wait(int *status) { + errno = ECHILD; + return -1; +} + +void *xxx_sbrk(int incr) { + + extern unsigned char *_end; + static unsigned char *heap = NULL; + unsigned char *prev_heap; + + if (heap == NULL) { + heap = (unsigned char*)&_end; + } + prev_heap = heap; + + heap += incr; + return prev_heap; +} + +register char* stack_ptr __asm__ ("sp"); + +caddr_t __attribute__((weak)) _sbrk (int incr) { + extern char end __asm__ ("_end"); + static char * heap_end; + char * prev_heap_end; + + if (heap_end == NULL) { + heap_end = &end; + } + + prev_heap_end = heap_end; + + if (heap_end + incr > stack_ptr) { +#if 0 + extern void abort (void); + _write (1, "_sbrk: Heap and stack collision\n", 32); + abort (); +#else + errno = ENOMEM; + return (caddr_t) -1; +#endif + } + + heap_end += incr; + return (caddr_t) prev_heap_end; +} diff --git a/ibus/usartu.c b/ibus/usartu.c new file mode 100644 index 0000000..29ac7b4 --- /dev/null +++ b/ibus/usartu.c @@ -0,0 +1,19 @@ +/* + * Copyright 2022 Oleg Borodin + */ + +#include + +#include +#include + +void usart_puts(uint32_t usart, char* str) { + int i = 0; + while (str[i] != 0) { + usart_send_blocking(usart, str[i++]); + } +} + +void usart_putc(uint32_t usart, char c) { + usart_send_blocking(usart, c); +} diff --git a/ibus/usartu.h b/ibus/usartu.h new file mode 100644 index 0000000..90fd757 --- /dev/null +++ b/ibus/usartu.h @@ -0,0 +1,7 @@ +#ifndef _USARTU_H_XYZ +#define _USARTU_H_XYZ + +void usart_puts(uint32_t usart, char * str); +void usart_putc(uint32_t usart, char c); + +#endif