mirror of
https://github.com/espressif/esp-idf.git
synced 2025-11-02 16:11:41 +01:00
Merge branch 'feature/ulp_uart' into 'master'
ulp-riscv: uart print See merge request espressif/esp-idf!19229
This commit is contained in:
43
components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_print.h
Normal file
43
components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_print.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Underlying driver function for printing a char, e.g. over UART */
|
||||
typedef void (*putc_fn_t)(const void *ctx, const char c);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Installs a print driver that will be used for ulp_riscv_print calls
|
||||
*
|
||||
* @param putc Underlying driver function for printing a char, e.g. over UART
|
||||
* @param putc_ctx Context that will be passed when calling the putc function
|
||||
*/
|
||||
void ulp_riscv_print_install(putc_fn_t putc, void *putc_ctx);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Prints a null-terminated string
|
||||
*
|
||||
* @param str String to print
|
||||
*/
|
||||
void ulp_riscv_print_str(const char *str);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Prints a hex number. Does not print 0x, only the digits
|
||||
*
|
||||
* @param Hex number to print
|
||||
*/
|
||||
void ulp_riscv_print_hex(int h);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ulp_riscv_gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
gpio_num_t tx_pin; // TX pin number
|
||||
} ulp_riscv_uart_cfg_t; // Config for the driver
|
||||
|
||||
typedef struct {
|
||||
uint32_t bit_duration_cycles; // Number of cycles to hold the line for each bit
|
||||
gpio_num_t tx_pin; // TX pin number
|
||||
} ulp_riscv_uart_t; // Context for the driver, initialized by ulp_riscv_uart_init
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize the bit-banged UART driver
|
||||
*
|
||||
* @note Will also initialize the underlying HW, i.e. the RTC GPIO used.
|
||||
*
|
||||
* @param uart Pointer to the struct that will contain the initialized context
|
||||
* @param cfg Pointer to the config struct which will be used to initialize the driver
|
||||
*/
|
||||
void ulp_riscv_uart_init(ulp_riscv_uart_t *uart, const ulp_riscv_uart_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Outputs a single byte on the tx pin
|
||||
*
|
||||
* @param uart Pointer to the initialized driver context
|
||||
* @param c Byte to output
|
||||
*/
|
||||
void ulp_riscv_uart_putc(const ulp_riscv_uart_t *uart, const char c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -94,7 +94,16 @@ void ulp_riscv_timer_resume(void);
|
||||
*
|
||||
* @param cycles Number of cycles to busy wait
|
||||
*/
|
||||
void ulp_riscv_delay_cycles(uint32_t cycles);
|
||||
void static inline ulp_riscv_delay_cycles(uint32_t cycles)
|
||||
{
|
||||
uint32_t start = ULP_RISCV_GET_CCOUNT();
|
||||
/* Off with an estimate of cycles in this function to improve accuracy */
|
||||
uint32_t end = start + cycles - 20;
|
||||
|
||||
while (ULP_RISCV_GET_CCOUNT() < end) {
|
||||
/* Wait */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the GPIO wakeup interrupt bit
|
||||
|
||||
51
components/ulp/ulp_riscv/ulp_core/ulp_riscv_print.c
Normal file
51
components/ulp/ulp_riscv/ulp_core/ulp_riscv_print.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "ulp_riscv_print.h"
|
||||
|
||||
typedef struct {
|
||||
putc_fn_t putc; // Putc function of the underlying driver, e.g. UART
|
||||
void *putc_ctx; // Context passed to the putc function
|
||||
} ulp_riscv_print_ctx_t;
|
||||
|
||||
static ulp_riscv_print_ctx_t s_print_ctx;
|
||||
|
||||
void ulp_riscv_print_install(putc_fn_t putc, void * putc_ctx)
|
||||
{
|
||||
s_print_ctx.putc_ctx = putc_ctx;
|
||||
s_print_ctx.putc = putc;
|
||||
}
|
||||
|
||||
void ulp_riscv_print_str(const char *str)
|
||||
{
|
||||
if (!s_print_ctx.putc) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; str[i] != 0; i++) {
|
||||
s_print_ctx.putc(s_print_ctx.putc_ctx ,str[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ulp_riscv_print_hex(int h)
|
||||
{
|
||||
int x;
|
||||
int c;
|
||||
|
||||
if (!s_print_ctx.putc) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Does not print '0x', only the digits (8 digits to print)
|
||||
for (x = 0; x < 8; x++) {
|
||||
c = (h >> 28) & 0xf; // extract the leftmost byte
|
||||
if (c < 10) {
|
||||
s_print_ctx.putc(s_print_ctx.putc_ctx ,'0' + c);
|
||||
} else {
|
||||
s_print_ctx.putc(s_print_ctx.putc_ctx ,'a' + c - 10);
|
||||
}
|
||||
h <<= 4; // move the 2nd leftmost byte to the left, to be extracted next
|
||||
}
|
||||
}
|
||||
50
components/ulp/ulp_riscv/ulp_core/ulp_riscv_uart.c
Normal file
50
components/ulp/ulp_riscv/ulp_core/ulp_riscv_uart.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "ulp_riscv.h"
|
||||
#include "ulp_riscv_utils.h"
|
||||
#include "ulp_riscv_gpio.h"
|
||||
#include "ulp_riscv_uart_ulp_core.h"
|
||||
|
||||
/* We calculate the bit duration at compile time to speed up and avoid pulling in soft-float libs */
|
||||
#define BIT_DURATION_CYCLES ( ULP_RISCV_CYCLES_PER_US * ((1000*1000) / CONFIG_ULP_RISCV_UART_BAUDRATE) )
|
||||
|
||||
void ulp_riscv_uart_init(ulp_riscv_uart_t *uart, const ulp_riscv_uart_cfg_t *cfg)
|
||||
{
|
||||
uart->tx_pin = cfg->tx_pin;
|
||||
/* 1 bit duration with length given in clock cycles */
|
||||
uart->bit_duration_cycles = BIT_DURATION_CYCLES;
|
||||
|
||||
/* Setup GPIO used for uart TX */
|
||||
ulp_riscv_gpio_init(cfg->tx_pin);
|
||||
ulp_riscv_gpio_output_enable(cfg->tx_pin);
|
||||
ulp_riscv_gpio_set_output_mode(cfg->tx_pin, RTCIO_MODE_OUTPUT_OD);
|
||||
ulp_riscv_gpio_pullup(cfg->tx_pin);
|
||||
ulp_riscv_gpio_pulldown_disable(cfg->tx_pin);
|
||||
ulp_riscv_gpio_output_level(cfg->tx_pin, 1);
|
||||
|
||||
}
|
||||
|
||||
void ulp_riscv_uart_putc(const ulp_riscv_uart_t *uart, const char c)
|
||||
{
|
||||
ulp_riscv_gpio_output_level(uart->tx_pin, 0);
|
||||
|
||||
for (int i = 0; i<8; i++) {
|
||||
/* Offset the delay to account for cycles spent setting the bit */
|
||||
ulp_riscv_delay_cycles(uart->bit_duration_cycles - 100);
|
||||
if ( (1 << i) & c) {
|
||||
ulp_riscv_gpio_output_level(uart->tx_pin, 1);
|
||||
} else {
|
||||
ulp_riscv_gpio_output_level(uart->tx_pin, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ulp_riscv_delay_cycles(uart->bit_duration_cycles - 20);
|
||||
ulp_riscv_gpio_output_level(uart->tx_pin, 1);
|
||||
ulp_riscv_delay_cycles(uart->bit_duration_cycles);
|
||||
}
|
||||
@@ -35,15 +35,6 @@ void ulp_riscv_halt(void)
|
||||
while(1);
|
||||
}
|
||||
|
||||
void ulp_riscv_delay_cycles(uint32_t cycles)
|
||||
{
|
||||
uint32_t start = ULP_RISCV_GET_CCOUNT();
|
||||
|
||||
while ((ULP_RISCV_GET_CCOUNT() - start) < cycles) {
|
||||
/* Wait */
|
||||
}
|
||||
}
|
||||
|
||||
void ulp_riscv_timer_stop(void)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN);
|
||||
|
||||
Reference in New Issue
Block a user