Compare commits
10 Commits
4ca7e495ab
...
47677d9e7f
Author | SHA1 | Date | |
---|---|---|---|
47677d9e7f | |||
6c4dd1c6ec | |||
435ddf8578 | |||
1173711d0c | |||
780291d5b0 | |||
03971211ef | |||
c525507ed8 | |||
0b31cd2b6c | |||
06edda3586 | |||
5d03067a3f |
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
53
libcpu/arm/cortex-m4/README.md
Normal file
53
libcpu/arm/cortex-m4/README.md
Normal 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`.
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user