123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- #include <os_common_api.h>
- #include <drivers/dma.h>
- #include <drivers/cfg_drv/dev_config.h>
- #include <display/ui_memsetcpy.h>
- static const struct device * dma_dev;
- static int dma_chan;
- static struct dma_config dma_cfg;
- static struct dma_block_config dma_block_cfg;
- static K_SEM_DEFINE(dma_sem, 0, 1);
- static void dma_complete_callback(const struct device *dev, void *user_data,
- uint32_t channel, int status)
- {
- k_sem_give(&dma_sem);
- }
- static int dma_transfer_init(void)
- {
- if (dma_dev) {
- return 0;
- }
- dma_dev = device_get_binding(CONFIG_DMA_0_NAME);
- if (dma_dev == NULL) {
- SYS_LOG_ERR(CONFIG_DMA_0_NAME " not found");
- return -ENODEV;
- }
- dma_chan = dma_request(dma_dev, 0xFF);
- if (dma_chan < 0) {
- SYS_LOG_ERR("dma_request failed");
- dma_dev = NULL;
- return -ENODEV;
- }
- dma_cfg.complete_callback_en = 1;
- dma_cfg.dma_callback = dma_complete_callback;
- dma_cfg.dma_slot = 0;
- dma_cfg.dest_data_size = 4;
- dma_cfg.block_count = 1;
- dma_cfg.head_block = &dma_block_cfg;
- return 0;
- }
- static int _memset32(void * buf, uint32_t c32, size_t n)
- {
- static uint32_t dma_c32 __in_section_unique(ram.noinit);
- if (ui_memsetcpy_wait_finish(5000)) {
- k_sem_reset(&dma_sem);
- }
- dma_c32 = c32;
- dma_cfg.channel_direction = PERIPHERAL_TO_MEMORY;
- dma_block_cfg.block_size = n;
- dma_block_cfg.source_address = (uint32_t)&dma_c32;
- dma_block_cfg.dest_address = (uint32_t)buf;
- if (dma_config(dma_dev, dma_chan, &dma_cfg)) {
- SYS_LOG_ERR("dma%d config error\n", dma_chan);
- dma_block_cfg.block_size = 0;
- return -1;
- }
- if (dma_start(dma_dev, dma_chan)) {
- SYS_LOG_ERR("dma%d start error\n", dma_chan);
- dma_block_cfg.block_size = 0;
- return -1;
- }
- return 0;
- }
- void ui_memset(void * buf, uint8_t c, size_t n)
- {
- if (((uintptr_t)buf & 0x3) || (n & 0x3)) {
- memset(buf, c, n);
- return;
- }
- if (dma_transfer_init()) {
- memset(buf, c, n);
- return;
- }
- uint32_t c32 = c | ((uint32_t)c << 8) | ((uint32_t)c << 16) | ((uint32_t)c << 24);
- if (_memset32(buf, c32, n)) {
- memset(buf, c, n);
- }
- }
- int ui_memset16(void * buf, uint16_t c16, size_t n16)
- {
- if (((uintptr_t)buf & 0x3) || (n16 & 0x1)) {
- return -EINVAL;
- }
- if (dma_transfer_init()) {
- return -EINVAL;
- }
- uint32_t c32 = c16 | ((uint32_t)c16 << 16);
- return _memset32(buf, c32, n16 * 2);
- }
- int ui_memset32(void * buf, uint32_t c32, size_t n32)
- {
- if ((uintptr_t)buf & 0x3) {
- return -EINVAL;
- }
- if (dma_transfer_init()) {
- return -EINVAL;
- }
- return _memset32(buf, c32, n32 * 4);
- }
- void ui_memcpy(void * dest, const void * src, size_t n)
- {
- if (((uintptr_t)dest & 0x3) || ((uintptr_t)src & 0x3) || (n & 0x3)) {
- memcpy(dest, src, n);
- return;
- }
- if (dma_transfer_init()) {
- memcpy(dest, src, n);
- return;
- }
- if (ui_memsetcpy_wait_finish(5000)) {
- k_sem_reset(&dma_sem);
- }
- dma_cfg.channel_direction = MEMORY_TO_MEMORY;
- dma_block_cfg.block_size = n;
- dma_block_cfg.source_address = (uint32_t)src;
- dma_block_cfg.dest_address = (uint32_t)dest;
- if (dma_config(dma_dev, dma_chan, &dma_cfg)) {
- SYS_LOG_ERR("dma%d config error\n", dma_chan);
- dma_block_cfg.block_size = 0;
- memcpy(dest, src, n);
- return;
- }
- if (dma_start(dma_dev, dma_chan)) {
- SYS_LOG_ERR("dma%d start error\n", dma_chan);
- dma_block_cfg.block_size = 0;
- memcpy(dest, src, n);
- return;
- }
- }
- int ui_memsetcpy_wait_finish(int timeout_ms)
- {
- int res = 0;
- if (dma_dev == NULL) {
- return 0;
- }
- if (dma_block_cfg.block_size > 0) {
- if (timeout_ms < 0) {
- res = k_sem_take(&dma_sem, K_FOREVER);
- } else {
- res = k_sem_take(&dma_sem, K_MSEC(timeout_ms));
- }
- if (res == 0) {
- dma_block_cfg.block_size = 0;
- }
- }
- return res;
- }
|