Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/can/Kconfig.mcan
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ config CAN_MCAN
bool
select CAN_HAS_CANFD
select CAN_HAS_RX_TIMESTAMP
select IO32_MEM
help
Enable Bosch m_can driver.
This driver supports the Bosch m_can IP. This IP is built into the
Expand Down
31 changes: 10 additions & 21 deletions drivers/can/can_mcan.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,6 @@ LOG_MODULE_REGISTER(can_mcan, CONFIG_CAN_LOG_LEVEL);
#define CAN_INIT_TIMEOUT (100)
#define CAN_DIV_CEIL(val, div) (((val) + (div) - 1) / (div))

static void memcpy32_volatile(volatile void *dst_, const volatile void *src_,
size_t len)
{
volatile uint32_t *dst = dst_;
const volatile uint32_t *src = src_;

__ASSERT(len % 4 == 0, "len must be a multiple of 4!");
len /= sizeof(uint32_t);

while (len--) {
*dst = *src;
++dst;
++src;
}
}

static void memset32_volatile(volatile void *dst_, uint32_t val, size_t len)
{
Expand Down Expand Up @@ -625,7 +610,8 @@ static void can_mcan_get_message(const struct device *dev,

sys_cache_data_invd_range((void *)&fifo[get_idx].hdr,
sizeof(struct can_mcan_rx_fifo_hdr));
memcpy32_volatile(&hdr, &fifo[get_idx].hdr,

io32_memcpy(&hdr, &fifo[get_idx].hdr,
sizeof(struct can_mcan_rx_fifo_hdr));

frame.dlc = hdr.dlc;
Expand Down Expand Up @@ -670,7 +656,8 @@ static void can_mcan_get_message(const struct device *dev,
/* Data needs to be written in 32 bit blocks! */
sys_cache_data_invd_range((void *)fifo[get_idx].data_32,
ROUND_UP(data_length, sizeof(uint32_t)));
memcpy32_volatile(frame.data_32, fifo[get_idx].data_32,

io32_memcpy(frame.data_32, fifo[get_idx].data_32,
ROUND_UP(data_length, sizeof(uint32_t)));

if ((frame.flags & CAN_FRAME_IDE) != 0) {
Expand Down Expand Up @@ -892,8 +879,9 @@ int can_mcan_send(const struct device *dev,
tx_hdr.std_id = frame->id & CAN_STD_ID_MASK;
}

memcpy32_volatile(&msg_ram->tx_buffer[put_idx].hdr, &tx_hdr, sizeof(tx_hdr));
memcpy32_volatile(msg_ram->tx_buffer[put_idx].data_32, frame->data_32,
BUILD_ASSERT(sizeof(msg_ram->tx_buffer[put_idx].hdr) == sizeof(tx_hdr));
io32_memcpy(&msg_ram->tx_buffer[put_idx].hdr, &tx_hdr, sizeof(tx_hdr));
io32_memcpy(msg_ram->tx_buffer[put_idx].data_32, frame->data_32,
ROUND_UP(data_length, 4));
sys_cache_data_flush_range((void *)&msg_ram->tx_buffer[put_idx].hdr, sizeof(tx_hdr));
sys_cache_data_flush_range((void *)&msg_ram->tx_buffer[put_idx].data_32,
Expand Down Expand Up @@ -966,7 +954,8 @@ int can_mcan_add_rx_filter_std(const struct device *dev,
filter_element.sfce = filter_id & 0x01 ? CAN_MCAN_FCE_FIFO1 :
CAN_MCAN_FCE_FIFO0;

memcpy32_volatile(&msg_ram->std_filt[filter_id], &filter_element,
BUILD_ASSERT(sizeof(msg_ram->std_filt[0]) == sizeof(filter_element));
io32_memcpy(&msg_ram->std_filt[filter_id], &filter_element,
sizeof(struct can_mcan_std_filter));
sys_cache_data_flush_range((void *)&msg_ram->std_filt[filter_id],
sizeof(struct can_mcan_std_filter));
Expand Down Expand Up @@ -1030,7 +1019,7 @@ static int can_mcan_add_rx_filter_ext(const struct device *dev,
filter_element.efce = filter_id & 0x01 ? CAN_MCAN_FCE_FIFO1 :
CAN_MCAN_FCE_FIFO0;

memcpy32_volatile(&msg_ram->ext_filt[filter_id], &filter_element,
io32_memcpy(&msg_ram->ext_filt[filter_id], &filter_element,
sizeof(struct can_mcan_ext_filter));
sys_cache_data_flush_range((void *)&msg_ram->ext_filt[filter_id],
sizeof(struct can_mcan_ext_filter));
Expand Down
20 changes: 20 additions & 0 deletions include/zephyr/sys/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,26 @@ char *utf8_trunc(char *utf8_str);
*/
char *utf8_lcpy(char *dst, const char *src, size_t n);

/**
* @brief Copy src to dest word-wise
*
* This function copies src to dest 32 bits at a time.
* If one calls this function without src and dst being aligned
* on a 4-byte boundary or if n is not a multiple of 4, it will
* do nothing and return NULL.
*
* NOTE: This function uses __ASSERT to enforce the requirements
* of each parameter given below.
*
* @param dest Destination address (must be aligned to a 4-byte boundary)
* @param src Source address (must be aligned to a 4-byte boundary)
* @param n number of bytes to copy (must be a multiple of 4)
*
* @return destination pointer or NULL on error
*/
volatile void *
io32_memcpy(volatile void * dest, const volatile void * src, size_t n);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions lib/os/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ zephyr_sources_ifdef(CONFIG_SYS_MEM_BLOCKS mem_blocks.c)

zephyr_sources_ifdef(CONFIG_WINSTREAM winstream.c)

zephyr_sources_ifdef(CONFIG_IO32_MEM io32_mem.c)

zephyr_library_include_directories(
${ZEPHYR_BASE}/kernel/include
${ZEPHYR_BASE}/arch/${ARCH}/include
Expand Down
8 changes: 8 additions & 0 deletions lib/os/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,14 @@ config UTF8
Enable the utf8 API. The API implements functions to specifically
handle UTF-8 encoded strings.

config IO32_MEM
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really need a Kconfig option for this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, @SebastianBoe is this really needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there is no pre-existing source file that the function belongs in.

And we don't want to unconditionally invoke gcc for something that is rarely used as it slows down the build and creates noise in the build.

bool "io32_memcpy()"
help
Enable io32_memcpy(). This function is useful when word-wise
copying is required, for example when copying from or to a
memory-mapped peripheral. May be expanded with memset and
similar in the future.

rsource "Kconfig.cbprintf"

rsource "Kconfig.heap"
Expand Down
37 changes: 37 additions & 0 deletions lib/os/io32_mem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2021 Pete Dietl
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdint.h>
#include <zephyr/sys/util.h>
#include <zephyr/sys/__assert.h>

#define IS_ALIGNED(X) (!((uintptr_t)X & (sizeof(uint32_t) - 1)))

volatile void *
io32_memcpy(volatile void * dst0, const volatile void * src0, size_t len)
{
__ASSERT(len % 4 == 0, "len must be a multiple of 4!");

volatile uint32_t *dst = dst0;
const volatile uint32_t *src = src0;

__ASSERT(IS_ALIGNED(dst), "dst0 must be aligned to a multiple of 4!");
__ASSERT(IS_ALIGNED(src), "src0 must be aligned to a multiple of 4!");

if (!((len % 4 == 0) && IS_ALIGNED(src) && IS_ALIGNED(dst))) {
return NULL;
}

len /= sizeof(uint32_t);

while (len--) {
*dst = *src;
++dst;
++src;
}

return dst0;
}