mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
608 lines
23 KiB
C
608 lines
23 KiB
C
/* Copyright (C) 2023 Alif Semiconductor - All Rights Reserved.
|
|
* Use, distribution and modification of this code is permitted under the
|
|
* terms stated in the Alif Semiconductor Software License Agreement
|
|
*
|
|
* You should have received a copy of the Alif Semiconductor Software
|
|
* License Agreement with this file. If not, please write to:
|
|
* contact@alifsemi.com, or visit: https://alifsemi.com/license
|
|
*
|
|
*/
|
|
/**************************************************************************//**
|
|
* @file dma_opcode.h
|
|
* @author Sudhir Sreedharan
|
|
* @email sudhir@alifsemi.com
|
|
* @version V1.0.0
|
|
* @date 8-Aug-2023
|
|
* @brief DMA Opcode Generation Header File
|
|
* @bug None.
|
|
* @Note None
|
|
******************************************************************************/
|
|
|
|
#ifndef DMA_OPCODE_H_
|
|
#define DMA_OPCODE_H_
|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
#define DMA_MAX_BACKWARD_JUMP 256 /*!< Max Loop backward jump offset */
|
|
#define DMA_MAX_LP_CNT 256 /*!< Max Loop count */
|
|
|
|
/* 8 bit-opcode with variable data payload of 0, 8, 16 or 32bits */
|
|
#define DMA_OP_1BYTE_LEN 1
|
|
#define DMA_OP_2BYTE_LEN 2
|
|
#define DMA_OP_3BYTE_LEN 3
|
|
#define DMA_OP_6BYTE_LEN 6
|
|
|
|
#define OP_DMAADDH(ar) (0x54 | (ar << 1)) /*!< Adds an immediate 16bit value to SARn or DARn */
|
|
#define OP_DMAADNH(ar) (0x5C | (ar << 1)) /*!< Adds an immediate 16bit negative value to SARn or DARn */
|
|
#define OP_DMAEND 0x00 /*!< End signal as the DMAC sequence is complete */
|
|
#define OP_DMAFLUSHP 0x35 /*!< Flush the peripheral contents and sends message to resend its level status */
|
|
#define OP_DMAGO(ns) (0xA0 | (ns << 1)) /*!< Execute thread in secure/non-secure mode */
|
|
#define OP_DMAKILL 0x01 /*!< Terminate Execution of a thread */
|
|
#define OP_DMALD 0x04 /*!< Performs DMA Load operation */
|
|
#define OP_DMALDS 0x05 /*!< Performs DMA Single Load operation */
|
|
#define OP_DMALDB 0x07 /*!< Performs DMA Burst Load operation */
|
|
#define OP_DMALDP(bs) (0x25 | (bs << 1)) /*!< Performs DMA Load & Notify Peripheral Single/Burst operation */
|
|
#define OP_DMALP(lc) (0x20 | (lc << 1)) /*!< Loop instruct DMAC to load 8bit val to LC0/LC1 reg */
|
|
#define OP_DMALPEND(nf, lc) (0x28 | (nf << 4) | (lc << 2)) /*!< Loop End, nf=0, lc=1 if DMALPFE started loop */
|
|
#define OP_DMALPENDS(lc) (0x39 | (lc << 2)) /*!< Loop End Single */
|
|
#define OP_DMALPENDB(lc) (0x3B | (lc << 2)) /*!< Loop End Burst */
|
|
#define OP_DMAMOV 0xBC /*!< Move 32bit immediate into SAR/DAR/CCR */
|
|
#define OP_DMANOP 0x18 /*!< For code alignment */
|
|
#define OP_DMARMB 0x12 /*!< Read Memory barrier, write-after-read sequence */
|
|
#define OP_DMASEV 0x34 /*!< Send event */
|
|
#define OP_DMAST 0x08 /*!< Performs DMA Store operation */
|
|
#define OP_DMASTS 0x09 /*!< Performs DMA Single Store operation */
|
|
#define OP_DMASTB 0x0B /*!< Performs DMA Burst Store operation */
|
|
#define OP_DMASTP(bs) (0x29 | (bs << 1)) /*!< Performs DMA Store & Notify Peripheral Single/Burst operation */
|
|
#define OP_DMASTZ 0x0C /*!< Store Zeros */
|
|
#define OP_DMAWFE 0x36 /*!< Wait for event */
|
|
#define OP_DMAWFP_P(p) (0x30 | (p << 0)) /*!< Wait for peripheral with peripheral bit set */
|
|
#define OP_DMAWFP(bs) (0x30 | (bs << 1)) /*!< Wait for peripheral in single/burst mode */
|
|
#define OP_DMAWMB 0x13 /*!< Write memory barrier */
|
|
|
|
/* SWAP SIZE */
|
|
typedef enum _DMA_SWAP {
|
|
DMA_SWAP_NONE, /*!< No swap, 8-bit data */
|
|
DMA_SWAP_16BIT, /*!< Swap bytes within 16-bit data */
|
|
DMA_SWAP_32BIT, /*!< Swap bytes within 32-bit data */
|
|
DMA_SWAP_64BIT, /*!< Swap bytes within 64-bit data */
|
|
DMA_SWAP_128BIT, /*!< Swap bytes within 128-bit data */
|
|
} DMA_SWAP;
|
|
|
|
|
|
/* Loop counters */
|
|
typedef enum _DMA_LC {
|
|
DMA_LC_0,
|
|
DMA_LC_1,
|
|
} DMA_LC;
|
|
|
|
/* Burst Type */
|
|
typedef enum _DMA_BURST {
|
|
DMA_BURST_FIXED = 0, /*!< Fixed Address burst */
|
|
DMA_BURST_INCREMENTING, /*!< Incrementing Address burst */
|
|
} DMA_BURST;
|
|
|
|
/* Transfer type */
|
|
typedef enum _DMA_XFER {
|
|
DMA_XFER_SINGLE = 0,
|
|
DMA_XFER_BURST = 1,
|
|
DMA_XFER_PERIPHERAL = 2,
|
|
DMA_XFER_FORCE = 2,
|
|
} DMA_XFER;
|
|
|
|
/* DMA Secure State */
|
|
typedef enum _DMA_SECURE_STATE {
|
|
DMA_STATE_SECURE = 0, /*!< Secure State */
|
|
DMA_STATE_NON_SECURE, /*!< Non-Secure State */
|
|
} DMA_SECURE_STATE;
|
|
|
|
/* DMA registers */
|
|
typedef enum _DMA_REG {
|
|
DMA_REG_SAR,
|
|
DMA_REG_CCR,
|
|
DMA_REG_DAR
|
|
} DMA_REG;
|
|
|
|
/* DMA channel control information */
|
|
typedef union _dma_ccr_t {
|
|
uint32_t value;
|
|
struct {
|
|
uint32_t src_inc : 1; /*!< Source Fixed/Increment type burst */
|
|
uint32_t src_burst_size : 3; /*!< No of bytes DMAC reads from source in a beat */
|
|
uint32_t src_burst_len : 4; /*!< No of data transfers in a burst when DMAC read from source */
|
|
uint32_t src_prot_ctrl : 3; /*!< Protection control when DMAC reads from source */
|
|
uint32_t src_cache_ctrl : 3; /*!< Cache control when DMAC reads from source */
|
|
uint32_t dst_inc : 1; /*!< Destination Fixed/Increment type burst */
|
|
uint32_t dst_burst_size : 3; /*!< No of bytes DMAC writes to destination in a beat */
|
|
uint32_t dst_burst_len : 4; /*!< No of data transfers in a burst when DMAC writes to destination */
|
|
uint32_t dst_prot_ctrl : 3; /*!< Protection control when DMAC writes to destination */
|
|
uint32_t dst_cache_ctrl : 3; /*!< Cache control when DMAC writes to destination */
|
|
uint32_t endian_swap_size : 3; /*!< swap size data */
|
|
} value_b;
|
|
} dma_ccr_t;
|
|
|
|
/* DMA Loop control information */
|
|
typedef struct _dma_loop_t {
|
|
DMA_XFER xfer_type; /*!< Transfer Type : Single/Burst/Peripheral */
|
|
DMA_LC lc; /*!< Loop Register : LC0/LC1 */
|
|
uint8_t jump; /*!< Backward Jump offset */
|
|
bool nf; /*!< Loop forever flag t */
|
|
} dma_loop_t;
|
|
|
|
/* DMA Opcode buffer information */
|
|
typedef struct _dma_opcode_buf {
|
|
uint8_t *buf; /*!< Start address of the opcode buffer */
|
|
uint32_t off; /*!< Current Offset from start address */
|
|
uint32_t buf_size; /*!< Total buffer size */
|
|
} dma_opcode_buf;
|
|
|
|
/**
|
|
\fn bool dma_construct_add(DMA_REG reg,
|
|
uint16_t off,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMAADDH
|
|
\param[in] reg Source or Destination Address Register
|
|
\param[in] off 16bit-immediate offset which needs to be added
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
|
|
static inline bool dma_construct_add(DMA_REG reg,
|
|
uint16_t off,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_3BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
if (reg == DMA_REG_SAR)
|
|
op_buf->buf[(op_buf->off)++] = OP_DMAADDH(0);
|
|
else if (reg == DMA_REG_DAR)
|
|
op_buf->buf[(op_buf->off)++] = OP_DMAADDH(1);
|
|
else
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)off;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(off >> 8);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_addneg(DMA_REG reg,
|
|
int16_t off,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMAADNH
|
|
\param[in] reg Source or Destination Address Register
|
|
\param[in] off 16bit-immediate value which needs to be subtracted
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_addneg(DMA_REG reg,
|
|
int16_t off,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_3BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
if (reg == DMA_REG_SAR)
|
|
op_buf->buf[(op_buf->off)++] = OP_DMAADNH(0);
|
|
else if (reg == DMA_REG_DAR)
|
|
op_buf->buf[(op_buf->off)++] = OP_DMAADNH(1);
|
|
else
|
|
return false;
|
|
|
|
off = off - 1;
|
|
off = ~off;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)off;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(off >> 8);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_end(dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMAEND
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_end(dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_1BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = OP_DMAEND;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_flushperiph(uint8_t periph,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMAFLUSHP
|
|
\param[in] periph peripheral number
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_flushperiph(uint8_t periph,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_2BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = OP_DMAFLUSHP;
|
|
periph = periph & 0x1F;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(periph << 3);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_go(DMA_SECURE_STATE ns,
|
|
uint8_t channel_num,
|
|
uint32_t imm,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMAGO
|
|
\param[in] ns Defines the secure/Non-Secure State
|
|
\param[in] channel_num Defines the channel number
|
|
\param[in] imm 32bit address where the microcode resides
|
|
\param[in] op_buf opcode buf info
|
|
\return void
|
|
*/
|
|
static inline bool dma_construct_go(DMA_SECURE_STATE ns,
|
|
uint8_t channel_num,
|
|
uint32_t imm,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_6BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)OP_DMAGO(ns);
|
|
op_buf->buf[(op_buf->off)++] = channel_num & 0x7;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)imm;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(imm >> 8);
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(imm >> 16);
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(imm >> 24);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn void dma_construct_kill(dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMAKILL
|
|
\param[in] op_buf opcode buf info
|
|
\return void
|
|
*/
|
|
static inline void dma_construct_kill(dma_opcode_buf *op_buf)
|
|
{
|
|
*op_buf->buf = OP_DMAKILL;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_load(DMA_XFER xfer_type, dma_opcode_buf *op_buf
|
|
\brief Build the opcode for DMALD
|
|
\param[in] xfer_type Burst/Single/Force Load operation
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_load(DMA_XFER xfer_type, dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_1BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
if (xfer_type == DMA_XFER_FORCE)
|
|
op_buf->buf[(op_buf->off)++] = OP_DMALD;
|
|
else if (xfer_type == DMA_XFER_BURST)
|
|
op_buf->buf[(op_buf->off)++] = OP_DMALDB;
|
|
else
|
|
op_buf->buf[(op_buf->off)++] = OP_DMALDS;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_loadperiph(DMA_XFER xfer_type,
|
|
uint8_t periph,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMALDP
|
|
\param[in] xfer_type Burst or Single Load operation
|
|
\param[in] periph Peripheral number
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_loadperiph(DMA_XFER xfer_type,
|
|
uint8_t periph,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_2BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
if (xfer_type > DMA_XFER_BURST)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)OP_DMALDP(xfer_type);
|
|
periph = periph & 0x1F;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(periph << 3);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_loop(DMA_LC lc,
|
|
uint8_t iter,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMALP
|
|
\param[in] lc Loop Counter register number
|
|
\param[in] iter 8bit loop value
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_loop(DMA_LC lc,
|
|
uint8_t iter,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_2BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)OP_DMALP(lc);
|
|
op_buf->buf[(op_buf->off)++] = iter - 1;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_loopend(dma_loop_t lp_args,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMALPEND
|
|
\param[in] lp_args loop arguments single/burst/force, lc, nf, jump
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_loopend(dma_loop_t *lp_args,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_2BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
if (lp_args->nf == 0)
|
|
op_buf->buf[(op_buf->off)++] = OP_DMALPEND(0, 1);
|
|
else if (lp_args->xfer_type == DMA_XFER_FORCE)
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)OP_DMALPEND(1, lp_args->lc);
|
|
else if (lp_args->xfer_type == DMA_XFER_BURST)
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)OP_DMALPENDB(lp_args->lc);
|
|
else
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)OP_DMALPENDS(lp_args->lc);
|
|
|
|
op_buf->buf[(op_buf->off)++] = lp_args->jump;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_move(uint32_t imm,
|
|
DMA_REG reg,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMAMOV
|
|
\param[in] imm 32bit immediate address
|
|
\param[in] reg SAR/CCR/DAR register
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_move(uint32_t imm,
|
|
DMA_REG reg,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_6BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = OP_DMAMOV;
|
|
op_buf->buf[(op_buf->off)++] = reg & 0x7;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)imm;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(imm >> 8);
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(imm >> 16);
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(imm >> 24);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_nop(dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMANOP
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_nop(dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_1BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = OP_DMANOP;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_rmb(dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMARMB
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_rmb(dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_1BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = OP_DMARMB;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_send_event(uint8_t event_num,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMASEV
|
|
\param[in] event_num Event number
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_send_event(uint8_t event_num,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_2BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = OP_DMASEV;
|
|
event_num = event_num & 0x1F;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(event_num << 3);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_store(DMA_XFER xfer_type,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMAST
|
|
\param[in] xfer_type Burst/Single/Force Load operation
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_store(DMA_XFER xfer_type,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_1BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
if (xfer_type == DMA_XFER_FORCE)
|
|
op_buf->buf[(op_buf->off)++] = OP_DMAST;
|
|
else if (xfer_type == DMA_XFER_BURST)
|
|
op_buf->buf[(op_buf->off)++] = OP_DMASTB;
|
|
else
|
|
op_buf->buf[(op_buf->off)++] = OP_DMASTS;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_storeperiph(DMA_XFER xfer_type,
|
|
uint8_t periph,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMASTP
|
|
\param[in] xfer_type Burst or Single Store operation
|
|
\param[in] periph Peripheral number
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_storeperiph(DMA_XFER xfer_type,
|
|
uint8_t periph,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_2BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
if (xfer_type > DMA_XFER_BURST)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)OP_DMASTP(xfer_type);
|
|
periph = periph & 0x1F;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(periph << 3);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_store_zeros(dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMASTZ
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_store_zeros(dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_1BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = OP_DMASTZ;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_wfe(bool invalidate,
|
|
uint8_t event_num,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMAWFE
|
|
\param[in] invalidate Set for invalidating the Cache
|
|
\param[in] event_num Event number
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_wfe(bool invalidate,
|
|
uint8_t event_num,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_2BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = OP_DMAWFE;
|
|
event_num = event_num & 0x1F;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)((event_num << 3) | (invalidate << 1));
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_wfp(DMA_XFER xfer_type,
|
|
uint8_t periph_num,
|
|
dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMAWFP
|
|
\param[in] xfer_type Single/Burst/Peripheral
|
|
\param[in] periph_num Peripheral number
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_wfp(DMA_XFER xfer_type,
|
|
uint8_t periph_num,
|
|
dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_2BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
if (xfer_type == DMA_XFER_PERIPHERAL)
|
|
op_buf->buf[(op_buf->off)++] = OP_DMAWFP_P(1);
|
|
else
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)OP_DMAWFP(xfer_type);
|
|
|
|
periph_num = periph_num & 0x1F;
|
|
op_buf->buf[(op_buf->off)++] = (uint8_t)(periph_num << 3);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_construct_wmb(dma_opcode_buf *op_buf)
|
|
\brief Build the opcode for DMAWMB
|
|
\param[in] op_buf opcode buf info
|
|
\return bool true if the opcode fits in the allocated space
|
|
*/
|
|
static inline bool dma_construct_wmb(dma_opcode_buf *op_buf)
|
|
{
|
|
if ((op_buf->off + DMA_OP_1BYTE_LEN) > op_buf->buf_size)
|
|
return false;
|
|
|
|
op_buf->buf[(op_buf->off)++] = OP_DMAWMB;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* DMA_OPCODE_H_ */
|