wes3 commented on a change in pull request #1868: hw/mcu/dialog: SNC URL: https://github.com/apache/mynewt-core/pull/1868#discussion_r294494085
########## File path: hw/mcu/dialog/da1469x/include/mcu/da1469x_snc.h ########## @@ -0,0 +1,485 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __MCU_DA1469X_SNC_H_ +#define __MCU_DA1469X_SNC_H_ + +#include <stdint.h> +#include "DA1469xAB.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* XXX: define these here for now until I get a better definition */ +#define SNC_REG_BASE_ADDR (0x50000000) +#define SNC_RAM_BASE_ADDR (0x20000000) +#define SNC_REG_MASK (1 << 19) +#define SNC_OP_IS_REG(op) ((((uint32_t)op) & SNC_REG_BASE_ADDR) ? SNC_REG_MASK : 0) +#define SNC_ADDR(addr) (((uint32_t)addr) - SNC_RAM_BASE_ADDR) +#define SNC_REG(addr) (((uint32_t)addr) - SNC_REG_BASE_ADDR) + +/* + * For certain commands which use direct or indirect addresses. A direct address + * specifies a memory location. An indirect address (a pointer) means that the + * address contains the address of the desired memory location. + * + * Please refer to the specific command to see if these definitions should be + * used for that command! + */ +#define SNC_ADDR_MODE_DIRECT (0) +#define SNC_ADDR_MODE_INDIRECT (1) + +/* + * No operation instruction. + * + * There are no operands for this instruction. + * + * ----------------------- + * | opcode (0) | N/C | + * ----------------------- + * | 31 - 28 | 27 - 0 | + * ----------------------- + */ +#define SNC_OPCODE_NOP (0) /* No operands */ +#define SNC_CMD_NOOP() (uint32_t)(SNC_OPCODE_NOP << 28) + +/* + * Store Contents + * + * Stores the contents of addr2 in addr1. Addr1 and/or Addr2 can be addresses + * or pointers and can reference either system RAM or a register + * + * am1: Addressing mode for addr1 + * SNC_WADAD_AM1_INDIRECT: Indirect addressing mode. + * SNC_WADAD_AM1_DIRECT: Direct addressing mode + * + * am2: Addressing mode for addr2 + * SNC_WADAD_AM2_INDIRECT: Indirect addressing mode. + * SNC_WADAD_AM2_DIRECT: Direct addressing mode + * ---------------------------------------------- + * | opcode (1) | am1 | am2 | N/C | addr1 | + * ---------------------------------------------- + * | 31 - 28 | 27 | 26 | 25 - 20 | 19 - 0 | + * ---------------------------------------------- + * + * ---------- + * | addr2 | + * ---------- + * | 31 - 0 | + * ---------- + * + * NOTE: The nomenclature used is addr2 first then addr1. + * + * Ex. RAM2RAM: addr2 and addr1 are both in system RAM. + * RAM2REG: addr2 is in system RAM and addr1 is in register space + * REG2RAM: addr2 is a register and addr1 is in system RAM. + */ +#define SNC_OPCODE_WADAD (1) +#define SNC_CMD_WADAD_RAM2RAM(addr1, am1, am2, addr2) \ + (uint32_t)((SNC_OPCODE_WADAD << 28) + (am1 << 27) + (am2 << 26) + \ + SNC_ADDR(addr1)), \ + (uint32_t)(SNC_ADDR(addr2)) +#define SNC_CMD_WADAD_RAM2REG(addr1, am1, am2, addr2) \ + (uint32_t)((SNC_OPCODE_WADAD << 28) + (am1 << 27) + (am2 << 26) + \ + SNC_REG_MASK + SNC_REG(addr1)), \ + (uint32_t)(SNC_ADDR(addr2)) +#define SNC_CMD_WADAD_REG2RAM(addr1, am1, am2, addr2) \ + (uint32_t)((SNC_OPCODE_WADAD << 28) + (am1 << 27) + (am2 << 26) + \ + SNC_ADDR(addr1)), \ + (uint32_t)(SNC_REG_MASK + SNC_REG(addr2)) +#define SNC_CMD_WADAD_REG2REG(addr1, am1, am2, addr2) \ + (uint32_t)((SNC_OPCODE_WADAD << 28) + (am1 << 27) + (am2 << 26) + \ + SNC_REG_MASK + SNC_REG(addr1)), \ + (uint32_t)(SNC_REG_MASK + SNC_REG(addr2)) + +#define SNC_WADAD_AM1_INDIRECT (0) +#define SNC_WADAD_AM1_DIRECT (1) +#define SNC_WADAD_AM2_DIRECT (0) +#define SNC_WADAD_AM2_INDIRECT (1) + +/* + * Store Value + * + * Stores immediate value (32-bits) in either addr (direct) or the address + * pointed to by addr (indirect) + * + * addr_mode: + * SNC_WADVA_AM_IND: Indirect address Ex. *addr = value + * SNC_WADVA_AM_DIR: Direct address mode Ex. addr = value + * + * ---------------------------------------------- + * | opcode (2) | addr_mode | N/C | addr | + * ---------------------------------------------- + * | 31 - 28 | 27 | 26 - 20 | 19 - 0 | + * ---------------------------------------------- + * + * ---------- + * | value | + * ---------- + * | 31 - 0 | + * ---------- + */ +#define SNC_OPCODE_WADVA (2) +#define SNC_CMD_WADVA_REG(addr, addr_mode, value) \ + (uint32_t)((SNC_OPCODE_WADVA << 28) + (addr_mode << 27) + \ + SNC_REG_MASK + SNC_REG(addr)), \ + (uint32_t)(value) + +#define SNC_CMD_WADVA_RAM(addr, addr_mode, value) \ + (uint32_t)((SNC_OPCODE_WADVA << 28) + (addr_mode << 27) + \ + SNC_ADDR(addr)), \ + (uint32_t)(value) + +#define SNC_WADVA_AM_IND (0) +#define SNC_WADVA_AM_DIR (1) + +#define SNC_CMD_WADVA_IND_RAM(addr, val) \ + SNC_CMD_WADVA_RAM(addr, SNC_WADVA_AM_IND, val) +#define SNC_CMD_WADVA_IND_REG(addr, val) \ + SNC_CMD_WADVA_REG(addr, SNC_WADVA_AM_IND, val) +#define SNC_CMD_WADVA_DIR_RAM(addr, val) \ + SNC_CMD_WADVA_RAM(addr, SNC_WADVA_AM_DIR, val) +#define SNC_CMD_WADVA_DIR_REG(addr, val) \ + SNC_CMD_WADVA_REG(addr, SNC_WADVA_AM_DIR, val) + +/* + * XOR + * + * Performs an XOR operation with the contents of addr and mask; stores contents + * in addr. Note that addr can be a register or RAM address, + * + * Ex: x = x ^ mask + * + * ------------------------- + * | opcode (3) | addr | + * ------------------------- + * | 31 - 28 | 19 - 0 | + * ------------------------- + * + * ---------- + * | mask | + * ---------- + * | 31 - 0 | + * ---------- + */ +#define SNC_OPCODE_TOBRE (3) +#define SNC_CMD_TOBRE_RAM(addr, mask) \ + (uint32_t)((SNC_OPCODE_TOBRE << 28) + SNC_ADDR(addr)), \ + (uint32_t)(mask) +#define SNC_CMD_TOBRE_REG(addr, mask) \ + (uint32_t)((SNC_OPCODE_TOBRE << 28) + SNC_REG_MASK + SNC_REG(addr)), \ + (uint32_t)(mask) + +/* + * Compare Bit in Address + * + * Compares the contents of addr and sets the EQUALHIGH_FLAG if the bit at + * position 'bitpos' is set to 1. NOTE: addr can be either RAM address + * or a register. Note that bitpos is a bit position (0 to 31). + * + * Ex: if (addr & (1 << bitpos)) { + * EQUALHIGH_FLAG = 1; + * } else { + * EQUALHIGH_FLAG = 0; + * } + * + * -------------------------------------------- + * | opcode (4) | bitpos | N/C | addr | + * -------------------------------------------- + * | 31 - 28 | 27 - 23 | 22 - 20 | 19 - 0 | + * -------------------------------------------- + */ +#define SNC_OPCODE_RDCBI (4) +#define SNC_CMD_RDCBI_REG(addr, bitpos) \ + (uint32_t)((SNC_OPCODE_RDCBI << 28) + ((bitpos & 0x1F) << 23) + \ + SNC_REG_MASK + SNC_REG(addr)) +#define SNC_CMD_RDCBI_RAM(addr, bitpos) \ + (uint32_t)((SNC_OPCODE_RDCBI << 28) + ((bitpos & 0x1F) << 23) + \ + SNC_ADDR(addr)) + +/* + * Compare Address Contents + * + * Compares the contents of addr1 and addr2 and sets the GREATERVAL_FLAG if the + * contents of addr1 are greater than the contents of addr2. Note that addr1 + * and addr2 can be either RAM addresses or a register. + * + * --------------------------------- + * | opcode (5) | N/C | addr1 | + * --------------------------------- + * | 31 - 28 | 27 - 20 | 19 - 0 | + * --------------------------------- + * + * -------------------- + * | N/C | addr2 | + * -------------------- + * | 31 - 20 | 19 - 0 | + * -------------------- + * + * NOTE: the nomenclature here is addr1 first, then addr2 + * EX: RAMRAM: both addr1 and addr2 are in system RAM + * RAMREG: addr1 is in system RAM, addr2 is a register + * REGRAM: addr1 is a register, addr2 is in system RAM + * REGREG: both addr1 and addr2 are registers + */ +#define SNC_OPCODE_RDCGR (5) +#define SNC_CMD_RDCGR_RAMRAM(addr1, addr2) \ + (uint32_t)((SNC_OPCODE_RDCGR << 28) + SNC_ADDR(addr1)), \ + (uint32_t)(SNC_ADDR(addr2)) +#define SNC_CMD_RDCGR_RAMREG(addr1, addr2) \ + (uint32_t)((SNC_OPCODE_RDCGR << 28) + SNC_ADDR(addr1)), \ + (uint32_t)(SNC_REG_MASK + SNC_REG(addr2)) +#define SNC_CMD_RDCGR_REGRAM(addr1, addr2) \ + (uint32_t)((SNC_OPCODE_RDCGR << 28) + SNC_REG_MASK + SNC_REG(addr1)), \ + (uint32_t)(SNC_ADDR(addr2)) +#define SNC_CMD_RDCGR_REGREG(addr1, addr2) \ + (uint32_t)((SNC_OPCODE_RDCGR << 28) + SNC_REG_MASK + SNC_REG(addr1)), \ + (uint32_t)(SNC_REG_MASK + SNC_REG(addr2)) + +/* + * Conditional branch instruction + * + * Perform a conditional branch to a direct or indirect memory + * address (RAM). There are three types of branches: + * + * EQUALHIGH_FLAG: branch if flag is true. (direct or indirect) + * 0x0A => branch to direct address + * 0x1A => branch to indirect address + * GREATERVAL_FLAG: branch if flag is true. (direct or indirect) + * 0x05 => branch to direct address + * 0x15 => branch to indirect address + * LOOP: perform branch up to 128 times. (direct only) + * 0b1yyyyyyy where yyyyyyy is loop count. + * + * ---------------------------------------- + * | opcode (6) | flags | N/C | ADDR | + * ---------------------------------------- + * | 31 - 28 | 27 - 20 | 19 | 18 - 0 | + * ---------------------------------------- + * + * addr: Either a direct address (specifies an address in RAM) or an indirect + * memory address (addr contains the RAM address to branch to). + * loops: Number of times to loop (max 127). + */ +#define SNC_OPCODE_COBR (6) +#define SNC_CMD_COBR_EQ_DIR(addr) \ + (uint32_t)((SNC_OPCODE_COBR << 28) + (0x0A << 20) + SNC_ADDR(addr)) +#define SNC_CMD_COBR_EQ_IND(addr) \ + (uint32_t)((SNC_OPCODE_COBR << 28) + (0x1A << 20) + SNC_ADDR(addr)) +#define SNC_CMD_COBR_GT_DIR(addr) \ + (uint32_t)((SNC_OPCODE_COBR << 28) + (0x05 << 20) + SNC_ADDR(addr)) +#define SNC_CMD_COBR_GT_IND(addr) \ + (uint32_t)((SNC_OPCODE_COBR << 28) + (0x15 << 20) + SNC_ADDR(addr)) +#define SNC_CMD_COBR_LOOP(addr, loops) \ + (uint32_t)((SNC_OPCODE_COBR << 28) + ((0x80 + (loops & 0x7f)) << 20) + \ + SNC_ADDR(addr)) + +/* + * Increment instruction + * + * Increments the contents of a memory address (RAM address) by + * either 1 or 4. + * + * INC bit value of 0: increment by 1 + * INC bit value of 1: increment by 4 + * + * ----------------------------------- + * | opcode (7) | N/C | INC | ADDR | + * ----------------------------------- + * | 31 - 28 | 27-20 | 19 | 18-0 | + * ----------------------------------- + */ +#define SNC_OPCODE_INC (7) +#define SNC_CMD_INC(addr, inc_by_4) \ + (uint32_t)((SNC_OPCODE_INC << 28) + (inc_by_4 << 19) + SNC_ADDR(addr)) +#define SNC_CMD_INC_BY_1(addr) SNC_CMD_INC(addr, 0) +#define SNC_CMD_INC_BY_4(addr) SNC_CMD_INC(addr, 1) + +/* + * Delay Instruction + * + * Delay for up to 255 LP clock ticks. + * + * ------------------------------- + * | opcode (8) | N/C | Delay | + * ------------------------------- + * | 31 - 28 | 27 - 8 | 7 - 0 | + * ------------------------------- + */ +#define SNC_OPCODE_DEL (8) +#define SNC_CMD_DEL(ticks) (uint32_t)((SNC_OPCODE_DEL << 28) | (ticks & 0xff)) + +/* + * Sleep instruction + * + * This instruction is used to halt program execution. Will + * generate a signal pulse to PDC and power down the + * sensor node controller. + * + * There are no operands for this instruction. + * + * ----------------------- + * | opcode (9) | N/C | + * ----------------------- + * | 31 - 28 | 27 - 0 | + * ----------------------- + */ +#define SNC_OPCODE_SLP (9) /* No operands */ +#define SNC_CMD_SLEEP() (uint32_t)(SNC_OPCODE_SLP << 28) + +/* + * API NOTES: + * + * 1) The SNC API are not protected by critical sections. If any of these + * API are called by more than one task or inside an ISR they need to be + * protected. + * + * 2) API with _sw_ are intended to be used when the host processor has control + * of the SNC (as opposed to the PDC). Typically these API are for debugging as + * the PDC usually controls the SNC. + */ + +/** + * initialize the SNC for software control + * + * Called when the host processor wants control of the SNC (PDC + * no longer controls SNC). + * + * @return int 0: success, -1 error. + */ +int snc_sw_init(void); + +/** + * snc sw start + * + * Starts the SNC. Note that the user should have called + * snc_sw_load prior to starting the SNC via software control. + * + * @return int 0: success -1: error + */ +int snc_sw_start(void); + +/** + * snc sw stop + * + * Stops the SNC from running a program. This should only be + * called when the SNC is under software control. + * + * @return int 0: success -1: error + */ +int snc_sw_stop(void); + +/** + * Checks if the SNC program has finished + * + * @return int 0: not finished 1: finished + */ +int snc_program_is_done(void); + +/** + * snc irq config + * + * Configures the SNC to interrupt the host processor and/or PDC + * when SNC generates an interrupt. + * + * @param mask One or more of the following: + * SNC_IRQ_MASK_NONE: Do not interrupt host or PDC + * SNC_IRQ_MASK_HOST: Interrupt host processor (CM33) + * SNC_IRQ_MASK_PDC: Interrupt PDC + * + * @return int 0: success -1: invalid mask parameter + * + * NOTES: + * + * 1) The IRQ configuration cannot be changed if there is a + * pending IRQ. The IRQ must be cleared in that case. This + * function will automatically clear the IRQ if that is the case + * and will not report an error. + */ +int snc_irq_config(uint8_t mask); + +#define SNC_IRQ_MASK_NONE (0x00) /* Do not interrupt host or PDC */ +#define SNC_IRQ_MASK_HOST (0x01) /* Interrupt host processor (CM33) */ +#define SNC_IRQ_MASK_PDC (0x02) /* Interrupt PDC */ + +/** + * snc irq clear + * + * Clears the IRQ from the SNC to the PDC and/or Host processor. + */ +static inline void +snc_irq_clear(void) +{ + SNC->SNC_CTRL_REG &= ~SNC_SNC_CTRL_REG_SNC_IRQ_ACK_Msk; +} + +/** + * snc error status + * + * Returns the status register error bits for hard fault and bus + * error. + * + * @return uint32_t Error status. + * Returns the SNC status register error bits: + * SNC_SNC_STATUS_REG_HARD_FAULT_STATUS_Msk: Hard Fault error + * SNC_SNC_STATUS_REG_BUS_ERROR_STATUS_Msk: Bus Fault error + */ +static inline uint32_t +snc_error_status(void) +{ + return SNC->SNC_STATUS_REG & (SNC_SNC_STATUS_REG_HARD_FAULT_STATUS_Msk | + SNC_SNC_STATUS_REG_BUS_ERROR_STATUS_Msk); Review comment: It is indeed inconsistent. So this does relate to my comment regarding your comment on the irq config stuff. My view is that if we use separate #defines making them the same bit positions as in the register masks is a bit confusing and should not be done. We either use the mask definitions from the header file (and I agree that we probably should not) or we use different definitions and do not rely on the mask bit positions to be the same. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [email protected] With regards, Apache Git Services
