https://github.com/kindsoldier/stm32-f4-freertos-opencm3
Code based on FreeRTOS v10, opencm3 and STM32F407 MCU
Released
No guarantees. This code is given only as an sample.
But must work good.
I try to publish a good code.
# # Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 # .SECONDARY: RTOS_LOC = RTOS CFLAGS+= -I. -Os -DSTM32F4 -std=c99 CFLAGS+= -mthumb -march=armv7e-m CFLAGS+= -mfloat-abi=hard -mfpu=fpv4-sp-d16 CFLAGS+= -mcpu=cortex-m4 CFLAGS+= -fno-common -ffunction-sections -fdata-sections CFLAGS+= -g -gdwarf-2 CFLAGS+= -I${RTOS_LOC} LDFLAGS+= ${CFLAGS} LDFLAGS+= --static LDFLAGS+= -nostartfiles LDFLAGS+= -T master.ld LDFLAGS+= -Wl,-Map=master.map LDFLAGS+= -Wl,--cref -Wl,--gc-sections LDFLAGS+= -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group LDFLAGS+= -lopencm3_stm32f4 LDFLAGS+= -L${RTOS_LOC} -lrtos RTOS_OBJS+= $(RTOS_LOC)/croutine.o RTOS_OBJS+= $(RTOS_LOC)/event_groups.o RTOS_OBJS+= $(RTOS_LOC)/heap_3.o RTOS_OBJS+= $(RTOS_LOC)/list.o RTOS_OBJS+= $(RTOS_LOC)/port.o RTOS_OBJS+= $(RTOS_LOC)/queue.o RTOS_OBJS+= $(RTOS_LOC)/stream_buffer.o RTOS_OBJS+= $(RTOS_LOC)/tasks.o RTOS_OBJS+= $(RTOS_LOC)/timers.o MASTER_OBJS+= master.o MASTER_OBJS+= syscall.o MASTER_OBJS+= buffer.o MASTER_OBJS+= uastdio.o MASTER_OBJS+= fsmcwr.o MASTER_OBJS+= ili9341.o MASTER_OBJS+= console.o MASTER_OBJS+= random.o MASTER_OBJS+= rtc4xx.o MASTER_OBJS+= xpt2046.o MASTER_OBJS+= opencm3.o all: rtos master.bin rtos: $(RTOS_LOC)/librtos.a ${RTOS_OBJS}: FreeRTOSConfig.h $(RTOS_LOC)/librtos.a: $(RTOS_OBJS) cd $(@D) && arm-eabi-ar rcv $(@F) $(^F) master.elf: $(MASTER_OBJS) arm-eabi-gcc $(^F) $(LDFLAGS) -o $@ arm-eabi-size --format=berkeley $@ %.o: %.c arm-eabi-gcc $(CFLAGS) -c -o $@ $< %.o: %.S arm-eabi-as $(ASFLAGS) -o $@ $< %.bin: %.elf arm-eabi-objcopy -O binary $< $@ %.elf: %.o arm-eabi-gcc $(^F) $(LDFLAGS) -o $@ arm-eabi-size --format=berkeley $@ clean: rm -f *.i *.o *.elf *.bin *.map *~ *.hex *.d *.s cd $(RTOS_LOC) && rm -f *.o *.d *~ lib*.a upload: all master.upl %.upl: %.bin @openocd \ -c 'puts "--- START --------------------"' \ -f 'interface/stlink-v2.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: @openocd \ -c 'puts "--- START --------------------"' \ -f 'interface/stlink-v2.cfg' \ -f 'target/stm32f4x.cfg' \ -c 'puts "--- INIT --------------------"' \ -c "init" \ -c "halt" \ -c "poll" #EOF
volatile static uint16_t adc_res[17]; void adc1_setup(void) { static uint8_t channel_seq[16]; gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO0); gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO1); adc_set_clk_prescale(ADC_CCR_ADCPRE_BY2); //adc_power_off(ADC1); adc_enable_scan_mode(ADC1); adc_set_continuous_conversion_mode(ADC1); adc_disable_discontinuous_mode_regular(ADC1); //adc_enable_temperature_sensor(); adc_enable_external_trigger_regular(ADC1, ADC_CR2_SWSTART, ADC_CR2_EXTEN_DISABLED); adc_set_right_aligned(ADC1); adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28CYC); adc_set_resolution(ADC1, 8); channel_seq[0] = ADC_CHANNEL0; channel_seq[1] = ADC_CHANNEL1; adc_set_multi_mode(ADC_CCR_MULTI_INDEPENDENT); adc_set_regular_sequence(ADC1, 1, channel_seq); adc_enable_dma(ADC1); adc_power_on(ADC1); adc_start_conversion_regular(ADC1); } /*** DMA2 ***/ static void dma2_setup(void) { dma_stream_reset(DMA2, DMA_STREAM4); dma_set_priority(DMA2, DMA_STREAM4, DMA_SxCR_PL_LOW); dma_set_memory_size(DMA2, DMA_STREAM4, DMA_SxCR_MSIZE_16BIT); dma_set_peripheral_size(DMA2, DMA_STREAM4, DMA_SxCR_PSIZE_16BIT); dma_enable_memory_increment_mode(DMA2, DMA_STREAM4); dma_enable_circular_mode(DMA2, DMA_STREAM4); dma_set_transfer_mode(DMA2, DMA_STREAM4, DMA_SxCR_DIR_PERIPHERAL_TO_MEM); dma_set_peripheral_address(DMA2, DMA_STREAM4, (uint32_t) & ADC_DR(ADC1)); dma_set_memory_address(DMA2, DMA_STREAM4, (uint32_t) &adc_res); dma_set_number_of_data(DMA2, DMA_STREAM4, 1); dma_channel_select(DMA2, DMA_STREAM4, DMA_SxCR_CHSEL_0); //nvic_enable_irq(NVIC_DMA2_STREAM4_IRQ); //dma_enable_transfer_complete_interrupt(DMA2, DMA_STREAM4); dma_enable_stream(DMA2, DMA_STREAM4); } void dma2_stream4_isr(void) { //dma_clear_interrupt_flags(DMA2, DMA_CHANNEL4, DMA_IFCR_CGIF1); } void dma2_stream0_isr(void) { //dma_clear_interrupt_flags(DMA2, DMA_CHANNEL4, DMA_IFCR_CGIF1); } float get_mcu_temp(void) { float temp; temp = adc_res[0]; //((((adc_res[2] * 3300.0f) / 0xFFF) / 1000.0f) - 0.760f) / .0025f; return temp; }
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #include <stdint.h> #include <stdbool.h> #include <string.h> #include <buffer.h> void buffer_init(buffer_t * buffer, uint8_t * data, uint16_t length) { if (buffer && buffer) { memset((void **)buffer, 0, length); buffer->length = length; buffer->data = data; buffer->head = 0; buffer->tail = 0; } } uint16_t buffer_count(const buffer_t * buffer) { if (buffer) { return (buffer->head - buffer->tail); } return 0; } bool buffer_full(const buffer_t * buffer) { if (buffer) { return (buffer_count(buffer) == buffer->length); } return true; } bool buffer_empty(const buffer_t * buffer) { if (buffer) { return (buffer_count(buffer) == 0); } return true; } uint16_t buffer_peek(const buffer_t * buffer) { uint8_t data = 0; if (!buffer_empty(buffer)) { data = buffer->data[buffer->tail % buffer->length]; } return data; } bool buffer_back(buffer_t * buffer) { if (!buffer_empty(buffer)) { buffer->head--; return true; } return false; } uint8_t buffer_get_byte(buffer_t * buffer) { uint8_t data = 0; if (!buffer_empty(buffer)) { data = buffer->data[buffer->tail % buffer->length]; buffer->tail++; } return data; } bool buffer_put_byte(buffer_t * buffer, uint8_t data) { bool status = false; if (buffer) { if (!buffer_full(buffer)) { buffer->data[buffer->head % buffer->length] = data; buffer->head++; status = true; } } return status; } uint8_t buffer_put_string(buffer_t * buffer, uint8_t * string) { if (buffer) { for (uint8_t i = 0; i < strlen(string); i++) { if (!buffer_put_byte(buffer, string[i])) return i; } } return 0; } bool buffer_scan_byte(buffer_t * buffer, uint8_t c) { if (buffer) { if (!buffer_empty(buffer)) { uint8_t tail = buffer->tail; for (uint8_t i = 0; i < buffer_count(buffer); i++) { uint8_t data = buffer->data[tail % buffer->length]; if (data == c) { return true; } tail++; } } return false; } return false; } uint16_t buffer_get_token(buffer_t * buffer, uint8_t * str, uint16_t len, uint8_t term) { if (buffer) { memset((void *)str, 0, len); if (buffer_scan_byte(buffer, term) && str) { uint8_t i = 0, c = 0; while ((c = buffer_get_byte(buffer)) != 0 && c != term && i < len) { str[i] = c; i++; } return i; } return 0; } return 0; } /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #ifndef BUFFER_H_ITU #define BUFFER_H_ITU typedef struct buffer { volatile uint16_t head; volatile uint16_t tail; volatile uint8_t *data; uint16_t length; } buffer_t; bool buffer_back(buffer_t *buffer); bool buffer_empty(const buffer_t *buffer); bool buffer_full(const buffer_t *buffer); bool buffer_put_byte(buffer_t *buffer, uint8_t data); bool buffer_scan_byte(buffer_t *buffer, uint8_t c); uint16_t buffer_count(const buffer_t *buffer); uint16_t buffer_get_token(buffer_t *buffer, uint8_t * str, uint16_t len, uint8_t term); uint16_t buffer_peek(const buffer_t *buffer); uint8_t buffer_get_byte(buffer_t *buffer); uint8_t buffer_put_string(buffer_t *buffer, uint8_t * string); void buffer_init(buffer_t *buffer, uint8_t * data, uint16_t length); #endif /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #include <stdint.h> #include <stdbool.h> #include <stdlib.h> #include <ili9341.h> #include <console.h> #include <font8x14.h> font_t basefont = { .width = 8, .height = 14, .start = 0, //32, .length = 255, //0x5F, .bitmap = basefont_bitmap }; console_t console = { .width = CONSOLE_WIDTH, .height = CONSOLE_HEIGHT, .line = 0, .row = 0, .xmax = LCD_WIDTH, .ymax = LCD_HEIGHT, .xshift = 0, .yshift = 0, .font = &basefont, }; void _console_setup(console_t *console, uint16_t xmax, uint16_t ymax, font_t *font) { console->xmax = xmax; console->ymax = ymax; console->font = font; console->width = ymax/font->width; console->height = ymax/font->height; console->buffer_len = console->width * console->height + 1; console->buffer = malloc(console->buffer_len); } void console_setup(void) { _console_setup(&console, LCD_WIDTH, LCD_HEIGHT, &basefont); } void console_render_char(console_t *console, uint8_t line, uint8_t row) { uint8_t c = console->buffer[(console->width * line) + row]; lcd_draw_char( (console->xmax - (console->font->height * (line + 1))) + console->yshift, (console->font->width * row) + console->xshift, console->font, c); } void console_render(console_t *console) { #if 0 for (uint8_t line = console->height; line > 0; --line) { for (uint8_t row = console->width; row > 0; --row) { console_render_char(console, line - 1, row - 1); } } #endif for (uint8_t line = 0; line < console->height; line++) { for (uint8_t row = 0; row < console->width; row++) { console_render_char(console, line, row); } } } void console_shift(console_t *console) { uint16_t i = 0; uint16_t pos = console->width * (console->line - 1) + console->row; uint16_t end = console->width * console->height; while (i < (end - console->width)) { console->buffer[i] = console->buffer[i + console->width]; i++; } while (i < end) { console->buffer[i] = ' '; i++; } if (console->line > 0) console->line--; else console->line = 0; } void console_putc(console_t *console, uint8_t c) { if ((console->row + 1) > console->width) { console->line++; console->row = 0; } if (console->line >= console->height) { console_shift(console); console_render(console); } console->buffer[(console->line * console->width) + console->row] = c; console_render_char(console, console->line, console->row); console->row++; } int console_puts(console_t *console, uint8_t *str) { uint8_t i = 0; while (str[i] != 0) { console_putc(console, str[i]); i++; } return i; } void console_render_xychar(console_t *console, uint8_t line, uint8_t row, uint8_t c) { lcd_draw_char( (console->xmax - (console->font->height * (line + 1))) + console->yshift, (console->font->width * row) + console->xshift, console->font, c); } void console_xyputc(console_t *console, uint16_t line, uint16_t row, uint8_t c) { if (row < console->width && line < console->height) { console_render_xychar(console, line, row, c); } } int console_xyputs(console_t *console, uint16_t line, uint16_t row, uint8_t *str) { uint8_t i = 0; while (str[i] != 0 && row < console->width && line < console->height) { console_render_xychar(console, line, row, str[i]); i++; row++; } return i; } /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #ifndef CONSOLE_H_ITU #define CONSOLE_H_ITU #include <ili9341.h> typedef struct console { uint8_t width; uint8_t height; uint8_t line; uint8_t row; uint16_t xmax; uint16_t ymax; uint16_t xshift; uint16_t yshift; font_t *font; uint8_t *buffer; uint16_t buffer_len; } console_t; #define CONSOLE_WIDTH (LCD_HEIGHT/8) #define CONSOLE_HEIGHT (LCD_WIDTH/14) extern console_t console; void _console_setup(console_t *console, uint16_t xmax, uint16_t ymax, font_t *font); void console_setup(void); void console_render_char(console_t *console, uint8_t line, uint8_t row); void console_render(console_t *console); void console_shift(console_t *console); void console_putc(console_t *console, uint8_t c); int console_puts(console_t *console, uint8_t *str); void console_render_xychar(console_t *console, uint8_t line, uint8_t row, uint8_t c); void console_xyputc(console_t *console, uint16_t line, uint16_t row, uint8_t c); int console_xyputs(console_t *console, uint16_t line, uint16_t row, uint8_t *str); #endif
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #include <stdint.h> #include <time.h> #include <datetime.h> time_t date_to_unixtime(const struct tm * date) { uint32_t year; uint32_t mon; uint32_t day; uint32_t time; year = date->tm_year; mon = date->tm_mon; day = date->tm_mday; /* January and February are counted as months 13 and 14 of the previous year */ if (mon <= 2) { mon += 12; year -= 1; } /* Convert years to days */ time = (365 * year) + (year / 4) - (year / 100) + (year / 400); /* Convert months to days */ time += (30 * mon) + (3 * (mon + 1) / 5) + day; /* Unix time starts on January 1st, 1970 */ time -= 719561; /* Convert days to seconds */ time *= 86400; /* Add hours, minutes and seconds */ time += (3600 * date->tm_hour) + (60 * date->tm_min) + date->tm_sec; /* Return Unix time */ return (time_t)time; } uint8_t day_of_week(uint16_t year, uint8_t mon, uint8_t mday) { uint16_t h; uint16_t j; uint16_t k; /* January and February are counted as months 13 and 14 of the previous year */ if (mon <= 2) { mon += 12; year -= 1; } /* J is the century */ j = year / 100; /* K the year of the century */ k = year % 100; /* Compute H using Zeller's congruence */ h = mday + (26 * (mon + 1) / 10) + k + (k / 4) + (5 * j) + (j / 4); /* Return the day of the week */ return ((h + 5) % 7) + 1; } void unixtime_to_date(time_t time, struct tm * date) { uint32_t a; uint32_t b; uint32_t c; uint32_t d; uint32_t e; uint32_t f; /* Negative Unix time values are not supported */ if (time < 1) time = 0; /* Retrieve hours, minutes and seconds */ date->tm_sec = time % 60; time /= 60; date->tm_min = time % 60; time /= 60; date->tm_hour = time % 24; time /= 24; /* Convert Unix time to date */ a = (uint32_t) ((4 * time + 102032) / 146097 + 15); b = (uint32_t) (time + 2442113 + a - (a / 4)); c = (20 * b - 2442) / 7305; d = b - 365 * c - (c / 4); e = d * 1000 / 30601; f = d - e * 30 - e * 601 / 1000; /* January and February are counted as months 13 and 14 of the previous year */ if (e <= 13) { c -= 4716; e -= 1; } else { c -= 4715; e -= 13; } /* Retrieve year, month and day */ date->tm_year = c; date->tm_mon = e; date->tm_mday = f; /* Calculate day of week */ date->tm_wday = day_of_week(c, e, f); } /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #ifndef DATETIME_H_ITU #define DATETIME_H_ITU time_t date_to_unixtime(const struct tm * date); uint8_t day_of_week(uint16_t year, uint8_t mon, uint8_t mday); void unixtime_to_date(time_t time, struct tm * date); #endif /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #ifndef FONT8x14_H #define FONT8x14_H const uint8_t basefont_bitmap[] = { // 0x72, 0xb5, 0x4a, 0x86, /* Magic */ // 0x00, 0x00, 0x00, 0x00, /* Version */ // 0x20, 0x00, 0x00, 0x00, /* Header size */ // 0x00, 0x00, 0x00, 0x00, /* Flags */ // 0x00, 0x01, 0x00, 0x00, /* No. of chars */ // 0x0e, 0x00, 0x00, 0x00, /* Char length */ // 0x0e, 0x00, 0x00, 0x00, /* Char width */ // 0x08, 0x00, 0x00, 0x00, /* Char height */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x7e, 0x00, 0x00, 0x00, /* 1 */ 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x00, 0x00, 0x00, /* 2 */ 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, /* 3 */ 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, /* 4 */ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, /* 5 */ ... 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 253 */ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 254 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 255 */ }; #endif
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H extern size_t __rtos_heap_size; extern uint32_t rcc_ahb_frequency; #define configMINIMAL_STACK_SIZE ((unsigned short) 128) #define configSYSTICK_CLOCK_HZ (configCPU_CLOCK_HZ / 8) /* fix for vTaskDelay() */ #define configTICK_RATE_HZ ((TickType_t) 1000) #define configTOTAL_HEAP_SIZE ((size_t) __rtos_heap_size) #define configCPU_CLOCK_HZ ((unsigned long) rcc_ahb_frequency) #define configIDLE_SHOULD_YIELD 1 #define configMAX_PRIORITIES 5 #define configMAX_TASK_NAME_LEN 5 #define configUSE_16_BIT_TICKS 0 #define configUSE_COUNTING_SEMAPHORES 1 #define configUSE_MUTEXES 1 #define configUSE_NEWLIB_REENTRANT 1 #define configUSE_PREEMPTION 1 #define configUSE_CO_ROUTINES 0 #define configMAX_CO_ROUTINE_PRIORITIES 2 #define configUSE_TICK_HOOK 0 #define configUSE_IDLE_HOOK 0 #define configUSE_TRACE_FACILITY 1 #define INCLUDE_uxTaskPriorityGet 1 #define INCLUDE_vTaskCleanUpResources 0 #define INCLUDE_vTaskDelay 1 #define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelete 1 #define INCLUDE_vTaskPrioritySet 1 #define INCLUDE_vTaskSuspend 1 #define INCLUDE_eTaskGetState 1 #define INCLUDE_uxTaskGetStackHighWaterMark 1 #define INCLUDE_xQueueGetMutexHolder 1 //#define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder //#define INCLUDE_xTaskAbortDelay 0 #define INCLUDE_xTaskGetCurrentTaskHandle 1 #define INCLUDE_xTaskGetHandle 1 #define INCLUDE_xTaskGetIdleTaskHandle 1 #define INCLUDE_xTaskGetSchedulerState 0 #define INCLUDE_xTaskResumeFromISR 1 #define INCLUDE_xTimerPendFunctionCall 0 #define IRQ2NVIC_PRIOR(x) ((x) << 4) #define configKERNEL_INTERRUPT_PRIORITY IRQ2NVIC_PRIOR(15) #define configMAX_SYSCALL_INTERRUPT_PRIORITY IRQ2NVIC_PRIOR(5) #define configSUPPORT_DYNAMIC_ALLOCATION 1 #define configSUPPORT_STATIC_ALLOCATION 0 #define configUSE_TIMERS 1 #define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) #define configTIMER_QUEUE_LENGTH 32 #define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE #define configGENERATE_RUN_TIME_STATS 1 #define configUSE_TRACE_FACILITY 1 #define portGET_RUN_TIME_COUNTER_VALUE xTaskGetTickCount #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* */ #define configUSE_STATS_FORMATTING_FUNCTIONS 1 //#define configAPPLICATION_ALLOCATED_HEAP 0 //#define configASSERT(x) //#define configASSERT_DEFINED 0 //#define configCHECK_FOR_STACK_OVERFLOW 0 //#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 //#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 //#define configPOST_SLEEP_PROCESSING(x) //#define configPRE_SLEEP_PROCESSING(x) //#define configQUEUE_REGISTRY_SIZE 0U //#define configUSE_APPLICATION_TASK_TAG 0 //#define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 //#define configUSE_MALLOC_FAILED_HOOK 0 //#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 //#define configUSE_QUEUE_SETS 0 //#define configUSE_RECURSIVE_MUTEXES 0 //#define configUSE_STATS_FORMATTING_FUNCTIONS 1 //#define configUSE_TASK_NOTIFICATIONS 1 //#define configUSE_TICKLESS_IDLE 0 //#define configUSE_TIME_SLICING 1 #endif /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #include <libopencm3/stm32/fsmc.h> void fsmc_write_burst_disable(uint32_t bcr) { FSMC_BCR(bcr) &= ~FSMC_BCR_CBURSTRW; } void fsmc_write_burst_enable(uint32_t bcr) { FSMC_BCR(bcr) |= FSMC_BCR_CBURSTRW; } void fsmc_extended_mode_disable(uint32_t bcr) { FSMC_BCR(bcr) &= ~FSMC_BCR_EXTMOD; } void fsmc_extended_mode_enable(uint32_t bcr) { FSMC_BCR(bcr) |= FSMC_BCR_EXTMOD; } void fsmc_write_disable(uint32_t bcr) { FSMC_BCR(bcr) &= ~FSMC_BCR_WREN; } void fsmc_write_enable(uint32_t bcr) { FSMC_BCR(bcr) |= FSMC_BCR_WREN; } void fsmc_wait_disable(uint32_t bcr) { FSMC_BCR(bcr) &= ~FSMC_BCR_WAITEN; } void fsmc_wait_enable(uint32_t bcr) { FSMC_BCR(bcr) |= FSMC_BCR_WAITEN; } void fsmc_wait_signal_polarity_low(uint32_t bcr) { FSMC_BCR(bcr) &= ~FSMC_BCR_WAITPOL; } void fsmc_wait_signal_polarity_high(uint32_t bcr) { FSMC_BCR(bcr) |= FSMC_BCR_WAITPOL; } void fsmc_wrapped_burst_mode_disable(uint32_t bcr) { FSMC_BCR(bcr) &= ~FSMC_BCR_WRAPMOD; } void fsmc_wrapped_burst_mode_enable(uint32_t bcr) { FSMC_BCR(bcr) |= FSMC_BCR_WRAPMOD; } void fsmc_burst_disable(uint32_t bcr) { FSMC_BCR(bcr) &= ~FSMC_BCR_BURSTEN; } void fsmc_burst_enable(uint32_t bcr) { FSMC_BCR(bcr) |= FSMC_BCR_BURSTEN; } void fsmc_wait_timing_configuration_disable(uint32_t bcr) { FSMC_BCR(bcr) &= ~FSMC_BCR_WAITEN; } void fsmc_wait_timing_configuration_enable(uint32_t bcr) { FSMC_BCR(bcr) |= FSMC_BCR_WAITEN; } void fsmc_address_data_multiplexing_disable(uint32_t bcr) { FSMC_BCR(bcr) &= ~FSMC_BCR_MUXEN; } void fsmc_address_data_multiplexing_enable(uint32_t bcr) { FSMC_BCR(bcr) |= FSMC_BCR_MUXEN; } void fsmc_memory_bank_enable(uint32_t bcr) { FSMC_BCR(bcr) |= FSMC_BCR_MBKEN; } void fsmc_memory_bank_disable(uint32_t bcr) { FSMC_BCR(bcr) &= ~FSMC_BCR_MBKEN; } void fsmc_set_access_mode(uint32_t bank, uint32_t mode) { FSMC_BTR(bank) |= FSMC_BTR_ACCMODx(mode); } void fsmc_set_data_latency(uint32_t bank, uint32_t lat) { FSMC_BTR(bank) |= FSMC_BTR_DATLATx(lat); } void fsmc_set_clock_divide_ratio(uint32_t bank, uint32_t div) { FSMC_BTR(bank) |= FSMC_BTR_CLKDIVx(div); } void fsmc_set_turnaround_phase_duration(uint32_t bank, uint32_t duration) { FSMC_BTR(bank) |= FSMC_BTR_BUSTURNx(duration); } void fsmc_set_data_phase_duration(uint32_t bank, uint32_t duration) { FSMC_BTR(bank) |= FSMC_BTR_DATASTx(duration); } void fsmc_set_address_hold_phase_duration(uint32_t bank, uint32_t duration) { FSMC_BTR(bank) |= FSMC_BTR_ADDHLDx(duration); } void fsmc_set_address_setup_phase_duration(uint32_t bank, uint32_t duration) { FSMC_BTR(bank) |= FSMC_BTR_ADDSETx(duration); }
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #ifndef FSMCWR_H #define FSMCWR_H #define BANK1 0 void fsmc_write_burst_disable(uint32_t bcr); void fsmc_write_burst_enable(uint32_t bcr); void fsmc_extended_mode_disable(uint32_t bcr); void fsmc_extended_mode_enable(uint32_t bcr); void fsmc_write_disable(uint32_t bcr); void fsmc_write_enable(uint32_t bcr); void fsmc_wait_disable(uint32_t bcr); void fsmc_wait_enable(uint32_t bcr); void fsmc_wait_signal_polarity_low(uint32_t bcr); void fsmc_wait_signal_polarity_high(uint32_t bcr); void fsmc_wrapped_burst_mode_disable(uint32_t bcr); void fsmc_wrapped_burst_mode_enable(uint32_t bcr); void fsmc_burst_disable(uint32_t bcr); void fsmc_burst_enable(uint32_t bcr); void fsmc_wait_timing_configuration_disable(uint32_t bcr); void fsmc_wait_timing_configuration_enable(uint32_t bcr); void fsmc_address_data_multiplexing_disable(uint32_t bcr); void fsmc_address_data_multiplexing_enable(uint32_t bcr); void fsmc_memory_bank_enable(uint32_t bcr); void fsmc_memory_bank_disable(uint32_t bcr); void fsmc_set_access_mode(uint32_t bank, uint32_t mode); void fsmc_set_data_latency(uint32_t bank, uint32_t lat); void fsmc_set_clock_divide_ratio(uint32_t bank, uint32_t div); void fsmc_set_turnaround_phase_duration(uint32_t bank, uint32_t duration); void fsmc_set_data_phase_duration(uint32_t bank, uint32_t duration); void fsmc_set_address_hold_phase_duration(uint32_t bank, uint32_t duration); void fsmc_set_address_setup_phase_duration(uint32_t bank, uint32_t duration); #endif
/* $Id$ */ #include <stdlib.h> #include <stdint.h> #include <ili9341.h> #include <FreeRTOS.h> #include <task.h> #define LCD_COMM *(volatile uint16_t *)(0x60000000) #define LCD_DATA *(volatile uint16_t *)(0x60080000) inline void _delay_ms(uint32_t n) { for (volatile int i = 0; i < n * 80000; i++) __asm__("nop"); } inline void delay_ms(uint32_t n) { for (volatile int i = 0; i < n * 80000; i++) __asm__("nop"); } inline void lcd_write_command(uint8_t comm) { taskENTER_CRITICAL(); LCD_COMM = (uint16_t) (comm & 0xFF); taskEXIT_CRITICAL(); } inline void lcd_write_data(uint16_t data) { LCD_DATA = data; } inline void lcd_write_byte(uint8_t data) { taskENTER_CRITICAL(); LCD_DATA = (uint16_t) (data && 0xFF); taskEXIT_CRITICAL(); } inline inline void lcd_write_word(uint16_t w) { lcd_write_data((w >> 8) & 0xFF); lcd_write_data(w & 0xFF); } void lcd_soft_reset(void) { lcd_write_command(LCD_SWRESET); } void lcd_sleep_out(void) { lcd_write_command(LCD_SLPOUT); } void lcd_set_color_mode(uint8_t mode) { lcd_write_command(LCD_COLMOD); lcd_write_byte(mode); } void lcd_set_normal_mode(void) { lcd_write_command(LCD_NORON); } void lcd_set_display_on(void) { lcd_write_command(LCD_DISPON); } void lcd_set_display_off(void) { lcd_write_command(LCD_DISPOFF); } void lcd_set_brightness(uint8_t level) { lcd_write_command(LCD_WRDISBV); lcd_write_byte(level); } void lcd_set_frame_rate_normal(uint8_t divb, uint8_t rtnb) { lcd_write_command(LCD_FRMCTR1); lcd_write_byte(divb); lcd_write_byte(rtnb); } void lcd_set_frame_rate_idle(uint8_t divb, uint8_t rtnb) { lcd_write_command(LCD_FRMCTR2); lcd_write_byte(divb); lcd_write_byte(rtnb); } void lcd_set_frame_rate_partial(uint8_t divb, uint8_t rtnb) { lcd_write_command(LCD_FRMCTR3); lcd_write_byte(divb); lcd_write_byte(rtnb); } void lcd_set_memory_access(uint8_t mode) { lcd_write_command(LCD_MADCTL); lcd_write_byte(mode); } void lcd_setup(void) { lcd_soft_reset(); _delay_ms(150); lcd_sleep_out(); _delay_ms(250); lcd_write_command(LCD_PWCTR1); lcd_write_data(0x1B); lcd_write_command(LCD_PWCTR2); lcd_write_data(0x01); lcd_write_command(LCD_VMCTR1); lcd_write_data(0x30); lcd_write_data(0x30); lcd_write_command(LCD_VMOFCTR); lcd_write_data(0XB7); lcd_write_command(LCD_COLMOD); lcd_write_data(0x55); lcd_write_command(LCD_DISSET5); lcd_write_data(0x0A); lcd_write_data(0xA2); lcd_write_command(LCD_GAMSET); lcd_write_data(0x01); lcd_write_command(LCD_GMCTRP1); lcd_write_data(0x0F); lcd_write_data(0x2A); lcd_write_data(0x28); lcd_write_data(0x08); lcd_write_data(0x0E); lcd_write_data(0x08); lcd_write_data(0x54); lcd_write_data(0XA9); lcd_write_data(0x43); lcd_write_data(0x0A); lcd_write_data(0x0F); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_command(LCD_GMCTRN1); lcd_write_data(0x00); lcd_write_data(0x15); lcd_write_data(0x17); lcd_write_data(0x07); lcd_write_data(0x11); lcd_write_data(0x06); lcd_write_data(0x2B); lcd_write_data(0x56); lcd_write_data(0x3C); lcd_write_data(0x05); lcd_write_data(0x10); lcd_write_data(0x0F); lcd_write_data(0x3F); lcd_write_data(0x3F); lcd_write_data(0x0F); lcd_write_command(LCD_RASET); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x01); lcd_write_data(0x3f); lcd_write_command(LCD_CASET); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0xef); lcd_write_command(LCD_IDMOFF); lcd_set_normal_mode(); lcd_write_command(LCD_COLMOD); lcd_write_data(0x55); lcd_write_command(LCD_FRMCTR1); lcd_write_data(0x00); lcd_write_data(0x18); lcd_sleep_out(); delay_ms(120); lcd_set_display_on(); _delay_ms(100); } void lcd_addr_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { lcd_write_command(LCD_CASET); lcd_write_word(x0); lcd_write_word(x1); lcd_write_command(LCD_RASET); lcd_write_word(y0); lcd_write_word(y1); } void lcd_write_ram(uint16_t w, uint16_t n) { lcd_write_command(LCD_RAMWR); while (n--) lcd_write_data(w); } void lcd_write_rect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color) { lcd_addr_window(x, y, (x + w), (y + h)); uint16_t c565 = lcd_rgb2c(color); lcd_write_ram(c565, (w + 1) * (h + 1 ) ); } void lcd_clear(void) { lcd_write_rect(0, 0, LCD_WIDTH/2, LCD_HEIGHT, LCD_BLACK); lcd_write_rect(LCD_WIDTH/2, 0, LCD_WIDTH/2 + 1, LCD_HEIGHT, LCD_BLACK); } void lcd_draw_pixel(uint16_t x, uint16_t y, uint32_t color) { lcd_addr_window(x, y, x, y); uint16_t c565 = lcd_rgb2c(color); lcd_write_command(LCD_RAMWR); lcd_write_data(c565); } #define swap(a, b) { int16_t t = a; a = b; b = t; } void lcd_draw_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint32_t color) { int16_t steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { swap(x0, y0); swap(x1, y1); } if (x0 > x1) { swap(x0, x1); swap(y0, y1); } int16_t dx, dy; dx = x1 - x0; dy = abs(y1 - y0); int16_t err = dx / 2; int16_t ystep; if (y0 < y1) ystep = 1; else ystep = -1; while (x0 <= x1) { if (steep) { lcd_draw_pixel(y0, x0, color); } else { lcd_draw_pixel(x0, y0, color); } err -= dy; if (err < 0) { y0 += ystep; err += dx; } x0++; } } void lcd_draw_vline(int16_t x, int16_t y, int16_t l, uint16_t color) { lcd_write_rect(x, y, (l - 1), 0, color); } void lcd_draw_hline(int16_t x, int16_t y, int16_t l, uint16_t color) { lcd_write_rect(x, y, 0, (l - 1), color); } void lcd_draw_rest(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h, uint32_t color) { lcd_draw_hline(x1, y1, w, color); lcd_draw_vline(x1, y1, h, color); lcd_draw_hline((x1 + h) - 0, y1, w, color); lcd_draw_vline(x1, (y1 + w) - 0, h, color); } uint16_t lcd_rgb2c(uint32_t rgb) { return (uint16_t) (((rgb & 0xF80000) >> 19)| ((rgb & 0x00F800) >> 6) | ((rgb & 0x0000F8) << 8)); } void lcd_draw_char(uint16_t xbase, uint16_t ybase, font_t *font, uint8_t c) { if (c < font->start || c > (font->start + font->length)) c = ' '; c = c - font->start; uint16_t fg = lcd_rgb2c(LCD_WHITE); uint16_t bg = lcd_rgb2c(LCD_BLACK); lcd_addr_window(xbase, ybase, xbase + font->height - 1, ybase + font->width - 1); lcd_write_command(LCD_RAMWR); for (uint8_t w = font->width; w > 0; w--) { for (uint8_t h = font->height; h > 0; h--) { if ((font->bitmap[(c) * font->height + (h - 1)]) & (1 << (w - 1))) lcd_write_data(0xEFEF); else lcd_write_data(0x0000); } } } /* EOF */
#ifndef ILI9341_H #define ILI9341_H //#define LCD_COMM *(volatile uint8_t *)(0x60000000) //#define LCD_DATA *(volatile uint8_t *)(0x600E0000) #define LCD_SWRESET 0x01 /* Software Reset */ #define LCD_RDDID 0x04 /* Read Display ID */ #define LCD_RDDST 0x09 /* Read Display Status */ #define LCD_RDDPM 0x0A /* Read Display Power Mode */ #define LCD_RDDMADCTL 0x0B /* Read Display MADCTL */ #define LCD_RDDCOLMOD 0x0C /* Read Display Pixel Format */ #define LCD_RDDIM 0x0D /* Read Display Image Mode */ #define LCD_RDDSM 0x0E /* Read Display Signal Mode */ #define LCD_RDDSDR 0x0F /* Read Display Self-Diagnostic Result */ #define LCD_SLPIN 0x10 /* Sleep In */ #define LCD_SLPOUT 0x11 /* Sleep Out */ #define LCD_PTLON 0x12 /* Partial Display Mode On */ #define LCD_NORON 0x13 /* Normal Display Mode On */ #define LCD_DINVOFF 0x20 /* Display Inversion Off */ #define LCD_DINVON 0x21 /* Display Inversion On */ #define LCD_GAMSET 0x26 /* Gamma Set */ #define LCD_DISPOFF 0x28 /* Display Off */ #define LCD_DISPON 0x29 /* Display On */ #define LCD_CASET 0x2A /* Column Address Set */ #define LCD_RASET 0x2B /* Row Address Set */ #define LCD_RAMWR 0x2C /* Memory Write */ #define LCD_RGBSET 0x2D /* Color Setting for 4K, 65K and 262K */ #define LCD_RAMRD 0x2E /* Memory Read */ #define LCD_PTLAR 0x30 /* Partial Area */ #define LCD_VSCRDEF 0x33 /* Vertical Scrolling Definition */ #define LCD_TEOFF 0x34 /* Tearing Effect Line OFF */ #define LCD_TEON 0x35 /* Tearing Effect Line ON */ #define LCD_MADCTL 0x36 /* Memory Data Access Control */ #define LCD_VSCRSADD 0x37 /* Vertical Scrolling Start Address */ #define LCD_IDMOFF 0x38 /* Idle Mode Off */ #define LCD_IDMON 0x39 /* Idle Mode On */ #define LCD_COLMOD 0x3A /* Interface Pixel Format */ #define LCD_IFCTL 0xF6 #define LCD_DISCTRL 0xB6 // 0x3C Write_Memory_Continue // 0x3E Read_Memory_Continue // 0x44 Set_Tear_Scanline // 0x45 Get_Scanline // 0x51 Write Display Brightness #define LCD_WRDISBV 0x51 /* Write Display Brightness */ // 0x52 Read Display Brightness #define LCD_WRCTRLD 0x53 /* Write CTRL Display */ #define LCD_RDID1 0xDA /* Read ID1 Value */ #define LCD_RDID2 0xDB /* Read ID2 Value */ #define LCD_RDID3 0xDC /* Read ID3 Value */ #define LCD_IFMODE 0xB0 /* RGB Interface Signal Control */ #define LCD_FRMCTR1 0xB1 /* Frame Rate Control 0xIn normal mode/ Full colors) */ #define LCD_FRMCTR2 0xB2 /* Frame Rate Control (In Idle mode/ 8-colors) */ #define LCD_FRMCTR3 0xB3 /* Frame Rate Control 0xIn Partial mode/ full colors) */ #define LCD_DINVCTR 0xB4 /* Display Inversion Control */ // 0xB5 Blanking Porch Control #define LCD_DISSET5 0xB6 /* Display Function set 5 */ // 0xB7 Entry Mode Set #define LCD_PWCTR1 0xC0 /* Power Control 1 */ #define LCD_PWCTR2 0xC1 /* Power Control 2 */ #define LCD_PWCTR3 0xC2 /* Power Control 3 0xin Normal mode/ Full colors) */ #define LCD_PWCTR4 0xC3 /* Power Control 4 0xin Idle mode/ 8-colors) */ #define LCD_PWCTR5 0xC4 /* Power Control 5 0xin Partial mode/ full-colors) */ #define LCD_VMCTR1 0xC5 /* VCOM Control 1 */ #define LCD_VMOFCTR 0xC7 /* VCOM Offset Control */ #define LCD_WRID2 0xD1 /* Write ID2 Value */ #define LCD_WRID3 0xD2 /* Write ID3 Value */ #define LCD_NVFCTR1 0xD9 /* NVM Control Status */ #define LCD_NVFCTR2 0xDE /* NVM Read Command */ #define LCD_NVFCTR3 0xDF /* NVM Write Command */ #define LCD_GMCTRP1 0xE0 /* Gamma `+'polarity) Correction Characteristics Setting */ #define LCD_GMCTRN1 0xE1 /* Gamma `-'polarity Correction Characteristics Setting */ #define LCD_COLOR_MODE_RGB 5 #define LCD_FRAME_RATE_DIV0 0 #define LCD_FRAME_RATE_DIV2 1 #define LCD_FRAME_RATE_DIV4 2 #define LCD_FRAME_RATE_DIV8 3 #define LCD_FRAME_RATE_119HZ 0x10 #define LCD_FRAME_RATE_112HZ 0x11 #define LCD_FRAME_RATE_106HZ 0x12 #define LCD_FRAME_RATE_100HZ 0x13 #define LCD_FRAME_RATE_95HZ 0x14 #define LCD_FRAME_RATE_90HZ 0x15 #define LCD_FRAME_RATE_86HZ 0x16 #define LCD_FRAME_RATE_83HZ 0x17 #define LCD_FRAME_RATE_79HZ 0x18 #define LCD_FRAME_RATE_76HZ 0x19 #define LCD_FRAME_RATE_73HZ 0x1A #define LCD_FRAME_RATE_70HZ 0x1B #define LCD_FRAME_RATE_68HZ 0x1C #define LCD_FRAME_RATE_65HZ 0x1D #define LCD_FRAME_RATE_63HZ 0x1E #define LCD_FRAME_RATE_61HZ 0x1F #define LCD_MADCTL_MY 0x80 #define LCD_MADCTL_MX 0x40 #define LCD_MADCTL_MV 0x20 #define LCD_MADCTL_ML 0x10 #define LCD_MADCTL_RGB 0x08 #define LCD_MADCTL_BGR 0x00 #define LCD_MADCTL_MH 0x04 #define LCD_565BLACK 0x0000 #define LCD_565BLUE 0x001F #define LCD_565RED 0xF800 #define LCD_565GREEN 0x07E0 #define LCD_565CYAN 0x07FF #define LCD_565MAGENTA 0xF81F #define LCD_565YELLOW 0xFFE0 #define LCD_565WHITE 0xFFFF #define LCD_BLACK 0x000000 #define LCD_BLUE 0x0000FF #define LCD_BROWN 0xA05000 #define LCD_CHARCOAL 0x4F4F4F #define LCD_CREAM 0xE8D898 #define LCD_CYAN 0x00FFFF #define LCD_GOLD 0xFFAA00 #define LCD_GRAY 0x808080 #define LCD_GREEN 0x00FF00 #define LCD_LILAC 0xE06090 #define LCD_LIME 0xC0FF81 #define LCD_MAGENTA 0xFF00FF #define LCD_MAROON 0x700000 #define LCD_OLIVE 0x2A8307 #define LCD_ORANGE 0xFF8000 #define LCD_PINK 0xFF0080 #define LCD_PURPLE 0x703070 #define LCD_RED 0xFF0000 #define LCD_ROSE 0xFF6060 #define LCD_SALMON 0xFF0055 #define LCD_STEEL 0x3883A8 #define LCD_TAN 0xE0A860 #define LCD_VIOLET 0xB090D0 #define LCD_WHITE 0xFFFFFF #define LCD_YELLOW 0xFFFF00 #define LCD_WIDTH 240 #define LCD_HEIGHT 320 typedef struct font { uint8_t width; uint8_t height; uint8_t start; uint8_t length; const uint8_t *bitmap; } font_t; void lcd_soft_reset(void); void lcd_sleep_out(void); void lcd_set_color_mode(uint8_t mode); void lcd_set_normal_mode(void); void lcd_set_display_on(void); void lcd_set_display_off(void); void lcd_set_brightness(uint8_t level); void lcd_set_frame_rate_normal(uint8_t divb, uint8_t rtnb); void lcd_set_frame_rate_idle(uint8_t divb, uint8_t rtnb); void lcd_set_frame_rate_partial(uint8_t divb, uint8_t rtnb); void lcd_setup(void); void lcd_addr_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); void lcd_write_ram(uint16_t w, uint16_t n); void lcd_write_rect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color); void lcd_clear(void); void lcd_draw_pixel(uint16_t x, uint16_t y, uint32_t color); void lcd_draw_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint32_t color); void lcd_draw_vline(int16_t x, int16_t y, int16_t l, uint16_t color); void lcd_draw_hline(int16_t x, int16_t y, int16_t l, uint16_t color); void lcd_draw_rest(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h, uint32_t color); uint16_t lcd_rgb2c(uint32_t rgb); void lcd_draw_char(uint16_t xbase, uint16_t ybase, font_t *font, uint8_t c); #endif /* EOF */
#include <libopencm3/cm3/nvic.h> #include <libopencm3/cm3/systick.h> #include <libopencm3/cm3/dwt.h> #include <libopencm3/cm3/scb.h> #include <libopencm3/stm32/syscfg.h> #include <libopencm3/stm32/rcc.h> #include <libopencm3/stm32/gpio.h> #include <libopencm3/stm32/usart.h> #include <libopencm3/stm32/timer.h> #include <libopencm3/stm32/i2c.h> #include <libopencm3/stm32/spi.h> #include <libopencm3/stm32/rtc.h> #include <libopencm3/stm32/adc.h> #include <libopencm3/stm32/dma.h> #include <libopencm3/stm32/fsmc.h> #include <libopencm3/stm32/pwr.h> #include <libopencm3/stm32/rng.h> #include <libopencm3/stm32/can.h> #include <libopencm3/stm32/exti.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <wctype.h> #include <ctype.h> #include <locale.h> #include <wchar.h> #include <time.h> #include <syscall.h> #include <fsmcwr.h> #include <buffer.h> #include <uastdio.h> #include <ili9341.h> #include <console.h> #include <random.h> #include <rtc4xx.h> #include <xpt2046.h> #include <FreeRTOS.h> #include <task.h> #include <queue.h> #include <timers.h> void send_console_msg(uint8_t row, uint8_t col, uint8_t * str); void send_console_msg_from_isr(uint8_t row, uint8_t col, uint8_t * str); /* Object definition */ #define _IRQ2NVIC_PRIOR(x) ((x) << 4) #define UART_QUEUE_LEN 512 #define CONSOLE_QUEUE_LEN 8 xTaskHandle usart1_task_h; xTaskHandle usart3_task_h; xTaskHandle counter_task_h; xTaskHandle console_task_h; volatile QueueHandle_t usart1_q; volatile QueueHandle_t usart3_q; volatile QueueHandle_t console_q; #define CONSOLE_STR_LEN 32 #define STR_LEN 16 typedef struct console_message_t { uint8_t row; uint8_t col; uint8_t str[CONSOLE_STR_LEN + 1]; } console_message_t; /* Generic */ void delay(uint32_t n) { for (volatile int i = 0; i < n * 10; i++) __asm__("nop"); } void _delay_ms(uint32_t n) { for (volatile int i = 0; i < n * 80000; i++) __asm__("nop"); } /* RCC CLOCK */ static void clock_setup(void) { rcc_clock_setup_hse_3v3(&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_GPIOC); rcc_periph_clock_enable(RCC_GPIOD); rcc_periph_clock_enable(RCC_GPIOE); rcc_periph_clock_enable(RCC_SPI2); rcc_periph_clock_enable(RCC_SYSCFG); rcc_periph_clock_enable(RCC_FSMC); rcc_periph_clock_enable(RCC_TIM2); rcc_periph_clock_enable(RCC_TIM7); rcc_periph_clock_enable(RCC_USART1); rcc_periph_clock_enable(RCC_USART3); rcc_periph_clock_enable(RCC_PWR); rcc_periph_clock_enable(RCC_RTC); rcc_periph_clock_enable(RCC_RNG); rcc_periph_clock_enable(RCC_DAC); rcc_periph_clock_enable(RCC_DMA1); rcc_periph_clock_enable(RCC_DMA2); rcc_periph_clock_enable(RCC_ADC1); } /* USART generic */ inline bool usart_recv_is_ready(uint32_t usart) { return (USART_SR(usart) & USART_SR_RXNE); } inline bool usart_rx_int_is_enable(uint32_t usart) { return (USART_CR1(USART1) & USART_CR1_RXNEIE); } /* USART1 */ void usart1_setup(void) { usart_disable(USART1); nvic_enable_irq(NVIC_USART1_IRQ); gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9 | GPIO10); gpio_set_af(GPIOA, GPIO_AF7, GPIO9 | GPIO10); usart_set_baudrate(USART1, 115200); usart_set_databits(USART1, 8); usart_set_stopbits(USART1, USART_STOPBITS_1); usart_set_parity(USART1, USART_PARITY_NONE); usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); usart_set_mode(USART1, USART_MODE_TX_RX); usart_enable_rx_interrupt(USART1); usart_enable(USART1); } void usart1_isr(void) { uint8_t data = 0; BaseType_t xHigherPriorityTaskWoken; xHigherPriorityTaskWoken = pdTRUE; if (usart_rx_int_is_enable(USART1) && usart_recv_is_ready(USART1)) { data = usart_recv_blocking(USART1); xQueueSendFromISR(usart1_q, &data, &xHigherPriorityTaskWoken); } portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); } /* USART3 */ void usart3_setup(void) { usart_disable(USART3); nvic_enable_irq(NVIC_USART3_IRQ); gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO10 | GPIO11); gpio_set_af(GPIOB, GPIO_AF7, GPIO10 | GPIO11); usart_set_baudrate(USART3, 9600); usart_set_databits(USART3, 8); usart_set_stopbits(USART3, USART_STOPBITS_1); usart_set_parity(USART3, USART_PARITY_NONE); usart_set_flow_control(USART3, USART_FLOWCONTROL_NONE); usart_set_mode(USART3, USART_MODE_TX_RX); usart_enable_rx_interrupt(USART3); usart_enable(USART3); } void usart3_isr(void) { uint8_t data = 0; BaseType_t xHigherPriorityTaskWoken; xHigherPriorityTaskWoken = pdTRUE; if (usart_rx_int_is_enable(USART3) && usart_recv_is_ready(USART3)) { data = usart_recv_blocking(USART3); xQueueSendFromISR(usart3_q, &data, &xHigherPriorityTaskWoken); } portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); } /* FSMC */ #define FSMC_PD (GPIO4 | GPIO5 | GPIO7 | GPIO13 | GPIO14 | GPIO15 | GPIO0 | GPIO1 | GPIO8 | GPIO9 | GPIO10) #define FSMC_PE (GPIO7 | GPIO8 | GPIO9 | GPIO10 | GPIO11 | GPIO12 | GPIO13 | GPIO14 | GPIO15) void fsmc_setup(void) { gpio_mode_setup(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, FSMC_PD); gpio_set_output_options(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, FSMC_PD); gpio_set_af(GPIOD, GPIO_AF12, FSMC_PD); gpio_mode_setup(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, FSMC_PE); gpio_set_output_options(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, FSMC_PE); gpio_set_af(GPIOE, GPIO_AF12, FSMC_PE); fsmc_set_access_mode(BANK1, FSMC_BTx_ACCMOD_B); fsmc_set_data_latency(BANK1, 0); fsmc_set_clock_divide_ratio(BANK1, 0); fsmc_set_turnaround_phase_duration(BANK1, 0); fsmc_set_data_phase_duration(BANK1, 5); fsmc_set_address_hold_phase_duration(BANK1, 0); fsmc_set_address_setup_phase_duration(BANK1, 1); fsmc_address_data_multiplexing_disable(BANK1); fsmc_write_burst_disable(BANK1); fsmc_wrapped_burst_mode_disable(BANK1); fsmc_extended_mode_disable(BANK1); fsmc_write_enable(BANK1); fsmc_wait_signal_polarity_low(BANK1); fsmc_wait_timing_configuration_enable(BANK1); fsmc_wait_disable(BANK1); fsmc_memory_bank_enable(BANK1); } /* ADC1 */ static void __adc1_setup(void) { gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO0); gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO1); rcc_periph_clock_enable(RCC_ADC1); adc_set_clk_prescale(ADC_CCR_ADCPRE_BY2); adc_disable_scan_mode(ADC1); adc_set_single_conversion_mode(ADC1); adc_set_sample_time(ADC1, ADC_CHANNEL0, ADC_SMPR_SMP_3CYC); adc_enable_temperature_sensor(); uint8_t channels[16]; channels[0] = ADC_CHANNEL16; adc_set_resolution(ADC1, 12); adc_set_regular_sequence(ADC1, 1, channels); adc_set_multi_mode(ADC_CCR_MULTI_INDEPENDENT); adc_power_on(ADC1); //adc_start_conversion_regular(ADC1); //while (!adc_eoc(ADC1)); //reg16 = adc_read_regular(ADC1); } static void adc1_setup(void) { gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO0); gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO1); adc_set_clk_prescale(ADC_CCR_ADCPRE_BY2); adc_enable_scan_mode(ADC1); adc_set_continuous_conversion_mode(ADC1); adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28CYC); adc_enable_temperature_sensor(); uint8_t channels[16]; channels[0] = ADC_CHANNEL0; channels[1] = ADC_CHANNEL1; adc_set_resolution(ADC1, 12); adc_set_regular_sequence(ADC1, 2, channels); adc_set_multi_mode(ADC_CCR_MULTI_INDEPENDENT); adc_enable_dma(ADC1); adc_set_dma_continue(ADC1); adc_power_on(ADC1); adc_start_conversion_regular(ADC1); } uint16_t adc_res[32]; static void dma2_setup(void) { dma_stream_reset(DMA2, DMA_STREAM0); dma_set_peripheral_address(DMA2, DMA_STREAM0, (uint32_t) & ADC_DR(ADC1)); dma_set_memory_address(DMA2, DMA_STREAM0, (uint32_t) &adc_res[0]); dma_set_number_of_data(DMA2, DMA_STREAM0, 2); dma_set_dma_flow_control(DMA2, DMA_STREAM0); dma_channel_select(DMA2, DMA_STREAM0, DMA_SxCR_CHSEL_0); dma_set_priority(DMA2, DMA_STREAM0, DMA_SxCR_PL_HIGH); dma_set_peripheral_size(DMA2, DMA_STREAM0, DMA_SxCR_PSIZE_16BIT); dma_set_memory_size(DMA2, DMA_STREAM0, DMA_SxCR_MSIZE_16BIT); dma_enable_memory_increment_mode(DMA2, DMA_STREAM0); dma_enable_circular_mode(DMA2, DMA_STREAM0); //dma_clear_interrupt_flags(DMA2, DMA_STREAM0, DMA_ISR_FLAGS); //nvic_enable_irq(NVIC_DMA2_STREAM0_IRQ); //dma_enable_transfer_complete_interrupt(DMA2, DMA_STREAM0); dma_enable_stream(DMA2, DMA_STREAM0); } /* TASKs */ static void usart1_task(void *args __attribute__ ((unused))) { uint8_t c; while (1) { if (xQueueReceive(usart1_q, &c, 10) == pdPASS) { while (!usart_get_flag(USART1, USART_SR_TXE)) taskYIELD(); usart_send_blocking(USART1, c); } else { taskYIELD(); } } } #if 0 typedef struct location { float latitude, float longitude, float timestamp } loc_t; #endif static void usart_puts(uint32_t usart, uint8_t * str) { uint16_t i = 0; while (str[i] != 0) { usart_send_blocking(usart, str[i]); i++; } } uint16_t get_substr(uint8_t * src, uint8_t *dst, uint16_t len, uint8_t delim, uint8_t num) { uint16_t i = 0; uint16_t n = 0; uint16_t d = 0; while (src[i] != 0 || src[i] != '\r' || src[i] != '\n') { if (src[i] == delim) { n++; i++; } if (n > num) { dst[d] = 0; break; } if (src[i] == delim) continue; if (n == num && d < len) { dst[d] = src[i]; d++; } i++; } return d; } #define MAX_BUF_LEN 128 static void usart3_task(void *args __attribute__ ((unused))) { uint8_t c; static uint8_t buf[MAX_BUF_LEN + 2]; static uint8_t i = 0; static uint8_t dst[MAX_BUF_LEN]; float lon, lan = 0; while (1) { if (xQueueReceive(usart3_q, &c, 10) == pdPASS) { if (c == '\n' || c == '\r' || i >= MAX_BUF_LEN) { buf[i] = 0; i = 0; if (strlen(buf) > 0 && strstr(buf, "$GPGLL") != NULL) { //usart_puts(USART1, buf); //usart_puts(USART1, "\r\n"); //printf("%s\r\n", buf); get_substr(buf, dst, MAX_BUF_LEN - 1, ',', 1); lan = strtof(dst, NULL); get_substr(buf, dst, MAX_BUF_LEN - 1, ',', 2); if (dst[0] == 'N') lan = -lan; get_substr(buf, dst, MAX_BUF_LEN - 1, ',', 3); lon = strtof(dst, NULL); get_substr(buf, dst, MAX_BUF_LEN - 1, ',', 4); if (dst[0] == 'E') lon = -lon; //printf("%d %d\r\n", (int32_t) (lan * 10000), (int32_t) (lon * 10000)); console_message_t msg; msg.row = 11; msg.col = 0; snprintf(msg.str, CONSOLE_STR_LEN, "%+6d %+6d", (int32_t) (lan * 10), (int32_t) (lon * 10)); xQueueSend(console_q, &msg, portMAX_DELAY); } } else { buf[i] = c; i++; } } else { taskYIELD(); } } } void send_console_msg(uint8_t row, uint8_t col, uint8_t * str) { console_message_t msg; msg.row = row; msg.col = col; memcpy(msg.str, str, CONSOLE_STR_LEN); xQueueSend(console_q, &msg, portMAX_DELAY); } void send_console_msg_from_isr(uint8_t row, uint8_t col, uint8_t * str) { console_message_t msg; msg.row = row; msg.col = col; //memcpy(msg.str, str, CONSOLE_STR_LEN); uint8_t i = 0; while ((i < CONSOLE_STR_LEN) || (str[i] != 0)) { msg.str[i] = str[i]; i++; } BaseType_t xHigherPriorityTaskWoken = pdFALSE; xQueueSendFromISR(console_q, &msg, &xHigherPriorityTaskWoken); if (xHigherPriorityTaskWoken) { //taskYIELD_FROM_ISR(); } } #define MAX_TASK_COUNT 7 void print_stats(void) { volatile UBaseType_t task_count = MAX_TASK_COUNT; TaskStatus_t *status_array = pvPortMalloc(task_count * sizeof(TaskStatus_t)); if (status_array != NULL) { uint32_t total_time, stat_as_percentage; task_count = uxTaskGetSystemState(status_array, task_count, &total_time); total_time /= 100UL; if (total_time > 0) { uint16_t row = 3; for (UBaseType_t x = 0; x < task_count; x++) { stat_as_percentage = status_array[x].ulRunTimeCounter / total_time; if (stat_as_percentage >= 0UL) { #define CONSOLE_MAX_STAT_ROW 8 if (row < CONSOLE_MAX_STAT_ROW) { console_message_t msg; msg.row = row; msg.col = 0; snprintf(msg.str, CONSOLE_STR_LEN, "%-5s %3d %3u", status_array[x].pcTaskName, stat_as_percentage, status_array[x].usStackHighWaterMark); xQueueSend(console_q, &msg, portMAX_DELAY); } row++; } } } } vPortFree(status_array); } static void counter_task(void *args __attribute__ ((unused))) { uint32_t i = 0; uint8_t str[CONSOLE_STR_LEN + 1]; while (1) { print_stats(); //adc_start_conversion_regular(ADC1); //while (!adc_eoc(ADC1)); //uint16_t reg16 = adc_read_regular(ADC1); snprintf(str, CONSOLE_STR_LEN, "0x%08X %4u %4u", i, adc_res[0], adc_res[1]); send_console_msg(16, 0, str); vTaskDelay(pdMS_TO_TICKS(250)); i++; } } static void console_task(void *args __attribute__ ((unused))) { console_message_t msg; while (1) { if (xQueueReceive(console_q, &msg, 10) == pdPASS) { console_xyputs(&console, msg.row, msg.col, msg.str); } else { taskYIELD(); } } } /* MAIN */ int main(void) { clock_setup(); dma2_setup(); adc1_setup(); delay(100); fsmc_setup(); lcd_setup(); lcd_clear(); uint32_t i = 1; uint8_t str[STR_LEN + 1]; console_xyputs(&console, 0, 0, "FreeRTOS STM32-F4 CONSOLE V0.2"); console_xyputs(&console, 1, 0, "SYS READY>"); usart1_setup(); usart3_setup(); scb_set_priority_grouping(SCB_AIRCR_PRIGROUP_GROUP16_NOSUB); nvic_set_priority(NVIC_SYSTICK_IRQ, _IRQ2NVIC_PRIOR(15)); nvic_set_priority(NVIC_USART1_IRQ, configMAX_SYSCALL_INTERRUPT_PRIORITY + _IRQ2NVIC_PRIOR(1)); nvic_set_priority(NVIC_USART3_IRQ, configMAX_SYSCALL_INTERRUPT_PRIORITY + _IRQ2NVIC_PRIOR(2)); usart1_q = xQueueCreate(UART_QUEUE_LEN, sizeof(uint8_t)); usart3_q = xQueueCreate(UART_QUEUE_LEN, sizeof(uint8_t)); console_q = xQueueCreate(CONSOLE_QUEUE_LEN, sizeof(console_message_t)); xTaskCreate(usart1_task, "UAR1", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, usart1_task_h); xTaskCreate(usart3_task, "UAR3", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, usart3_task_h); xTaskCreate(counter_task, "CNTR", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, counter_task_h); xTaskCreate(console_task, "CONS", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, console_task_h); vTaskStartScheduler(); return 0; } /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #include <FreeRTOS.h> #include <task.h> #include <libopencm3/stm32/rcc.h> #include <libopencm3/stm32/gpio.h> #include <libopencm3/cm3/nvic.h> extern void vPortSVCHandler(void) __attribute__ ((naked)); extern void xPortPendSVHandler(void) __attribute__ ((naked)); extern void xPortSysTickHandler(void); __attribute__((used)) void sv_call_handler(void) { vPortSVCHandler(); } __attribute__((used)) void pend_sv_handler(void) { xPortPendSVHandler(); } __attribute__((used)) void sys_tick_handler(void) { xPortSysTickHandler(); } /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #include <libopencm3/stm32/rng.h> #include <stdlib.h> void rng_enable_interrupt(void) { RNG_CR |= RNG_CR_IE; } void rng_disable_interrupt(void) { RNG_CR &= ~RNG_CR_IE; } #if 0 void rng_enable(void) { RNG_CR |= RNG_CR_RNGEN; } void rng_disable(void) { RNG_CR &= ~RNG_CR_RNGEN; } #endif uint32_t rng_random(void) { static uint32_t last_value; static uint32_t new_value; uint32_t error = 0; error = RNG_SR_SEIS | RNG_SR_CEIS; while (new_value == last_value) { if (((RNG_SR & error) == 0) && ((RNG_SR & RNG_SR_DRDY) == 1)) { new_value = RNG_DR; } } last_value = new_value; return new_value; } /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #ifndef _RANDOM_H_ICU_ #define _RANDOM_H_ICU_ void rng_enable_interrupt(void); void rng_disable_interrupt(void); #if 0 void rng_enable(void); void rng_disable(void); #endif uint32_t rng_random(void); #endif /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #include <libopencm3/stm32/rcc.h> #include <libopencm3/stm32/rtc.h> #include <libopencm3/stm32/pwr.h> #include <stdlib.h> #include <rtc4xx.h> /* Sample: void rtc_init(void) { pwr_backup_domain_enable_write(); rcc_backup_domain_software_reset(); rcc_external_lowspeed_oscillator_enable(); rcc_rtc_clock_enable(); rcc_rtc_clock_source_selection(RCC_BDCR_RTCSEL_LSE); rtc_write_protection_disable(); rtc_set_calibration_output_1hz(); rtc_write_protection_disable(); rtc_calibration_output_enable(); rtc_init_mode_enable(); rtc_write_prescaler(0x07, 0xFF); rtc_set_24h_format(); rtc_init_mode_disable(); rtc_write_protection_enable(); pwr_backup_domain_disable_write(); } */ void pwr_backup_domain_enable_write(void) { PWR_CR |= PWR_CR_DBP; } void pwr_backup_domain_disable_write(void) { PWR_CR &= ~PWR_CR_DBP; } void rcc_backup_domain_software_reset(void) { RCC_BDCR |= RCC_BDCR_BDRST; RCC_BDCR &= ~RCC_BDCR_BDRST; } void rcc_external_lowspeed_oscillator_enable(void) { RCC_BDCR |= RCC_BDCR_LSEON; while (!(RCC_BDCR & RCC_BDCR_LSERDY)); } void rcc_rtc_clock_enable(void) { RCC_BDCR |= RCC_BDCR_RTCEN; } void rcc_rtc_clock_disable(void) { RCC_BDCR &= ~RCC_BDCR_RTCEN; } void rcc_rtc_clock_source_selection(uint32_t source) { uint32_t reg = RCC_BDCR; reg &= ~(RCC_BDCR_RTCSEL_MASK << RCC_BDCR_RTCSEL_SHIFT); reg |= (source & RCC_BDCR_RTCSEL_MASK) << RCC_BDCR_RTCSEL_SHIFT; RCC_BDCR = reg; } void rtc_write_protection_disable(void) { RTC_WPR = 0xCA; RTC_WPR = 0x53; } void rtc_write_protection_enable(void) { RTC_WPR = 0xFF; } void rtc_set_calibration_output_1hz(void) { RTC_CR |= RTC_CR_COSEL; } void rtc_set_calibration_output_512hz(void) { RTC_CR &= ~RTC_CR_COSEL; } void rtc_calibration_output_enable(void) { RTC_CR |= RTC_CR_COE; } void rtc_calibration_output_disable(void) { RTC_CR &= ~RTC_CR_COE; } void rtc_write_prescaler(uint32_t sync, uint32_t async) { RTC_PRER = (sync << RTC_PRER_PREDIV_S_SHIFT); RTC_PRER |= (async << RTC_PRER_PREDIV_A_SHIFT); } void rtc_set_24h_format(void) { uint32_t reg = RTC_TR; reg &= ~RTC_TR_PM; RTC_TR = reg; } void rtc_set_12h_format(void) { uint32_t reg = RTC_TR; reg |= RTC_TR_PM; RTC_TR = reg; } void rtc_init_mode_enable(void) { RTC_ISR |= RTC_ISR_INIT; while (!(RTC_ISR & RTC_ISR_INITF)); } void rtc_init_mode_disable(void) { RTC_ISR &= ~RTC_ISR_INIT; while (RTC_ISR & RTC_ISR_INITF); } void rtc_register_synchronization(void) { RTC_ISR &= ~(RTC_ISR_RSF); while (RTC_ISR & RTC_ISR_RSF); } void rtc_set_time_register(uint32_t tr) { pwr_backup_domain_enable_write(); rtc_write_protection_disable(); rtc_init_mode_enable(); RTC_TR = tr; rtc_register_synchronization(); rtc_init_mode_disable(); rtc_write_protection_enable(); pwr_backup_domain_disable_write(); } void rtc_set_date_register(uint32_t dr) { pwr_backup_domain_enable_write(); rtc_write_protection_disable(); rtc_init_mode_enable(); RTC_DR = dr; rtc_register_synchronization(); rtc_init_mode_disable(); rtc_write_protection_enable(); pwr_backup_domain_disable_write(); } /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #ifndef RTC4XX_H_XYZ #define RTC4XX_H_XYZ void pwr_backup_domain_enable_write(void); void pwr_backup_domain_disable_write(void); void rcc_backup_domain_software_reset(void); void rcc_external_lowspeed_oscillator_enable(void); void rcc_rtc_clock_enable(void); void rcc_rtc_clock_disable(void); void rcc_rtc_clock_source_selection(uint32_t source); void rtc_write_protection_disable(void); void rtc_write_protection_enable(void); void rtc_set_calibration_output_1hz(void); void rtc_set_calibration_output_512hz(void); void rtc_calibration_output_enable(void); void rtc_calibration_output_disable(void); void rtc_write_prescaler(uint32_t async, uint32_t sync); void rtc_set_24h_format(void); void rtc_set_12h_format(void); void rtc_init_mode_enable(void); void rtc_init_mode_disable(void); void rtc_register_synchronization(void); void rtc_set_time_register(uint32_t tr); void rtc_set_date_register(uint32_t dr); #endif /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #include <stdlib.h> #include <reent.h> #include <sys/stat.h> #include <sys/errno.h> #include <libopencm3/stm32/usart.h> #include <errno.h> #include <FreeRTOS.h> #include <task.h> #include <queue.h> #include <syscall.h> extern QueueHandle_t usart1_q; #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; } int _exit() { 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) { uint8_t data = 0; 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++) { xQueueSend(usart1_q, &ptr[i], portMAX_DELAY); } 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 *_sbrk(int incr) { extern const void *_heap; extern const void *_eheap; void *prev_heap_ptr; static void *heap_ptr; if (heap_ptr == 0) { heap_ptr = (void *)&_heap; } void * next_heap_ptr = heap_ptr + incr; if (next_heap_ptr >= (void *) &_eheap) { errno = ENOMEM; return NULL; } prev_heap_ptr = heap_ptr; heap_ptr = next_heap_ptr; return (void *)prev_heap_ptr; } /* EOF */
#include <stdlib.h> __attribute__((always_inline)) static inline uint32_t __get_LR(void) { register uint32_t result; __asm volatile ("mov %0, lp\n" : "=r" (result)); return result; } __attribute__((always_inline)) static inline uint32_t __get_SP(void) { register uint32_t result; __asm volatile ("mov %0, sp\n" : "=r" (result)); return result; } /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <wctype.h> #include <ctype.h> #include <locale.h> #include <wchar.h> #include <stdbool.h> #include <string.h> #include <unistd.h> #include <syscall.h> #include <buffer.h> #include <uastdio.h> #define BUFFER_SIZE 256 buffer_t stdin_buffer; buffer_t stdout_buffer; static uint8_t stdin_buffer_data[BUFFER_SIZE]; static uint8_t stdout_buffer_data[BUFFER_SIZE]; void io_setup(void) { buffer_init(&stdin_buffer, stdin_buffer_data, sizeof(stdin_buffer_data)); buffer_init(&stdout_buffer, stdout_buffer_data, sizeof(stdout_buffer_data)); } /* EOF */
#ifndef UART_STDIO_H_ITU #define UART_STDIO_H_ITU #define BUFFER_SIZE 256 extern buffer_t stdin_buffer; extern buffer_t stdout_buffer; void io_setup(void); #endif
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #include <libopencm3/stm32/gpio.h> #include <libopencm3/stm32/spi.h> #include <stdlib.h> #include <xpt2046.h> void ts_spi_setup(void) { gpio_mode_setup(TS_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, TS_SCL_PIN | TS_CS_PIN | TS_MO_PIN | TS_MI_PIN); gpio_set_af(TS_SPI_PORT, GPIO_AF5, TS_SCL_PIN | TS_CS_PIN | TS_MO_PIN | TS_MI_PIN); gpio_set_output_options(TS_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, TS_MO_PIN | TS_SCL_PIN | TS_CS_PIN); spi_reset(TS_SPI); spi_disable(TS_SPI); spi_init_master(TS_SPI, SPI_CR1_BAUDRATE_FPCLK_DIV_128, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE, SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST); spi_set_full_duplex_mode(TS_SPI); spi_disable_software_slave_management(TS_SPI); spi_set_nss_high(TS_SPI); spi_set_master_mode(TS_SPI); spi_enable_ss_output(TS_SPI); spi_disable_crc(TS_SPI); spi_enable(TS_SPI); } uint16_t ts_get_data16(uint8_t command) { spi_xfer(TS_SPI, command); uint16_t res1 = spi_xfer(TS_SPI, 0x00); uint16_t res2 = spi_xfer(TS_SPI, 0x00); return ((res1 << 8) | (res2 && 0xFF)) >> 4; } uint16_t ts_get_x_raw(void) { int16_t res = 0; for (uint8_t i = 0; i < TS_EVAL_COUNT; i++) { res += ts_get_data16(TS_COMM_X_DPOS); } return res / TS_EVAL_COUNT; } uint16_t ts_get_y_raw(void) { int16_t res = 0; for (uint8_t i = 0; i < TS_EVAL_COUNT; i++) { res += ts_get_data16(TS_COMM_Y_DPOS); } return res / TS_EVAL_COUNT; } uint16_t ts_get_x(void) { uint16_t res = ts_get_x_raw(); if (res >= TS_X_MAX_EDGE) return TS_X_SCREEN_MAX; if (res <= TS_X_MIN_EDGE) return TS_X_SCREEN_MIN; res = (TS_X_SCREEN_MAX * (res - TS_X_MIN_EDGE)) / (TS_X_MAX_EDGE - TS_X_MIN_EDGE); return TS_X_SCREEN_MAX - res; } uint16_t ts_get_y(void) { uint16_t res = ts_get_y_raw(); if (res >= TS_Y_MAX_EDGE) return TS_Y_SCREEN_MIN; if (res <= TS_Y_MIN_EDGE) return TS_Y_SCREEN_MIN; res = (TS_Y_SCREEN_MAX * (res - TS_Y_MIN_EDGE)) / (TS_Y_MAX_EDGE - TS_Y_MIN_EDGE); return res; } uint16_t ts_get_z1_raw(void) { uint16_t res = 0; for (uint8_t i = 0; i < TS_EVAL_COUNT; i++) { res += ts_get_data16(TS_COMM_Z1_POS); } return res / TS_EVAL_COUNT; } uint16_t ts_get_z2_raw(void) { uint16_t res = 0; for (uint8_t i = 0; i < TS_EVAL_COUNT; i++) { res += ts_get_data16(TS_COMM_Z2_POS); } return res / TS_EVAL_COUNT; } /* EOF */
/* Author, Copyright: Oleg Borodin <onborodin@gmail.com> 2018 */ #ifndef XPT2046_H_XYZ #define XPT2046_H_XYZ #define TS_SPI SPI2 #define TS_SPI_PORT GPIOB #define TS_MO_PIN GPIO15 #define TS_MI_PIN GPIO14 #define TS_SCL_PIN GPIO13 #define TS_CS_PIN GPIO12 #define TS_SB (1 << 7) #define TS_A2 (1 << 6) #define TS_A1 (1 << 5) #define TS_A0 (1 << 4) #define TS_MODE8 (1 << 3) #define TS_MODE12 (0 << 3) #define TS_SER (1 << 2) #define TS_DFR (0 << 2) #define TS_PD1 (1 << 1) #define TS_PD0 (1 << 0) #define TS_COMM_Y_SPOS (TS_MODE12 | TS_SER | TS_SB | TS_A0) #define TS_COMM_X_SPOS (TS_MODE12 | TS_SER | TS_SB | TS_A2 | TS_A0) #define TS_COMM_Y_DPOS (TS_MODE12 | TS_SB | TS_A0) #define TS_COMM_X_DPOS (TS_MODE12 | TS_SB | TS_A2 | TS_A0) #define TS_COMM_Z1_POS (TS_MODE12 | TS_SB | TS_A1 | TS_A0) #define TS_COMM_Z2_POS (TS_MODE12 | TS_SB | TS_A2) #define TS_COMM_TEMP (TS_MODE12 | TS_SB) #define TS_EVAL_COUNT 5 #define TS_X_MIN_EDGE 128 #define TS_X_MAX_EDGE 1904 #define TS_Y_MIN_EDGE 96 #define TS_Y_MAX_EDGE 1856 #define TS_X_SCREEN_MIN 0 #define TS_X_SCREEN_MAX 239 #define TS_Y_SCREEN_MIN 0 #define TS_Y_SCREEN_MAX 319 void ts_spi_setup(void); uint16_t ts_get_data16(uint8_t command); uint16_t ts_get_x_raw(void); uint16_t ts_get_y_raw(void); uint16_t ts_get_x(void); uint16_t ts_get_y(void); uint16_t ts_get_z1_raw(void); uint16_t ts_get_z2_raw(void); #endif /* EOF */
/* Generic linker script for STM32 targets using libopencm3. */
MEMORY {
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}
/* Enforce emmition of the vector table. */
EXTERN(vector_table)
/* Define the entry point of the output file. */
ENTRY(reset_handler)
SECTIONS {
.text : {
KEEP(*(.vectors)) /* Vector table */
*(.text*) /* Program code */
. = ALIGN(4);
*(.rodata*) /* Read-only data */
. = ALIGN(4);
} >FLASH
/* C++ Static constructors/destructors, also used for __attribute__
* ((constructor)) and the likes */
.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
/*
* Another section used by C++ stuff, appears when using newlib with
* 64bit (long long) printf support
*/
.ARM.extab : {
*(.ARM.extab*)
} >FLASH
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
. = ALIGN(4);
__text_end = .;
.data : {
__data_start = .;
_sdata = .;
_data = .;
*(.data*) /* Read-write initialized data */
. = ALIGN(4);
__data_end = . ;
_edata = . ;
} >SRAM AT >FLASH
_data_loadaddr = LOADADDR(.data);
.bss : {
__bss_start = .;
__bss_start__ = .;
*(.bss*) /* Read-write zero initialized data */
*(COMMON)
. = ALIGN(4);
__bss_end = .;
__bss_end__ = .;
_ebss = .;
} >SRAM
/*
* The .eh_frame section appears to be used for C++ exception handling.
* You may need to fix this if you're using C++.
*/
/* /DISCARD/ : { *(.eh_frame) } */
. = ALIGN(4);
__end = .;
_heap = .;
}
PROVIDE(__rtos_heap_size = LENGTH(SRAM) - 2048);
PROVIDE(_eheap = ORIGIN(SRAM) + LENGTH(SRAM));
PROVIDE(_stack = ORIGIN(SRAM) + LENGTH(SRAM));
/* EOF */