tsoftuart: add a softare timer base UART driver, and example.
This commit is contained in:
		
							parent
							
								
									05da9151ee
								
							
						
					
					
						commit
						5ab0d05768
					
				
					 8 changed files with 349 additions and 0 deletions
				
			
		
							
								
								
									
										1
									
								
								examples/tsoftuart/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								examples/tsoftuart/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					!local.mk
 | 
				
			||||||
							
								
								
									
										7
									
								
								examples/tsoftuart/FreeRTOSConfig.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								examples/tsoftuart/FreeRTOSConfig.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					#define configUSE_TRACE_FACILITY 1
 | 
				
			||||||
 | 
					#define configGENERATE_RUN_TIME_STATS 1
 | 
				
			||||||
 | 
					#define portGET_RUN_TIME_COUNTER_VALUE() (RTC.COUNTER)
 | 
				
			||||||
 | 
					#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Use the defaults for everything else */
 | 
				
			||||||
 | 
					#include_next<FreeRTOSConfig.h>
 | 
				
			||||||
							
								
								
									
										13
									
								
								examples/tsoftuart/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								examples/tsoftuart/Makefile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					# Makefile for tsfotuart example
 | 
				
			||||||
 | 
					PROGRAM=tsoftuart
 | 
				
			||||||
 | 
					EXTRA_COMPONENTS=extras/dhcpserver extras/wificfg extras/mactimer extras/tsoftuart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# For the mDNS responder included with lwip:
 | 
				
			||||||
 | 
					EXTRA_CFLAGS += -DLWIP_MDNS_RESPONDER=1 -DLWIP_NUM_NETIF_CLIENT_DATA=1 -DLWIP_NETIF_EXT_STATUS_CALLBACK=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Avoid writing the wifi state to flash when using wificfg.
 | 
				
			||||||
 | 
					EXTRA_CFLAGS += -DWIFI_PARAM_SAVE=0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXTRA_CFLAGS += -DWIFICFG_CLIENT_TASK=1 -DWIFICFG_IRAM_TEST=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include ../../common.mk
 | 
				
			||||||
							
								
								
									
										1
									
								
								examples/tsoftuart/local.mk
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								examples/tsoftuart/local.mk
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					FLASH_SIZE ?= 32
 | 
				
			||||||
							
								
								
									
										75
									
								
								examples/tsoftuart/tsoftuart.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								examples/tsoftuart/tsoftuart.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,75 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Example timer based software UART drive.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2019 OurAirQuality.org
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0, January 2004 (the
 | 
				
			||||||
 | 
					 * "License"); you may not use this file except in compliance with the
 | 
				
			||||||
 | 
					 * License.  You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
				
			||||||
 | 
					 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
				
			||||||
 | 
					 * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
 | 
				
			||||||
 | 
					 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
				
			||||||
 | 
					 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
				
			||||||
 | 
					 * DEALINGS WITH THE SOFTWARE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <espressif/esp_common.h>
 | 
				
			||||||
 | 
					#include <espressif/user_interface.h>
 | 
				
			||||||
 | 
					#include <esp/uart.h>
 | 
				
			||||||
 | 
					#include <FreeRTOS.h>
 | 
				
			||||||
 | 
					#include <task.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lwip/sockets.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "wificfg/wificfg.h"
 | 
				
			||||||
 | 
					#include "tsoftuart/tsoftuart.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tsoftuart_task(void *pvParameters)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Initialize the UART Tx. */
 | 
				
			||||||
 | 
					    uint32_t tx_pin = *(uint32_t *)pvParameters;
 | 
				
			||||||
 | 
					    struct tsoftuart *uart = tsoftuart_init(tx_pin, 9600);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    for (;;) {
 | 
				
			||||||
 | 
					        /* Reset the timing error records. */
 | 
				
			||||||
 | 
					        uart->output_queue_error_low = 0;
 | 
				
			||||||
 | 
					        uart->output_queue_error_high = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        char str[] = "Hello 0123456789 abcdefghijklmnopqrstuvwxyz\r\n";
 | 
				
			||||||
 | 
					        for (size_t i = 0; i < strlen(str); i++) {
 | 
				
			||||||
 | 
					            tsoftuart_putc(uart, str[i]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Check the timing error. */
 | 
				
			||||||
 | 
					        if (uart->output_queue_error_high > 2 || uart->output_queue_error_low < -2) {
 | 
				
			||||||
 | 
					            tsoftuart_write(uart, "X\r\n", 3);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vTaskDelay(200 / portTICK_PERIOD_MS);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void user_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uart_set_baud(0, 115200);
 | 
				
			||||||
 | 
					    printf("SDK version:%s\n", sdk_system_get_sdk_version());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wificfg_init(80, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Start two tasks writing to different pins. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static uint32_t tx_pin1 = 1;
 | 
				
			||||||
 | 
					    xTaskCreate(&tsoftuart_task, "tsoftuart1", 256, &tx_pin1, 1, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static uint32_t tx_pin2 = 2;
 | 
				
			||||||
 | 
					    xTaskCreate(&tsoftuart_task, "tsoftuart2", 256, &tx_pin2, 1, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								extras/tsoftuart/component.mk
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								extras/tsoftuart/component.mk
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					# Component makefile for extras/tsoftuart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Expected anyone using tsoftuart includes it as 'tsoftuart/tsoftuart.h'
 | 
				
			||||||
 | 
					INC_DIRS += $(tsoftuart_ROOT)..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# args for passing into compile rule generation
 | 
				
			||||||
 | 
					tsoftuart_INC_DIR =
 | 
				
			||||||
 | 
					tsoftuart_SRC_DIR = $(tsoftuart_ROOT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(eval $(call component_compile_rules,tsoftuart))
 | 
				
			||||||
							
								
								
									
										195
									
								
								extras/tsoftuart/tsoftuart.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								extras/tsoftuart/tsoftuart.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,195 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Software timer based UART driver.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 to 2019 OurAirQuality.org
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0, January 2004 (the
 | 
				
			||||||
 | 
					 * "License"); you may not use this file except in compliance with the
 | 
				
			||||||
 | 
					 * License.  You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
				
			||||||
 | 
					 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
				
			||||||
 | 
					 * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
 | 
				
			||||||
 | 
					 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
				
			||||||
 | 
					 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
				
			||||||
 | 
					 * DEALINGS WITH THE SOFTWARE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <esp/uart.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <espressif/esp_system.h>
 | 
				
			||||||
 | 
					#include "FreeRTOS.h"
 | 
				
			||||||
 | 
					#include "task.h"
 | 
				
			||||||
 | 
					#include "tsoftuart/tsoftuart.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * The design builds a sequence of UART output transitions - the delay between
 | 
				
			||||||
 | 
					 * each toggling of the output. This sequence is then followed by a timer and
 | 
				
			||||||
 | 
					 * the timer handler toggles the state and resets the timer for the next
 | 
				
			||||||
 | 
					 * transition until done. This design avoids the code having to spin to
 | 
				
			||||||
 | 
					 * implement delays, and avoid having to disable interrupts for more reliable
 | 
				
			||||||
 | 
					 * timing.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The MAC timer interrupt is used here as it has a high priority which helps
 | 
				
			||||||
 | 
					 * keep accurate output transition times. The MAC timer interrupt is a NMI and
 | 
				
			||||||
 | 
					 * the handler needs to take care not to interact widely. The handler only
 | 
				
			||||||
 | 
					 * accesses the timer queue, which has already been initialized.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This software UART is not completely reliable, but might suit debug output
 | 
				
			||||||
 | 
					 * or communication that has an error detection layer, and it is more reliable
 | 
				
			||||||
 | 
					 * at lower baud rates. While it can run up to 115200 baud it is not very
 | 
				
			||||||
 | 
					 * reliable at these higher rates. It is not uncommon for the MAC timer
 | 
				
			||||||
 | 
					 * handler to be delayed 20us, so at UART baud rates above 19200 errors are
 | 
				
			||||||
 | 
					 * expected. This driver attempts to measure the timing errors and this can be
 | 
				
			||||||
 | 
					 * used to help detect when timing errors have occurred.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void IRAM output_handler(void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    tsoftuart_t *uart = arg;
 | 
				
			||||||
 | 
					    uint32_t tail = uart->output_queue_tail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    do {
 | 
				
			||||||
 | 
					        uint32_t state = uart->output_queue_state ^ 1;
 | 
				
			||||||
 | 
					        uint64_t current = mactime_get_count();
 | 
				
			||||||
 | 
					        gpio_write(uart->tx_pin, state);
 | 
				
			||||||
 | 
					        uart->output_queue_state = state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (tail == 0) {
 | 
				
			||||||
 | 
					            // First transition.
 | 
				
			||||||
 | 
					            uart->output_start_time = current;
 | 
				
			||||||
 | 
					            uart->output_expected_time = current;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* The difference can be negative because the delay is skipped
 | 
				
			||||||
 | 
					         * if very short, see below. */
 | 
				
			||||||
 | 
					        int32_t err = current - uart->output_expected_time;
 | 
				
			||||||
 | 
					        if (err > uart->output_queue_error_high) {
 | 
				
			||||||
 | 
					            uart->output_queue_error_high = err;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (err < uart->output_queue_error_low) {
 | 
				
			||||||
 | 
					            uart->output_queue_error_low = err;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (tail >= uart->output_queue_head) {
 | 
				
			||||||
 | 
					            // Done.
 | 
				
			||||||
 | 
					            uart->output_queue_tail = tail;
 | 
				
			||||||
 | 
					            uart->output_done = 1;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Offset from the start. */
 | 
				
			||||||
 | 
					        uint32_t next = uart->output_queue[tail++];
 | 
				
			||||||
 | 
					        uint64_t target = uart->output_start_time + next;
 | 
				
			||||||
 | 
					        uart->output_expected_time = target;
 | 
				
			||||||
 | 
					        /* Target an earlier time, that would not give an error if
 | 
				
			||||||
 | 
					         * actually met, to give more room for the response delay. */
 | 
				
			||||||
 | 
					        target -= 4;
 | 
				
			||||||
 | 
					        int64_t diff = target - current;
 | 
				
			||||||
 | 
					        if (diff >= 0) {
 | 
				
			||||||
 | 
					            uart->output_queue_tail = tail;
 | 
				
			||||||
 | 
					            mactime_add_pending(&uart->output_mactimer, target);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } while(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void tsoftuart_putc(tsoftuart_t *uart, uint8_t ch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uart->output_queue_state = 1;
 | 
				
			||||||
 | 
					    gpio_write(uart->tx_pin, uart->output_queue_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uart->output_queue_head = 0;
 | 
				
			||||||
 | 
					    uart->output_queue_tail = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uart->output_queue_error_high = 0;
 | 
				
			||||||
 | 
					    uart->output_queue_error_low = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uart->output_done = 0;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    uint32_t state = 0;
 | 
				
			||||||
 | 
					    uint32_t count = 1;
 | 
				
			||||||
 | 
					    size_t head = 0;
 | 
				
			||||||
 | 
					    uint32_t cumulative = 0;
 | 
				
			||||||
 | 
					    uint32_t td = uart->td;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (size_t i = 0; i < 8; i++) {
 | 
				
			||||||
 | 
					        if ((ch & 1) == state) {
 | 
				
			||||||
 | 
					            /* No change */
 | 
				
			||||||
 | 
					            count++;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            cumulative += count * td;
 | 
				
			||||||
 | 
					            uart->output_queue[head++] = (cumulative + 128) >> 8;
 | 
				
			||||||
 | 
					            state ^= 1;
 | 
				
			||||||
 | 
					            count = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        ch >>= 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (state == 0) {
 | 
				
			||||||
 | 
					        cumulative += count * td;
 | 
				
			||||||
 | 
					        uart->output_queue[head++] = (cumulative + 128) >> 8;
 | 
				
			||||||
 | 
					        state ^= 1;
 | 
				
			||||||
 | 
					        count = 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uart->output_queue_head = head;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Trigger the first transition in the future. */
 | 
				
			||||||
 | 
					    mactimer_arm(&uart->output_mactimer, 20);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Wait until the transmittions is expected to have completed. */
 | 
				
			||||||
 | 
					    uint32_t delay = (td * 11 + 128) >> 8;
 | 
				
			||||||
 | 
					    vTaskDelay(((delay / 1000) + portTICK_PERIOD_MS) / portTICK_PERIOD_MS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Double check that it is done. There is a possibility that the timer has
 | 
				
			||||||
 | 
					     * failed to trigger, and this needed to be detected and the timer removed
 | 
				
			||||||
 | 
					     * from the pending list before retrying. */
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					    for (i = 0; uart->output_done == 0 && i < 10; i++) {
 | 
				
			||||||
 | 
					        vTaskDelay(1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (uart->output_done == 0) {
 | 
				
			||||||
 | 
					        /* Remove the timer. */
 | 
				
			||||||
 | 
					        mactimer_disarm(&uart->output_mactimer);
 | 
				
			||||||
 | 
					        /* Set the output high */
 | 
				
			||||||
 | 
					        gpio_write(uart->tx_pin, 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ssize_t tsoftuart_write(tsoftuart_t *uart, const void *ptr, size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    for(int i = 0; i < len; i++) {
 | 
				
			||||||
 | 
					        tsoftuart_putc(uart, ((char *)ptr)[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return len;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tsoftuart_t *tsoftuart_init(uint8_t tx_pin, uint32_t baud_rate)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    tsoftuart_t *uart = malloc(sizeof(tsoftuart_t));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (uart) {
 | 
				
			||||||
 | 
					        uart->tx_pin = tx_pin;
 | 
				
			||||||
 | 
					        uart->td = 256000000 / baud_rate;
 | 
				
			||||||
 | 
					        gpio_enable(tx_pin, GPIO_OUTPUT);
 | 
				
			||||||
 | 
					        gpio_set_pullup(tx_pin, true, false);
 | 
				
			||||||
 | 
					        gpio_write(tx_pin, 1);
 | 
				
			||||||
 | 
					        mactimer_init();
 | 
				
			||||||
 | 
					        mactimer_setfn(&uart->output_mactimer, output_handler, uart);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return uart;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										47
									
								
								extras/tsoftuart/tsoftuart.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								extras/tsoftuart/tsoftuart.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,47 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Software timer based UART driver.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 to 2019 OurAirQuality.org
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0, January 2004 (the
 | 
				
			||||||
 | 
					 * "License"); you may not use this file except in compliance with the
 | 
				
			||||||
 | 
					 * License.  You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
				
			||||||
 | 
					 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
				
			||||||
 | 
					 * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
 | 
				
			||||||
 | 
					 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
				
			||||||
 | 
					 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
				
			||||||
 | 
					 * DEALINGS WITH THE SOFTWARE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _TSOFTUART_H
 | 
				
			||||||
 | 
					#define _TSOFTUART_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mactimer/mactimer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct tsoftuart {
 | 
				
			||||||
 | 
					    uint32_t tx_pin;
 | 
				
			||||||
 | 
					    /* Bit time period in usec * 256 */
 | 
				
			||||||
 | 
					    uint32_t td;
 | 
				
			||||||
 | 
					    mactimer_t output_mactimer;
 | 
				
			||||||
 | 
					    uint32_t output_queue[16];
 | 
				
			||||||
 | 
					    volatile uint64_t output_start_time;
 | 
				
			||||||
 | 
					    volatile size_t output_queue_head;
 | 
				
			||||||
 | 
					    volatile size_t output_queue_tail;
 | 
				
			||||||
 | 
					    size_t output_queue_state;
 | 
				
			||||||
 | 
					    uint64_t output_expected_time;
 | 
				
			||||||
 | 
					    int32_t output_queue_error_high;
 | 
				
			||||||
 | 
					    int32_t output_queue_error_low;
 | 
				
			||||||
 | 
					    uint32_t output_done;
 | 
				
			||||||
 | 
					} tsoftuart_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void tsoftuart_putc(tsoftuart_t *uart, uint8_t ch);
 | 
				
			||||||
 | 
					ssize_t tsoftuart_write(tsoftuart_t *uart, const void *ptr, size_t len);
 | 
				
			||||||
 | 
					tsoftuart_t *tsoftuart_init(uint8_t tx_pin, uint32_t baud_rate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _TSOFTUART_H */
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue