Compare commits

...

10 Commits

15 changed files with 193 additions and 15 deletions

View File

@ -154,6 +154,7 @@ rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *da
no = ((rt_uint32_t)tx_tosnd - (rt_uint32_t)tx_fifo->buffer) / sizeof(struct rt_can_sndbxinx_list);
tx_tosnd->result = RT_CAN_SND_RESULT_WAIT;
rt_completion_init(&(tx_tosnd->completion));
if (can->ops->sendmsg(can, data, no) != RT_EOK)
{
/* send failed. */
@ -192,6 +193,8 @@ rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *da
err_ret:
level = rt_hw_interrupt_disable();
can->status.dropedsndpkg++;
//TODO:发送失败,取消发送状态
can->ops->control(can, RT_CAN_CMD_CANCEL, (void *)no);
rt_hw_interrupt_enable(level);
break;
}

View File

@ -182,6 +182,7 @@ struct rt_can_ops;
#define RT_CAN_CMD_SET_CANFD 0x1A
#define RT_CAN_CMD_SET_BAUD_FD 0x1B
#define RT_CAN_CMD_SET_BITTIMING 0x1C
#define RT_CAN_CMD_CANCEL 0x1D
#define RT_DEVICE_CAN_INT_ERR 0x1000

View File

@ -27,9 +27,9 @@ static rt_size_t _adc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_
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))
for (i = 0; i < size; i += sizeof(int), pos++)
{
result = adc->ops->convert(adc, pos + i, value);
result = adc->ops->convert(adc, pos, value);
if (result != RT_EOK)
{
return 0;

View File

@ -1121,7 +1121,8 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
if (args != RT_NULL)
{
struct serial_configure *pconfig = (struct serial_configure *) args;
if (serial->parent.ref_count)
if (((pconfig->rx_bufsz != serial->config.rx_bufsz) || (pconfig->tx_bufsz != serial->config.tx_bufsz))
&& serial->parent.ref_count)
{
/*can not change buffer size*/
return -RT_EBUSY;

View File

@ -306,10 +306,10 @@
// start with recbuf at 0/
#define RXSTART_INIT 0x0
// receive buffer end
#define RXSTOP_INIT (0x1FFF - MAX_TX_PACKAGE_SIZE*2) - 1
#define RXSTOP_INIT ((0x1FFF - MAX_TX_PACKAGE_SIZE * 2) - 1)
// start TX buffer at 0x1FFF-0x0600, pace for one full ethernet frame (~1500 bytes)
#define TXSTART_INIT (0x1FFF - MAX_TX_PACKAGE_SIZE*2)
#define TXSTART_INIT (0x1FFF - MAX_TX_PACKAGE_SIZE * 2)
// stp TX buffer at end of mem
#define TXSTOP_INIT 0x1FFF

View File

@ -27,10 +27,20 @@
#pragma import(__use_no_heap)
#endif /* __CC_ARM */
#if defined (__clang__) && defined (RT_USING_CPLUSPLUS)
#define RT_USING_POSIX_MEMALIGN
#endif
#include <sys/errno.h>
void *malloc(size_t n)
{
#ifdef RT_USING_HEAP
return rt_malloc(n);
#ifndef RT_USING_POSIX_MEMALIGN
return rt_malloc(n);
#else
return rt_malloc_align(n, RT_ALIGN_SIZE);
#endif
#else
_NO_HEAP_ERROR();
return RT_NULL;
@ -41,7 +51,11 @@ RTM_EXPORT(malloc);
void *realloc(void *rmem, size_t newsize)
{
#ifdef RT_USING_HEAP
return rt_realloc(rmem, newsize);
#ifndef RT_USING_POSIX_MEMALIGN
return rt_realloc(rmem, newsize);
#else
return rt_realloc_align(rmem, newsize, RT_ALIGN_SIZE);
#endif
#else
_NO_HEAP_ERROR();
return RT_NULL;
@ -63,9 +77,36 @@ RTM_EXPORT(calloc);
void free(void *rmem)
{
#ifdef RT_USING_HEAP
rt_free(rmem);
#ifndef RT_USING_POSIX_MEMALIGN
rt_free(rmem);
#else
rt_free_align(rmem);
#endif
#else
_NO_HEAP_ERROR();
#endif
}
RTM_EXPORT(free);
#if defined RT_USING_POSIX_MEMALIGN
int posix_memalign(void **ptr, size_t align, size_t size)
{
if ((align & (align - 1)) != 0)
{
return -EINVAL;
}
if(align != RT_ALIGN(align, sizeof(void *)))
{
return -EINVAL;
}
*ptr = rt_malloc_align(size, align);
if(*ptr == RT_NULL)
{
return -ENOMEM;
}
return 0;
}
#endif

View File

@ -34,6 +34,7 @@ int libc_system_init(void)
INIT_COMPONENT_EXPORT(libc_system_init);
#if defined(RT_USING_POSIX_STDIO) && defined(RT_USING_NEWLIB)
#define NEWLIB_VERSION_NUM (__NEWLIB__ * 10000U + __NEWLIB_MINOR__ * 100U + __NEWLIB_PATCHLEVEL__)
#define STDIO_DEVICE_NAME_MAX 32
static FILE* std_console = NULL;
int libc_stdio_set_console(const char* device_name, int mode)
@ -89,8 +90,9 @@ int libc_stdio_set_console(const char* device_name, int mode)
_GLOBAL_REENT->_stdout = std_console;
_GLOBAL_REENT->_stderr = std_console;
}
#if (NEWLIB_VERSION_NUM < 30400U) || (NEWLIB_VERSION_NUM >= 40000U && NEWLIB_VERSION_NUM < 40200U)
_GLOBAL_REENT->__sdidinit = 1;
#endif
}
if (std_console)

View File

@ -610,7 +610,8 @@ at_client_t at_client_get(const char *dev_name)
for (idx = 0; idx < AT_CLIENT_NUM_MAX; idx++)
{
if (rt_strcmp(at_client_table[idx].device->parent.name, dev_name) == 0)
if (at_client_table[idx].device && \
(rt_strcmp(at_client_table[idx].device->parent.name, dev_name) == 0))
{
return &at_client_table[idx];
}

View File

@ -1027,7 +1027,7 @@ enum rt_device_class_type
/**
* device control
*/
#define RT_DEVICE_CTRL_BASE(Type) (RT_Device_Class_##Type * 0x100)
#define RT_DEVICE_CTRL_BASE(Type) ((RT_Device_Class_##Type + 1) * 0x100)
/**
* special device commands

View File

@ -268,6 +268,7 @@ void rt_free(void *ptr);
void *rt_realloc(void *ptr, rt_size_t nbytes);
void *rt_calloc(rt_size_t count, rt_size_t size);
void *rt_malloc_align(rt_size_t size, rt_size_t align);
void *rt_realloc_align(void *rmem, rt_size_t newsize, rt_size_t align);
void rt_free_align(void *ptr);
void rt_memory_info(rt_size_t *total,

View File

@ -0,0 +1,53 @@
## Independent Interrupts Management
### Introduction
Calling `rt_hw_interrupt_disable` in multiple places on `rt-thread` may cause interruption delays when the application requires accurate interrupt responses. This is because the system cannot generate any interrupts except abnormal interrupts after disabling interrupts. This is a common problem in the interrupt management of the operating system. The independent interrupt management module is designed to solve this problem.
The independent interrupt management module is designed to solve the problem of interrupt delays caused by calling `rt_hw_interrupt_disable` in multiple places on `rt-thread`. The module is implemented by rewrite the `rt_hw_interrupt_disable` and `rt_hw_interrupt_enable` functions in the `libcpu` library.
### Usage
- Add the following code to the project's `board.c` file.
```
#ifdef RT_USING_INDEPENDENT_INTERRUPT_MANAGEMENT
#define RT_NVIC_PRO_BITS __NVIC_PRIO_BITS
rt_base_t rt_hw_interrupt_disable(void)
{
rt_base_t level = __get_BASEPRI();
__set_BASEPRI(RT_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - RT_NVIC_PRO_BITS));
__ISB();
__DSB();
return level;
}
void rt_hw_interrupt_enable(rt_base_t level)
{
__set_BASEPRI(level);
}
#endif /* RT_USING_INDEPENDENT_INTERRUPT_MANAGEMENT */
```
- Add the following configuration to the `Kconfig` file in the `board` directory.
```
menuconfig RT_USING_INDEPENDENT_INTERRUPT_MANAGEMENT
bool "Enable independent interrupt management"
default n
if RT_USING_INDEPENDENT_INTERRUPT_MANAGEMENT
config RT_MAX_SYSCALL_INTERRUPT_PRIORITY
int "Set max syscall interrupt priority"
range 0 7
default 2
endif
```
- Select `RT_USING_INDEPENDENT_INTERRUPT_MANAGEMENT` to enable this feature.
- Select `RT_MAX_SYSCALL_INTERRUPT_PRIORITY` to set the maximum priority of the interrupt that can be called by the system call. The default value is 2.
### Description
- The [basepri](https://developer.arm.com/documentation/107706/0100/Exceptions-and-interrupts-overview/Special-registers-for-exception-masking/BASEPRI) register is used in the functions to complete the interrupt management.
- For example, if `RT_MAX_SYSCALL_INTERRUPT_PRIORITY` is set to 0x01, the system masking only interrupts with a priority of `0x01-0xFF`.
- Interrupts with a priority of 0 are not managed by the system and can continue to respond to interrupts after `rt_hw_interrupt_disable` is called.
- When using the [basepri](https://developer.arm.com/documentation/107706/0100/Exceptions-and-interrupts-overview/Special-registers-for-exception-masking/BASEPRI) register for independent interrupt management, note that interrupts with a priority value lower than `RT_MAX_SYSCALL_INTERRUPT_PRIORITY` cannot call any `system API`.

View File

@ -10,6 +10,7 @@
* 2013-06-18 aozima add restore MSP feature.
* 2013-06-23 aozima support lazy stack optimized.
* 2018-07-24 aozima enhancement hard fault exception handler.
* 2024-08-13 Evlers allows rewrite to interrupt enable/disable api to support independent interrupts management
*/
/**
@ -32,6 +33,7 @@
* rt_base_t rt_hw_interrupt_disable();
*/
.global rt_hw_interrupt_disable
.weak rt_hw_interrupt_disable
.type rt_hw_interrupt_disable, %function
rt_hw_interrupt_disable:
MRS r0, PRIMASK
@ -42,6 +44,7 @@ rt_hw_interrupt_disable:
* void rt_hw_interrupt_enable(rt_base_t level);
*/
.global rt_hw_interrupt_enable
.weak rt_hw_interrupt_enable
.type rt_hw_interrupt_enable, %function
rt_hw_interrupt_enable:
MSR PRIMASK, r0
@ -208,6 +211,10 @@ rt_hw_context_switch_to:
CPSIE F
CPSIE I
/* clear the BASEPRI register to disable masking priority */
MOV r0, #0x00
MSR BASEPRI, r0
/* ensure PendSV exception taken place before subsequent operation */
DSB
ISB

View File

@ -11,6 +11,7 @@
; * 2013-06-18 aozima add restore MSP feature.
; * 2013-06-23 aozima support lazy stack optimized.
; * 2018-07-24 aozima enhancement hard fault exception handler.
; * 2024-08-13 Evlers allows rewrite to interrupt enable/disable api to support independent interrupts management
; */
;/**
@ -36,7 +37,8 @@ NVIC_PENDSVSET EQU 0x10000000 ; value to trigger PendSV excep
;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
EXPORT rt_hw_interrupt_disable
PUBWEAK rt_hw_interrupt_disable
SECTION .text:CODE:REORDER:NOROOT(2)
rt_hw_interrupt_disable:
MRS r0, PRIMASK
CPSID I
@ -45,7 +47,8 @@ rt_hw_interrupt_disable:
;/*
; * void rt_hw_interrupt_enable(rt_base_t level);
; */
EXPORT rt_hw_interrupt_enable
PUBWEAK rt_hw_interrupt_enable
SECTION .text:CODE:REORDER:NOROOT(2)
rt_hw_interrupt_enable:
MSR PRIMASK, r0
BX LR
@ -208,6 +211,10 @@ rt_hw_context_switch_to:
CPSIE F
CPSIE I
; clear the BASEPRI register to disable masking priority
MOV r0, #0x00
MSR BASEPRI, r0
; ensure PendSV exception taken place before subsequent operation
DSB
ISB

View File

@ -10,6 +10,7 @@
; * 2013-06-18 aozima add restore MSP feature.
; * 2013-06-23 aozima support lazy stack optimized.
; * 2018-07-24 aozima enhancement hard fault exception handler.
; * 2024-08-13 Evlers allows rewrite to interrupt enable/disable api to support independent interrupts management
; */
;/**
@ -36,7 +37,7 @@ NVIC_PENDSVSET EQU 0x10000000 ; value to trigger PendSV excep
; * rt_base_t rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable PROC
EXPORT rt_hw_interrupt_disable
EXPORT rt_hw_interrupt_disable [WEAK]
MRS r0, PRIMASK
CPSID I
BX LR
@ -46,7 +47,7 @@ rt_hw_interrupt_disable PROC
; * void rt_hw_interrupt_enable(rt_base_t level);
; */
rt_hw_interrupt_enable PROC
EXPORT rt_hw_interrupt_enable
EXPORT rt_hw_interrupt_enable [WEAK]
MSR PRIMASK, r0
BX LR
ENDP
@ -208,6 +209,10 @@ rt_hw_context_switch_to PROC
CPSIE F
CPSIE I
; clear the BASEPRI register to disable masking priority
MOV r0, #0x00
MSR BASEPRI, r0
; ensure PendSV exception taken place before subsequent operation
DSB
ISB

View File

@ -1698,6 +1698,62 @@ RT_WEAK void *rt_malloc_align(rt_size_t size, rt_size_t align)
}
RTM_EXPORT(rt_malloc_align);
/**
* This function will change the size of previously allocated memory block,
* which address is aligned to the specified alignment size.
*
* @param rmem is the pointer to memory allocated by rt_malloc_align.
*
* @param newsize is the required new size.
*
* @param align is the alignment size.
*
* @return the changed memory block address.
*/
RT_WEAK void *rt_realloc_align(void *rmem, size_t newsize, rt_size_t align)
{
void *real_ptr;
void *ptr;
void *align_ptr;
int uintptr_size;
rt_size_t align_size;
/* sizeof pointer */
uintptr_size = sizeof(void*);
uintptr_size -= 1;
/* align the alignment size to uintptr size byte */
align = ((align + uintptr_size) & ~uintptr_size);
/* get total aligned size */
align_size = ((newsize + uintptr_size) & ~uintptr_size) + align;
real_ptr = (void *) * (rt_ubase_t *)((rt_ubase_t)rmem - sizeof(void *));
ptr = rt_realloc(real_ptr, align_size);
if (ptr != RT_NULL)
{
/* the allocated memory block is aligned */
if (((rt_ubase_t)ptr & (align - 1)) == 0)
{
align_ptr = (void *)((rt_ubase_t)ptr + align);
}
else
{
align_ptr = (void *)(((rt_ubase_t)ptr + (align - 1)) & ~(align - 1));
}
/* set the pointer before alignment pointer to the real pointer */
*((rt_ubase_t *)((rt_ubase_t)align_ptr - sizeof(void *))) = (rt_ubase_t)ptr;
ptr = align_ptr;
}
return ptr;
}
/**
* This function release the memory block, which is allocated by
* rt_malloc_align function and address is aligned.