mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-29 17:22:56 +08:00
545 lines
15 KiB
C
545 lines
15 KiB
C
#ifndef _PIKA_HAL_STM32_COMMON_H_
|
|
#define _PIKA_HAL_STM32_COMMON_H_
|
|
|
|
#include "../PikaStdDevice/pika_hal.h"
|
|
#include "pika_adapter_rtt.h"
|
|
|
|
#ifndef rt_container_of
|
|
#define rt_container_of(ptr, type, member) \
|
|
((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
|
|
#endif
|
|
|
|
#define CHIP_FAMILY_STM32
|
|
#define SOC_FAMILY_STM32
|
|
#define RT_USING_DEVICE_OPS
|
|
|
|
#define SERIES_OF(_start) (defined(_start##xx) || defined(_start##x8) || \
|
|
defined(_start##xB) || defined(_start##xC) || \
|
|
defined(_start##xD) || defined(_start##xE) || defined(_start##xG))
|
|
|
|
/* auto select HAL header */
|
|
#if SERIES_OF(STM32H750) || SERIES_OF(STM32H743) || SERIES_OF(STM32H753) || \
|
|
SERIES_OF(STM32H755) || SERIES_OF(STM32H757)
|
|
#define SOC_SERIES_STM32H7
|
|
#define CHIP_SERIES_STM32H7
|
|
#include "stm32h7xx_hal.h"
|
|
|
|
#elif SERIES_OF(STM32F103) || SERIES_OF(STM32F102) || SERIES_OF(STM32F101)
|
|
#define SOC_SERIES_STM32F1
|
|
#define CHIP_SERIES_STM32F1
|
|
#include "stm32f1xx_hal.h"
|
|
|
|
#elif SERIES_OF(STM32G030) || SERIES_OF(STM32G031) || SERIES_OF(STM32G041) || \
|
|
SERIES_OF(STM32G070) || SERIES_OF(STM32G071) || SERIES_OF(STM32G081)
|
|
#define SOC_SERIES_STM32G0
|
|
#define CHIP_SERIES_STM32G0
|
|
#include "stm32g0xx_hal.h"
|
|
|
|
#elif SERIES_OF(STM32F030) || SERIES_OF(STM32F031) || SERIES_OF(STM32F051) || \
|
|
SERIES_OF(STM32F070) || SERIES_OF(STM32F042)
|
|
#define SOC_SERIES_STM32F0
|
|
#define CHIP_SERIES_STM32F0
|
|
#include "stm32f0xx_hal.h"
|
|
|
|
#elif SERIES_OF(STM32F401) || SERIES_OF(STM32F405) || SERIES_OF(STM32F407) || \
|
|
SERIES_OF(STM32F411)
|
|
#define SOC_SERIES_STM32F4
|
|
#define CHIP_SERIES_STM32F4
|
|
#include "stm32f4xx_hal.h"
|
|
|
|
#elif SERIES_OF(STM32U585) || SERIES_OF(STM32U575)
|
|
#define SOC_SERIES_STM32U5
|
|
#define CHIP_SERIES_STM32U5
|
|
#include "stm32u5xx_hal.h"
|
|
|
|
#elif SERIES_OF(STM32L451) || SERIES_OF(STM32L452) || SERIES_OF(STM32L462) || \
|
|
SERIES_OF(STM32L471) || SERIES_OF(STM32L475) || SERIES_OF(STM32L476) || \
|
|
SERIES_OF(STM32L485) || SERIES_OF(STM32L486)
|
|
#define SOC_SERIES_STM32L4
|
|
#define CHIP_SERIES_STM32L4
|
|
#include "stm32l4xx_hal.h"
|
|
|
|
#else
|
|
#error "Unsupported STM32 series"
|
|
#endif
|
|
|
|
/* struct */
|
|
|
|
struct rt_pin_irq_hdr
|
|
{
|
|
rt_base_t pin;
|
|
rt_uint8_t mode; /* e.g. PIN_IRQ_MODE_RISING */
|
|
void (*hdr)(void *args);
|
|
void *args;
|
|
};
|
|
|
|
struct rt_pin_ops
|
|
{
|
|
void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_uint8_t mode);
|
|
void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_uint8_t value);
|
|
rt_int8_t (*pin_read)(struct rt_device *device, rt_base_t pin);
|
|
rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_base_t pin,
|
|
rt_uint8_t mode, void (*hdr)(void *args), void *args);
|
|
rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_base_t pin);
|
|
rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled);
|
|
rt_base_t (*pin_get)(const char *name);
|
|
};
|
|
|
|
|
|
#define PIN_NONE (-1)
|
|
|
|
#define PIN_LOW 0x00
|
|
#define PIN_HIGH 0x01
|
|
|
|
#define PIN_MODE_OUTPUT 0x00
|
|
#define PIN_MODE_INPUT 0x01
|
|
#define PIN_MODE_INPUT_PULLUP 0x02
|
|
#define PIN_MODE_INPUT_PULLDOWN 0x03
|
|
#define PIN_MODE_OUTPUT_OD 0x04
|
|
|
|
#define PIN_IRQ_MODE_RISING 0x00
|
|
#define PIN_IRQ_MODE_FALLING 0x01
|
|
#define PIN_IRQ_MODE_RISING_FALLING 0x02
|
|
#define PIN_IRQ_MODE_HIGH_LEVEL 0x03
|
|
#define PIN_IRQ_MODE_LOW_LEVEL 0x04
|
|
|
|
#define PIN_IRQ_DISABLE 0x00
|
|
#define PIN_IRQ_ENABLE 0x01
|
|
|
|
#define PIN_IRQ_PIN_NONE PIN_NONE
|
|
|
|
#define RT_DEVICE_CTRL_RESUME 0x01 /**< resume device */
|
|
#define RT_DEVICE_CTRL_SUSPEND 0x02 /**< suspend device */
|
|
#define RT_DEVICE_CTRL_CONFIG 0x03 /**< configure device */
|
|
#define RT_DEVICE_CTRL_CLOSE 0x04 /**< close device */
|
|
#define RT_DEVICE_CTRL_NOTIFY_SET 0x05 /**< set notify func */
|
|
#define RT_DEVICE_CTRL_SET_INT 0x06 /**< set interrupt */
|
|
#define RT_DEVICE_CTRL_CLR_INT 0x07 /**< clear interrupt */
|
|
#define RT_DEVICE_CTRL_GET_INT 0x08 /**< get interrupt status */
|
|
#define RT_DEVICE_CTRL_CONSOLE_OFLAG 0x09 /**< get console open flag */
|
|
#define RT_DEVICE_CTRL_MASK 0x1f /**< mask for contrl commands */
|
|
|
|
#define RT_DEVICE_FLAG_DEACTIVATE 0x000 /**< device is not not initialized */
|
|
|
|
#define RT_DEVICE_FLAG_RDONLY 0x001 /**< read only */
|
|
#define RT_DEVICE_FLAG_WRONLY 0x002 /**< write only */
|
|
#define RT_DEVICE_FLAG_RDWR 0x003 /**< read and write */
|
|
|
|
#define RT_DEVICE_FLAG_REMOVABLE 0x004 /**< removable device */
|
|
#define RT_DEVICE_FLAG_STANDALONE 0x008 /**< standalone device */
|
|
#define RT_DEVICE_FLAG_ACTIVATED 0x010 /**< device is activated */
|
|
#define RT_DEVICE_FLAG_SUSPENDED 0x020 /**< device is suspended */
|
|
#define RT_DEVICE_FLAG_STREAM 0x040 /**< stream mode */
|
|
|
|
#define RT_DEVICE_FLAG_INT_RX 0x100 /**< INT mode on Rx */
|
|
#define RT_DEVICE_FLAG_DMA_RX 0x200 /**< DMA mode on Rx */
|
|
#define RT_DEVICE_FLAG_INT_TX 0x400 /**< INT mode on Tx */
|
|
#define RT_DEVICE_FLAG_DMA_TX 0x800 /**< DMA mode on Tx */
|
|
|
|
#define RT_DEVICE_OFLAG_CLOSE 0x000 /**< device is closed */
|
|
#define RT_DEVICE_OFLAG_RDONLY 0x001 /**< read only access */
|
|
#define RT_DEVICE_OFLAG_WRONLY 0x002 /**< write only access */
|
|
#define RT_DEVICE_OFLAG_RDWR 0x003 /**< read and write */
|
|
#define RT_DEVICE_OFLAG_OPEN 0x008 /**< device is opened */
|
|
#define RT_DEVICE_OFLAG_MASK 0xf0f /**< mask of open flag */
|
|
|
|
#ifdef RT_USING_DEVICE_OPS
|
|
/**
|
|
* operations set for device object
|
|
*/
|
|
struct rt_device_ops
|
|
{
|
|
/* common device interface */
|
|
rt_err_t (*init) (rt_device_t dev);
|
|
rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag);
|
|
rt_err_t (*close) (rt_device_t dev);
|
|
rt_ssize_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
|
|
rt_ssize_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
|
|
rt_err_t (*control)(rt_device_t dev, int cmd, void *args);
|
|
};
|
|
#endif /* RT_USING_DEVICE_OPS */
|
|
|
|
static inline rt_base_t rt_hw_interrupt_disable(void){
|
|
pika_platform_disable_irq_handle();
|
|
return 0;
|
|
}
|
|
|
|
static inline void rt_hw_interrupt_enable(rt_base_t level){
|
|
pika_platform_enable_irq_handle();
|
|
}
|
|
|
|
struct rt_adc_device;
|
|
struct rt_adc_ops
|
|
{
|
|
rt_err_t (*enabled)(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled);
|
|
rt_err_t (*convert)(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value);
|
|
rt_uint8_t (*get_resolution)(struct rt_adc_device *device);
|
|
rt_int16_t (*get_vref) (struct rt_adc_device *device);
|
|
};
|
|
|
|
struct rt_adc_device
|
|
{
|
|
struct rt_device parent;
|
|
const struct rt_adc_ops *ops;
|
|
};
|
|
typedef struct rt_adc_device *rt_adc_device_t;
|
|
|
|
static rt_ssize_t _adc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
|
|
{
|
|
rt_err_t result = RT_EOK;
|
|
rt_size_t i;
|
|
struct rt_adc_device *adc = (struct rt_adc_device *)dev;
|
|
rt_uint32_t *value = (rt_uint32_t *)buffer;
|
|
|
|
for (i = 0; i < size; i += sizeof(int))
|
|
{
|
|
result = adc->ops->convert(adc, pos + i, value);
|
|
if (result != RT_EOK)
|
|
{
|
|
return 0;
|
|
}
|
|
value++;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
static inline rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_int8_t channel)
|
|
{
|
|
rt_err_t result = RT_EOK;
|
|
|
|
RT_ASSERT(dev);
|
|
|
|
if (dev->ops->enabled != RT_NULL)
|
|
{
|
|
result = dev->ops->enabled(dev, channel, RT_TRUE);
|
|
}
|
|
else
|
|
{
|
|
result = -RT_ENOSYS;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static inline rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_int8_t channel)
|
|
{
|
|
rt_err_t result = RT_EOK;
|
|
|
|
RT_ASSERT(dev);
|
|
|
|
if (dev->ops->enabled != RT_NULL)
|
|
{
|
|
result = dev->ops->enabled(dev, channel, RT_FALSE);
|
|
}
|
|
else
|
|
{
|
|
result = -RT_ENOSYS;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static inline rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_int8_t channel)
|
|
{
|
|
rt_uint32_t value;
|
|
|
|
RT_ASSERT(dev);
|
|
|
|
dev->ops->convert(dev, channel, &value);
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
#define PIN_NUM(port, no) (((((port) & 0xFu) << 4) | ((no) & 0xFu)))
|
|
#define PIN_PORT(pin) ((uint8_t)(((pin) >> 4) & 0xFu))
|
|
#define PIN_NO(pin) ((uint8_t)((pin) & 0xFu))
|
|
|
|
#if defined(SOC_SERIES_STM32MP1)
|
|
#if defined(GPIOZ)
|
|
#define gpioz_port_base (175) /* PIN_STPORT_MAX * 16 - 16 */
|
|
#define PIN_STPORT(pin) ((pin > gpioz_port_base) ? ((GPIO_TypeDef *)(GPIOZ_BASE )) : ((GPIO_TypeDef *)(GPIOA_BASE + (0x1000u * PIN_PORT(pin)))))
|
|
#else
|
|
#define PIN_STPORT(pin) ((GPIO_TypeDef *)(GPIOA_BASE + (0x1000u * PIN_PORT(pin))))
|
|
#endif /* GPIOZ */
|
|
#else
|
|
#define PIN_STPORT(pin) ((GPIO_TypeDef *)(GPIOA_BASE + (0x400u * PIN_PORT(pin))))
|
|
#endif /* SOC_SERIES_STM32MP1 */
|
|
|
|
#define PIN_STPIN(pin) ((uint16_t)(1u << PIN_NO(pin)))
|
|
|
|
/* e.g. PA7 */
|
|
rt_base_t _stm32_pin_get(const char *name);
|
|
|
|
#define RT_ADC_INTERN_CH_TEMPER (-1)
|
|
#define RT_ADC_INTERN_CH_VREF (-2)
|
|
#define RT_ADC_INTERN_CH_VBAT (-3)
|
|
|
|
|
|
#define BSP_USING_GPIO
|
|
#define RT_USING_PIN
|
|
#define BSP_USING_PWM
|
|
|
|
#ifdef ADC1
|
|
#define BSP_USING_ADC1
|
|
#endif
|
|
|
|
#ifdef DAC1
|
|
#define BSP_USING_DAC1
|
|
#endif
|
|
|
|
#if defined(USART1) || defined(UART1)
|
|
#define BSP_USING_UART1
|
|
#endif
|
|
|
|
#if defined(USART2) || defined(UART2)
|
|
#define BSP_USING_UART2
|
|
#endif
|
|
|
|
#if defined(USART3) || defined(UART3)
|
|
#define BSP_USING_UART3
|
|
#endif
|
|
|
|
#if defined(USART4) || defined(UART4)
|
|
#define BSP_USING_UART4
|
|
#endif
|
|
|
|
#if defined(USART5) || defined(UART5)
|
|
#define BSP_USING_UART5
|
|
#endif
|
|
|
|
#if defined(USART6) || defined(UART6)
|
|
#define BSP_USING_UART6
|
|
#endif
|
|
|
|
#if defined(USART7) || defined(UART7)
|
|
#define BSP_USING_UART7
|
|
#endif
|
|
|
|
#if defined(USART8) || defined(UART8)
|
|
#define BSP_USING_UART8
|
|
#endif
|
|
|
|
|
|
#if defined(BSP_USING_UART1) || defined(BSP_USING_UART2) || defined(BSP_USING_UART3) || \
|
|
defined(BSP_USING_UART4) || defined(BSP_USING_UART5) || defined(BSP_USING_UART6) || \
|
|
defined(BSP_USING_UART7) || defined(BSP_USING_UART8) || defined(BSP_USING_LPUART1)
|
|
#define RT_USING_SERIAL
|
|
// #define RT_SERIAL_USING_DMA
|
|
|
|
#endif
|
|
|
|
|
|
#if defined(TIM1)
|
|
#define BSP_USING_PWM1
|
|
#endif
|
|
|
|
#if defined(TIM2)
|
|
#define BSP_USING_PWM2
|
|
#endif
|
|
|
|
#if defined(TIM3)
|
|
#define BSP_USING_PWM3
|
|
#endif
|
|
|
|
#if defined(TIM4)
|
|
#define BSP_USING_PWM4
|
|
#endif
|
|
|
|
#if defined(TIM5)
|
|
#define BSP_USING_PWM5
|
|
#endif
|
|
|
|
#if defined(TIM6)
|
|
#define BSP_USING_PWM6
|
|
#endif
|
|
|
|
#if defined(TIM7)
|
|
#define BSP_USING_PWM7
|
|
#endif
|
|
|
|
#if defined(TIM8)
|
|
#define BSP_USING_PWM8
|
|
#endif
|
|
|
|
#if defined(TIM9)
|
|
#define BSP_USING_PWM9
|
|
#endif
|
|
|
|
#if defined(TIM10)
|
|
#define BSP_USING_PWM10
|
|
#endif
|
|
|
|
#if defined(TIM11)
|
|
#define BSP_USING_PWM11
|
|
#endif
|
|
|
|
#if defined(TIM12)
|
|
#define BSP_USING_PWM12
|
|
#endif
|
|
|
|
#if defined(TIM13)
|
|
#define BSP_USING_PWM13
|
|
#endif
|
|
|
|
#if defined(TIM14)
|
|
#define BSP_USING_PWM14
|
|
#endif
|
|
|
|
#if defined(TIM15)
|
|
#define BSP_USING_PWM15
|
|
#endif
|
|
|
|
#if defined(TIM16)
|
|
#define BSP_USING_PWM16
|
|
#endif
|
|
|
|
#if defined(TIM17)
|
|
#define BSP_USING_PWM17
|
|
#endif
|
|
|
|
struct rt_dac_device;
|
|
struct rt_dac_ops
|
|
{
|
|
rt_err_t (*disabled)(struct rt_dac_device *device, rt_uint32_t channel);
|
|
rt_err_t (*enabled)(struct rt_dac_device *device, rt_uint32_t channel);
|
|
rt_err_t (*convert)(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value);
|
|
rt_uint8_t (*get_resolution)(struct rt_dac_device *device);
|
|
};
|
|
|
|
struct rt_dac_device
|
|
{
|
|
struct rt_device parent;
|
|
const struct rt_dac_ops *ops;
|
|
};
|
|
|
|
struct rt_ringbuffer
|
|
{
|
|
rt_uint8_t *buffer_ptr;
|
|
/* use the msb of the {read,write}_index as mirror bit. You can see this as
|
|
* if the buffer adds a virtual mirror and the pointers point either to the
|
|
* normal or to the mirrored buffer. If the write_index has the same value
|
|
* with the read_index, but in a different mirror, the buffer is full.
|
|
* While if the write_index and the read_index are the same and within the
|
|
* same mirror, the buffer is empty. The ASCII art of the ringbuffer is:
|
|
*
|
|
* mirror = 0 mirror = 1
|
|
* +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
|
|
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Full
|
|
* +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
|
|
* read_idx-^ write_idx-^
|
|
*
|
|
* +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
|
|
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Empty
|
|
* +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
|
|
* read_idx-^ ^-write_idx
|
|
*/
|
|
|
|
rt_uint32_t read_mirror : 1;
|
|
rt_uint32_t read_index : 31;
|
|
rt_uint32_t write_mirror : 1;
|
|
rt_uint32_t write_index : 31;
|
|
/* as we use msb of index as mirror bit, the size should be signed and
|
|
* could only be positive. */
|
|
rt_int32_t buffer_size;
|
|
};
|
|
|
|
struct rt_serial_rx_fifo
|
|
{
|
|
struct rt_ringbuffer rb;
|
|
|
|
// struct rt_completion rx_cpt;
|
|
|
|
rt_uint16_t rx_cpt_index;
|
|
|
|
/* software fifo */
|
|
rt_uint8_t buffer[];
|
|
};
|
|
|
|
typedef struct rt_dac_device *rt_dac_device_t;
|
|
|
|
#define rt_interrupt_enter()
|
|
#define rt_interrupt_leave()
|
|
|
|
#define RT_ALIGN_DOWN(size, align) ((size) & ~((align) - 1))
|
|
#define RT_ALIGN_SIZE 8
|
|
|
|
#define RT_SERIAL_RX_MINBUFSZ 64
|
|
#define RT_SERIAL_TX_MINBUFSZ 64
|
|
|
|
#define RT_DEVICE_FLAG_RX_BLOCKING 0x1000
|
|
#define RT_DEVICE_FLAG_RX_NON_BLOCKING 0x2000
|
|
|
|
#define RT_DEVICE_FLAG_TX_BLOCKING 0x4000
|
|
#define RT_DEVICE_FLAG_TX_NON_BLOCKING 0x8000
|
|
|
|
#define RT_SERIAL_RX_BLOCKING RT_DEVICE_FLAG_RX_BLOCKING
|
|
#define RT_SERIAL_RX_NON_BLOCKING RT_DEVICE_FLAG_RX_NON_BLOCKING
|
|
#define RT_SERIAL_TX_BLOCKING RT_DEVICE_FLAG_TX_BLOCKING
|
|
#define RT_SERIAL_TX_NON_BLOCKING RT_DEVICE_FLAG_TX_NON_BLOCKING
|
|
|
|
void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio);
|
|
static void rt_ringbuffer_init(struct rt_ringbuffer *rb,
|
|
rt_uint8_t *pool,
|
|
rt_int32_t size)
|
|
{
|
|
RT_ASSERT(rb != RT_NULL);
|
|
RT_ASSERT(size > 0);
|
|
|
|
/* initialize read and write index */
|
|
rb->read_mirror = rb->read_index = 0;
|
|
rb->write_mirror = rb->write_index = 0;
|
|
|
|
/* set buffer pool and size */
|
|
rb->buffer_ptr = pool;
|
|
rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
|
|
}
|
|
|
|
/** return the size of empty space in rb */
|
|
#define rt_ringbuffer_space_len(rb) ((rb)->buffer_size - rt_ringbuffer_data_len(rb))
|
|
|
|
enum rt_ringbuffer_state
|
|
{
|
|
RT_RINGBUFFER_EMPTY,
|
|
RT_RINGBUFFER_FULL,
|
|
/* half full is neither full nor empty */
|
|
RT_RINGBUFFER_HALFFULL,
|
|
};
|
|
|
|
static inline enum rt_ringbuffer_state rt_ringbuffer_status(struct rt_ringbuffer *rb)
|
|
{
|
|
if (rb->read_index == rb->write_index)
|
|
{
|
|
if (rb->read_mirror == rb->write_mirror)
|
|
return RT_RINGBUFFER_EMPTY;
|
|
else
|
|
return RT_RINGBUFFER_FULL;
|
|
}
|
|
return RT_RINGBUFFER_HALFFULL;
|
|
}
|
|
|
|
static rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb)
|
|
{
|
|
switch (rt_ringbuffer_status(rb))
|
|
{
|
|
case RT_RINGBUFFER_EMPTY:
|
|
return 0;
|
|
case RT_RINGBUFFER_FULL:
|
|
return rb->buffer_size;
|
|
case RT_RINGBUFFER_HALFFULL:
|
|
default:
|
|
{
|
|
rt_size_t wi = rb->write_index, ri = rb->read_index;
|
|
|
|
if (wi > ri)
|
|
return wi - ri;
|
|
else
|
|
return rb->buffer_size - (ri - wi);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|