Merge pull request #4608 from OpenNuvoton/nuvoton_m487

Support Nuvoton's new target NUMAKER_PFM_M487
pull/4935/head
Jimmy Brisson 2017-08-14 11:35:33 -05:00 committed by GitHub
commit 0150f58e12
147 changed files with 85300 additions and 34 deletions

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed 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 LWIPOPTS_CONF_H
#define LWIPOPTS_CONF_H
#define LWIP_TRANSPORT_ETHERNET 1
#define ETH_PAD_SIZE 2
#define MEM_SIZE (16*1024)//(8*1024)//(16*1024)
#endif

View File

@ -0,0 +1,378 @@
/*
* Copyright (c) 2017 Nuvoton Technology Corp.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Description: M480 MAC driver source file
*/
#include "m480_eth.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "mbed_toolchain.h"
#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0)
#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0)
#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0)
#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON;}while(0)
#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0)
/*
#ifdef __ICCARM__
#pragma data_alignment=4
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
#else
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
#endif
*/
MBED_ALIGN(4) struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
MBED_ALIGN(4) struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
MBED_ALIGN(4) u8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
MBED_ALIGN(4) u8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
extern void ethernetif_input(u16_t len, u8_t *buf, u32_t s, u32_t ns);
extern void ethernetif_loopback_input(struct pbuf *p);
extern void ack_emac_rx_isr(void);
// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns
// Assume we want to set each tick to 100ns.
// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz
// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600
static void mdio_write(u8_t addr, u8_t reg, u16_t val)
{
EMAC->MIIMDAT = val;
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
}
static u16_t mdio_read(u8_t addr, u8_t reg)
{
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
return(EMAC->MIIMDAT);
}
static int reset_phy(void)
{
u16_t reg;
u32_t delayCnt;
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);
delayCnt = 2000;
while(delayCnt-- > 0) {
if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0)
break;
}
if(delayCnt == 0) {
LWIP_DEBUGF(LWIP_DBG_LEVEL_SEVERE|LWIP_DBG_ON,("Reset phy failed\n"));
return(-1);
}
mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |
ADVERTISE_10HALF |
ADVERTISE_10FULL |
ADVERTISE_100HALF |
ADVERTISE_100FULL);
reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR);
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);
delayCnt = 200000;
while(delayCnt-- > 0) {
if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
== (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
break;
}
if(delayCnt == 0) {
LWIP_DEBUGF(LWIP_DBG_LEVEL_SEVERE|LWIP_DBG_ON , ("AN failed. Set to 100 FULL\n"));
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
return(-1);
} else {
reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);
if(reg & ADVERTISE_100FULL) {
LWIP_DEBUGF(LWIP_DBG_LEVEL_ALL|LWIP_DBG_ON, ("100 full\n"));
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
} else if(reg & ADVERTISE_100HALF) {
LWIP_DEBUGF(LWIP_DBG_LEVEL_ALL|LWIP_DBG_ON, ("100 half\n"));
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
} else if(reg & ADVERTISE_10FULL) {
LWIP_DEBUGF(LWIP_DBG_LEVEL_ALL|LWIP_DBG_ON, ("10 full\n"));
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
} else {
LWIP_DEBUGF(LWIP_DBG_LEVEL_ALL|LWIP_DBG_ON, ("10 half\n"));
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
}
}
printf("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1));
printf("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2));
return(0);
}
static void init_tx_desc(void)
{
u32_t i;
cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
for(i = 0; i < TX_DESCRIPTOR_NUM; i++) {
tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
tx_desc[i].buf = &tx_buf[i][0];
tx_desc[i].status2 = 0;
tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
}
EMAC->TXDSA = (unsigned int)&tx_desc[0];
return;
}
static void init_rx_desc(void)
{
u32_t i;
cur_rx_desc_ptr = &rx_desc[0];
for(i = 0; i < RX_DESCRIPTOR_NUM; i++) {
rx_desc[i].status1 = OWNERSHIP_EMAC;
rx_desc[i].buf = &rx_buf[i][0];
rx_desc[i].status2 = 0;
rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
}
EMAC->RXDSA = (unsigned int)&rx_desc[0];
return;
}
static void set_mac_addr(u8_t *addr)
{
EMAC->CAM0M = (addr[0] << 24) |
(addr[1] << 16) |
(addr[2] << 8) |
addr[3];
EMAC->CAM0L = (addr[4] << 24) |
(addr[5] << 16);
}
static void __eth_clk_pin_init()
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Enable IP clock */
CLK_EnableModuleClock(EMAC_MODULE);
// Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH
CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
/* Update System Core Clock */
SystemCoreClockUpdate();
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
// Configure RMII pins
SYS->GPA_MFPL = SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;
SYS->GPC_MFPL = SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0;
SYS->GPC_MFPH = SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK;
SYS->GPE_MFPH = SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |
SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |
SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |
SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |
SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;
// Enable high slew rate on all RMII TX output pins
PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |
(GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) |
(GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos);
/* Lock protected registers */
SYS_LockReg();
}
void ETH_init(u8_t *mac_addr)
{
// init CLK & pins
__eth_clk_pin_init();
// Reset MAC
EMAC->CTL = EMAC_CTL_RST_Msk;
while(EMAC->CTL & EMAC_CTL_RST_Msk) {}
init_tx_desc();
init_rx_desc();
set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc...
/* Configure the MAC interrupt enable register. */
EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
EMAC_INTEN_TXIEN_Msk |
EMAC_INTEN_RXGDIEN_Msk |
EMAC_INTEN_TXCPIEN_Msk |
EMAC_INTEN_RXBEIEN_Msk |
EMAC_INTEN_TXBEIEN_Msk |
EMAC_INTEN_RDUIEN_Msk |
EMAC_INTEN_TSALMIEN_Msk |
EMAC_INTEN_WOLIEN_Msk;
/* Configure the MAC control register. */
EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk;
/* Accept packets for us and all broadcast and multicast packets */
EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
EMAC_CAMCTL_AMP_Msk |
EMAC_CAMCTL_ABP_Msk;
EMAC->CAMEN = 1; // Enable CAM entry 0
reset_phy();
EMAC_ENABLE_RX();
EMAC_ENABLE_TX();
}
void ETH_halt(void)
{
EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk);
}
unsigned int m_status;
void EMAC_RX_IRQHandler(void)
{
m_status = EMAC->INTSTS & 0xFFFF;
EMAC->INTSTS = m_status;
if (m_status & EMAC_INTSTS_RXBEIF_Msk) {
// Shouldn't goes here, unless descriptor corrupted
LWIP_DEBUGF(LWIP_DBG_LEVEL_SERIOUS|LWIP_DBG_ON, ("RX descriptor corrupted \r\n"));
//return;
}
ack_emac_rx_isr();
}
void EMAC_RX_Action(void)
{
unsigned int cur_entry, status;
do {
cur_entry = EMAC->CRXDSA;
if ((cur_entry == (u32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) // cur_entry may equal to cur_rx_desc_ptr if RDU occures
break;
status = cur_rx_desc_ptr->status1;
if(status & OWNERSHIP_EMAC)
break;
if (status & RXFD_RXGD) {
// Lwip will invoke osMutexWait for resource protection, so ethernetif_input can't be called in EMAC_RX_IRQHandler.
ethernetif_input(status & 0xFFFF, cur_rx_desc_ptr->buf, cur_rx_desc_ptr->status2, (u32_t)cur_rx_desc_ptr->next);
}
cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
cur_rx_desc_ptr = cur_rx_desc_ptr->next;
} while (1);
ETH_TRIGGER_RX();
}
void EMAC_TX_IRQHandler(void)
{
unsigned int cur_entry, status;
status = EMAC->INTSTS & 0xFFFF0000;
EMAC->INTSTS = status;
if(status & EMAC_INTSTS_TXBEIF_Msk) {
// Shouldn't goes here, unless descriptor corrupted
return;
}
cur_entry = EMAC->CTXDSA;
while (cur_entry != (u32_t)fin_tx_desc_ptr) {
fin_tx_desc_ptr = fin_tx_desc_ptr->next;
}
}
u8_t *ETH_get_tx_buf(void)
{
if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)
return(NULL);
else
return(cur_tx_desc_ptr->buf);
}
void ETH_trigger_tx(u16_t length, struct pbuf *p)
{
struct eth_descriptor volatile *desc;
cur_tx_desc_ptr->status2 = (unsigned int)length;
desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr
cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC;
cur_tx_desc_ptr = desc;
ETH_TRIGGER_TX();
}
int ETH_link_ok()
{
/* first, a dummy read to latch */
mdio_read(CONFIG_PHY_ADDR, MII_BMSR);
if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS)
return 1;
return 0;
}

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2016 Nuvoton Technology Corp.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Description: M480 EMAC driver header file
*/
#include "lwip/def.h"
#include "lwip/pbuf.h"
#include "M480.h"
#ifndef _M480_ETH_
#define _M480_ETH_
/* Generic MII registers. */
#define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
#define MII_LPA 0x05 /* Link partner ability reg */
#define MII_EXPANSION 0x06 /* Expansion register */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
#define MII_RERRCOUNTER 0x15 /* Receive error counter */
#define MII_SREVISION 0x16 /* Silicon revision */
#define MII_RESV1 0x17 /* Reserved... */
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
#define MII_PHYADDR 0x19 /* PHY address */
#define MII_RESV2 0x1a /* Reserved... */
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
#define MII_NCONFIG 0x1c /* Network interface config */
/* Basic mode control register. */
#define BMCR_RESV 0x007f /* Unused... */
#define BMCR_CTST 0x0080 /* Collision test */
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LSTATUS 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x07c0 /* Unused... */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_RESV 0x1c00 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
#define RX_DESCRIPTOR_NUM 4 //2 // 4: Max Number of Rx Frame Descriptors
#define TX_DESCRIPTOR_NUM 4 //2 // 4: Max number of Tx Frame Descriptors
#define PACKET_BUFFER_SIZE 1520
#define CONFIG_PHY_ADDR 1
// Frame Descriptor's Owner bit
#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC
//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU
// Rx Frame Descriptor Status
#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received
#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available
// Tx Frame Descriptor's Control bits
#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable
#define TXFD_INTEN 0x04 // Interrupt Enable
#define TXFD_CRCAPP 0x02 // Append CRC
#define TXFD_PADEN 0x01 // Padding Enable
// Tx Frame Descriptor Status
#define TXFD_TXCP 0x00080000 // Transmission Completion
#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available
// Tx/Rx buffer descriptor structure
struct eth_descriptor;
struct eth_descriptor {
u32_t status1;
u8_t *buf;
u32_t status2;
struct eth_descriptor *next;
#ifdef TIME_STAMPING
u32_t backup1;
u32_t backup2;
u32_t reserved1;
u32_t reserved2;
#endif
};
#ifdef TIME_STAMPING
#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0)
#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0)
s32_t ETH_settime(u32_t sec, u32_t nsec);
s32_t ETH_gettime(u32_t *sec, u32_t *nsec);
s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec);
s32_t ETH_adjtimex(int ppm);
void ETH_setinc(void);
#endif
extern void ETH_init(u8_t *mac_addr);
extern u8_t *ETH_get_tx_buf(void);
extern void ETH_trigger_tx(u16_t length, struct pbuf *p);
#endif /* _M480_ETH_ */

View File

@ -0,0 +1,530 @@
/**
* @file
* Ethernet Interface Skeleton
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/*
* This file is a skeleton for developing Ethernet network interface
* drivers for lwIP. Add code to the low_level functions and do a
* search-and-replace for the word "ethernetif" to replace it with
* something that better describes your network interface.
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include <lwip/stats.h>
#include <lwip/snmp.h>
#include "netif/etharp.h"
#include "lwip/ethip6.h"
#include "netif/ppp/pppoe.h"
#include "m480_eth.h"
#include "string.h"
#include "eth_arch.h"
#include "sys_arch.h"
#include <ctype.h>
#include <stdio.h>
#include "mbed_interface.h"
#include "cmsis.h"
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 'n'
// Fow now, all interrupt handling happens inside one single handler, so we need to figure
// out what actually triggered the interrupt.
static volatile uint8_t emac_timer_fired;
volatile uint8_t allow_net_callbacks;
struct netif *_netif;
unsigned char my_mac_addr[6] = {0x02, 0x00, 0xac, 0x55, 0x66, 0x88};
extern u8_t my_mac_addr[6];
extern int ETH_link_ok(void);
extern void EMAC_RX_Action(void);
sys_sem_t RxReadySem; /**< RX packet ready semaphore */
static void __phy_task(void *data);
static void __packet_rx_task(void *data);
/**
* Helper struct to hold private data used to operate your ethernet interface.
* Keeping the ethernet address of the MAC in this struct is not necessary
* as it is already kept in the struct netif.
* But this is only an example, anyway...
*/
struct ethernetif {
struct eth_addr *ethaddr;
/* Add whatever per-interface state that is needed here. */
};
// Override mbed_mac_address of mbed_interface.c to provide ethernet devices with a semi-unique MAC address
void mbed_mac_address(char *mac)
{
uint32_t uID1;
// Fetch word 0
uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800
// Fetch word 1
// we only want bottom 16 bits of word1 (MAC bits 32-47)
// and bit 9 forced to 1, bit 8 forced to 0
// Locally administered MAC, reduced conflicts
// http://en.wikipedia.org/wiki/MAC_address
uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800
if( word0 == 0xFFFFFFFF ) // Not burn any mac address at 1st 2 words of Data Flash
{
// with a semi-unique MAC address from the UUID
/* Enable FMC ISP function */
SYS_UnlockReg();
FMC_Open();
// = FMC_ReadUID(0);
uID1 = FMC_ReadUID(1);
word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;
word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF);
/* Disable FMC ISP function */
FMC_Close();
/* Lock protected registers */
SYS_LockReg();
}
word1 |= 0x00000200;
word1 &= 0x0000FEFF;
mac[0] = (word1 & 0x0000ff00) >> 8;
mac[1] = (word1 & 0x000000ff);
mac[2] = (word0 & 0xff000000) >> 24;
mac[3] = (word0 & 0x00ff0000) >> 16;
mac[4] = (word0 & 0x0000ff00) >> 8;
mac[5] = (word0 & 0x000000ff);
// printf("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]);
}
/**
* In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static void
low_level_init(struct netif *netif)
{
/* set MAC hardware address length */
netif->hwaddr_len = ETH_HWADDR_LEN;
/* set MAC hardware address */
#if 1 // set MAC HW address
#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
netif->hwaddr[0] = MBED_MAC_ADDR_0;
netif->hwaddr[1] = MBED_MAC_ADDR_1;
netif->hwaddr[2] = MBED_MAC_ADDR_2;
netif->hwaddr[3] = MBED_MAC_ADDR_3;
netif->hwaddr[4] = MBED_MAC_ADDR_4;
netif->hwaddr[5] = MBED_MAC_ADDR_5;
#else
mbed_mac_address((char *)netif->hwaddr);
#endif /* set MAC HW address */
#else
netif->hwaddr[0] = my_mac_addr[0];
netif->hwaddr[1] = my_mac_addr[1];
netif->hwaddr[2] = my_mac_addr[2];
netif->hwaddr[3] = my_mac_addr[3];
netif->hwaddr[4] = my_mac_addr[4];
netif->hwaddr[5] = my_mac_addr[5];
#endif // endif
/* maximum transfer unit */
netif->mtu = 1500;
/* device capabilities */
/* NETIF_FLAG_LINK_UP should be enabled by netif_set_link_up() */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET;
#ifdef LWIP_IGMP
netif->flags |= NETIF_FLAG_IGMP;
#endif
#if LWIP_IPV6_MLD
netif->flags |= NETIF_FLAG_MLD6;
#endif
// TODO: enable clock & configure GPIO function
ETH_init(netif->hwaddr);
#if LWIP_IGMP
EMAC_ENABLE_RECV_BCASTPKT();
#endif
#if LWIP_IPV6_MLD
EMAC_ENABLE_RECV_MCASTPKT();
#endif
}
/**
* This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
* @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent
*
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
* strange results. You might consider waiting for space in the DMA queue
* to become availale since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
*/
static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
struct pbuf *q;
u8_t *buf = NULL;
u16_t len = 0;
buf = ETH_get_tx_buf();
if(buf == NULL)
return ERR_MEM;
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
for(q = p; q != NULL; q = q->next) {
memcpy((u8_t*)&buf[len], q->payload, q->len);
len = len + q->len;
}
#ifdef TIME_STAMPING
ETH_trigger_tx(len, p->flags & PBUF_FLAG_GET_TXTS ? p : NULL);
#else
ETH_trigger_tx(len, NULL);
#endif
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.xmit);
return ERR_OK;
}
/**
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
* @param netif the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header)
* NULL on memory error
*/
static struct pbuf *
low_level_input(struct netif *netif, u16_t len, u8_t *buf)
{
struct pbuf *p, *q;
#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p != NULL) {
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
len = 0;
/* We iterate over the pbuf chain until we have read the entire
* packet into the pbuf. */
for(q = p; q != NULL; q = q->next) {
memcpy((u8_t*)q->payload, (u8_t*)&buf[len], q->len);
len = len + q->len;
}
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.recv);
} else {
// do nothing. drop the packet
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
}
return p;
}
/**
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
void
ethernetif_input(u16_t len, u8_t *buf, u32_t s, u32_t ns)
{
struct eth_hdr *ethhdr;
struct pbuf *p;
/* move received packet into a new pbuf */
p = low_level_input(_netif, len, buf);
/* no packet could be read, silently ignore this */
if (p == NULL) return;
#ifdef TIME_STAMPING
p->ts_sec = s;
p->ts_nsec = ns;
#endif
/* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload;
switch (htons(ethhdr->type)) {
/* IP or ARP packet? */
case ETHTYPE_IP:
case ETHTYPE_ARP:
#if PPPOE_SUPPORT
/* PPPoE packet? */
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
/* full packet send to tcpip_thread to process */
if (_netif->input(p, _netif)!=ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(p);
p = NULL;
}
break;
default:
pbuf_free(p);
p = NULL;
break;
}
}
#ifdef TIME_STAMPING
void
ethernetif_loopback_input(struct pbuf *p) // TODO: make sure packet not drop in input()
{
/* pass all packets to ethernet_input, which decides what packets it supports */
if (netif->input(p, netif) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("k64f_enetif_input: input error\n"));
/* Free buffer */
pbuf_free(p);
}
}
#endif
/**
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t
eth_arch_enetif_init(struct netif *netif)
{
err_t err;
struct ethernetif *ethernetif;
LWIP_ASSERT("netif != NULL", (netif != NULL));
_netif = netif;
ethernetif = mem_malloc(sizeof(struct ethernetif));
if (ethernetif == NULL) {
LWIP_DEBUGF(NETIF_DEBUG, (" eth_arch_enetif_init: out of memory\n"));
return ERR_MEM;
}
// Chris: The initialization code uses osDelay, so timers neet to run
// SysTick_Init();
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "m480";
#endif /* LWIP_NETIF_HOSTNAME */
/*
* Initialize the snmp variables and counters inside the struct netif.
* The last argument should be replaced with your link speed, in units
* of bits per second.
*/
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
netif->state = ethernetif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
#if LWIP_IPV4
netif->output = etharp_output;
#endif
#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
#endif
netif->linkoutput = low_level_output;
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
/* initialize the hardware */
low_level_init(netif);
/* Packet receive task */
err = sys_sem_new(&RxReadySem, 0);
if(err != ERR_OK) {
LWIP_ASSERT("RxReadySem creation error", (err == ERR_OK));
}
// In GCC code, DEFAULT_THREAD_STACKSIZE 512 bytes is not enough for rx_task
#if defined (__GNUC__)
// mbed OS 2.0, DEFAULT_THREAD_STACKSIZE*3
// mbed OS 5.0, DEFAULT_THREAD_STACKSIZE*5
sys_thread_new("receive_thread", __packet_rx_task, &RxReadySem, DEFAULT_THREAD_STACKSIZE*5, osPriorityNormal);
#else
sys_thread_new("receive_thread", __packet_rx_task, &RxReadySem, DEFAULT_THREAD_STACKSIZE, osPriorityNormal);
#endif
/* PHY monitoring task */
#if defined (__GNUC__)
// mbed OS 2.0, DEFAULT_THREAD_STACKSIZE
// mbed OS 5.0, DEFAULT_THREAD_STACKSIZE*2
sys_thread_new("phy_thread", __phy_task, netif, DEFAULT_THREAD_STACKSIZE*2, osPriorityNormal);
#else
sys_thread_new("phy_thread", __phy_task, netif, DEFAULT_THREAD_STACKSIZE, osPriorityNormal);
#endif
/* Allow the PHY task to detect the initial link state and set up the proper flags */
osDelay(10);
return ERR_OK;
}
void eth_arch_enable_interrupts(void) {
// enet_hal_config_interrupt(BOARD_DEBUG_ENET_INSTANCE_ADDR, (kEnetTxFrameInterrupt | kEnetRxFrameInterrupt), true);
EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |
EMAC_INTEN_TXIEN_Msk ;
NVIC_EnableIRQ(EMAC_RX_IRQn);
NVIC_EnableIRQ(EMAC_TX_IRQn);
}
void eth_arch_disable_interrupts(void) {
NVIC_DisableIRQ(EMAC_RX_IRQn);
NVIC_DisableIRQ(EMAC_TX_IRQn);
}
/* Defines the PHY link speed */
typedef enum _phy_speed
{
kPHY_Speed10M = 0U, /* ENET PHY 10M speed. */
kPHY_Speed100M /* ENET PHY 100M speed. */
} phy_speed_t;
/* Defines the PHY link duplex. */
typedef enum _phy_duplex
{
kPHY_HalfDuplex = 0U, /* ENET PHY half duplex. */
kPHY_FullDuplex /* ENET PHY full duplex. */
} phy_duplex_t;
typedef struct {
int connected;
phy_speed_t speed;
phy_duplex_t duplex;
} PHY_STATE;
#define STATE_UNKNOWN (-1)
static void __phy_task(void *data) {
struct netif *netif = (struct netif*)data;
// PHY_STATE crt_state = {STATE_UNKNOWN, (phy_speed_t)STATE_UNKNOWN, (phy_duplex_t)STATE_UNKNOWN};
// PHY_STATE prev_state;
// prev_state = crt_state;
while (1) {
// Get current status
// Get the actual PHY link speed
// Compare with previous state
if( !(ETH_link_ok()) && (netif->flags & NETIF_FLAG_LINK_UP) ) {
/* tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1); */
netif_set_link_down(netif);
LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING|LWIP_DBG_ON, ("Link Down\r\n"));
}else if ( ETH_link_ok() && !(netif->flags & NETIF_FLAG_LINK_UP) ) {
/* tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1); */
netif_set_link_up(netif);
LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING|LWIP_DBG_ON, ("Link Up\r\n"));
}
osDelay(200);
}
}
void ack_emac_rx_isr()
{
sys_sem_signal(&RxReadySem);
}
static void __packet_rx_task(void *data) {
while (1) {
/* Wait for receive task to wakeup */
sys_arch_sem_wait(&RxReadySem, 0);
EMAC_RX_Action();
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2016 Nuvoton Technology Corp.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Description: EMAC driver header file
*/
#ifndef __ETHERNETIF_H__
#define __ETHERNETIF_H__
#include "lwip/err.h"
#include "lwip/netif.h"
#if defined(__cplusplus)
extern "C" {
#endif
//extern sys_sem_t tx_sem;
extern sys_sem_t rx_sem;
//err_t ethernetif_init(struct netif *netif);
//err_t ethernetif_input(struct netif *netif);
//struct netif *ethernetif_register(void);
//int ethernetif_poll(void);
#if defined(__cplusplus)
}
#endif
#ifdef SERVER
#define MAC_ADDR0 0x00
#define MAC_ADDR1 0x00
#define MAC_ADDR2 0x00
#define MAC_ADDR3 0x00
#define MAC_ADDR4 0x00
#define MAC_ADDR5 0x01
#else
#define MAC_ADDR0 0x00
#define MAC_ADDR1 0x00
#define MAC_ADDR2 0x00
#define MAC_ADDR3 0x00
#define MAC_ADDR4 0x00
//#define MAC_ADDR5 0x02
#define MAC_ADDR5 0x03
//#define MAC_ADDR5 0x04
#endif
#endif

View File

@ -0,0 +1,31 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBEDTLS_DEVICE_H
#define MBEDTLS_DEVICE_H
#define MBEDTLS_DES_ALT
#define MBEDTLS_SHA1_ALT
#define MBEDTLS_SHA256_ALT
#define MBEDTLS_SHA512_ALT
#define MBEDTLS_AES_ALT
#define MBEDTLS_AES_SETKEY_ENC_ALT
#define MBEDTLS_AES_SETKEY_DEC_ALT
#define MBEDTLS_AES_ENCRYPT_ALT
#define MBEDTLS_AES_DECRYPT_ALT
#endif /* MBEDTLS_DEVICE_H */

View File

@ -0,0 +1,584 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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.
*/
/*
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
*
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_AES_ALT)
#include <string.h>
#include "mbedtls/aes.h"
#include "M480.h"
#include "mbed_toolchain.h"
#include "mbed_assert.h"
#define mbedtls_trace(...) //printf(__VA_ARGS__)
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
}
static uint32_t au32MyAESIV[4] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
extern volatile int g_AES_done;
// Must be a multiple of 16 bytes block size
#define MAX_DMA_CHAIN_SIZE (16*6)
MBED_ALIGN(4) static uint8_t au8OutputData[MAX_DMA_CHAIN_SIZE];
MBED_ALIGN(4) static uint8_t au8InputData[MAX_DMA_CHAIN_SIZE];
static void dumpHex(const unsigned char au8Data[], int len)
{
int j;
for (j = 0; j < len; j++) mbedtls_trace("%02x ", au8Data[j]);
mbedtls_trace("\r\n");
}
static void swapInitVector(unsigned char iv[16])
{
unsigned int* piv;
int i;
// iv SWAP
piv = (unsigned int*)iv;
for( i=0; i< 4; i++)
{
*piv = (((*piv) & 0x000000FF) << 24) |
(((*piv) & 0x0000FF00) << 8) |
(((*piv) & 0x00FF0000) >> 8) |
(((*piv) & 0xFF000000) >> 24);
piv++;
}
}
/* IRQHandler: To share CRYPTO_IRQHandler() with TRNG & other crypto IPs
For ex:
volatile void CRYPTO_IRQHandler()
{
...
if (AES_GET_INT_FLAG()) {
g_AES_done = 1;
AES_CLR_INT_FLAG();
}
...
}
*/
/* AES available channel 0~3 */
static unsigned char channel_flag[4]={0x00,0x00,0x00,0x00}; // 0: idle, 1: busy
static int channel_alloc()
{
int i;
for(i=0; i< (int)sizeof(channel_flag); i++)
{
if( channel_flag[i] == 0x00 )
{
channel_flag[i] = 0x01;
return i;
}
}
return(-1);
}
static void channel_free(int i)
{
if( i >=0 && i < (int)sizeof(channel_flag) )
channel_flag[i] = 0x00;
}
void mbedtls_aes_init( mbedtls_aes_context *ctx )
{
int i =-1;
mbedtls_trace("=== %s \r\n", __FUNCTION__);
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
ctx->swapType = AES_IN_OUT_SWAP;
while( (i = channel_alloc()) < 0 )
{
mbed_assert_internal("No available AES channel", __FILE__, __LINE__);
}
ctx->channel = i;
ctx->iv = au32MyAESIV;
/* Unlock protected registers */
SYS_UnlockReg();
CLK_EnableModuleClock(CRPT_MODULE);
/* Lock protected registers */
SYS_LockReg();
NVIC_EnableIRQ(CRPT_IRQn);
AES_ENABLE_INT();
mbedtls_trace("=== %s channel[%d]\r\n", __FUNCTION__, (int)ctx->channel);
}
void mbedtls_aes_free( mbedtls_aes_context *ctx )
{
mbedtls_trace("=== %s channel[%d]\r\n", __FUNCTION__,(int)ctx->channel);
if( ctx == NULL )
return;
channel_free(ctx->channel);
mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) );
}
/*
* AES key schedule (encryption)
*/
#if defined(MBEDTLS_AES_SETKEY_ENC_ALT)
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits )
{
unsigned int i;
mbedtls_trace("=== %s keybits[%d]\r\n", __FUNCTION__, keybits);
dumpHex(key,keybits/8);
switch( keybits )
{
case 128:
ctx->keySize = AES_KEY_SIZE_128;
break;
case 192:
ctx->keySize = AES_KEY_SIZE_192;
break;
case 256:
ctx->keySize = AES_KEY_SIZE_256;
break;
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
// key swap
for( i = 0; i < ( keybits >> 5 ); i++ )
{
ctx->buf[i] = (*(key+i*4) << 24) |
(*(key+1+i*4) << 16) |
(*(key+2+i*4) << 8) |
(*(key+3+i*4) );
}
AES_SetKey(ctx->channel, ctx->buf, ctx->keySize);
return( 0 );
}
#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */
/*
* AES key schedule (decryption)
*/
#if defined(MBEDTLS_AES_SETKEY_DEC_ALT)
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits )
{
int ret;
mbedtls_trace("=== %s keybits[%d]\r\n", __FUNCTION__, keybits);
dumpHex((uint8_t *)key,keybits/8);
/* Also checks keybits */
if( ( ret = mbedtls_aes_setkey_enc( ctx, key, keybits ) ) != 0 )
goto exit;
exit:
return( ret );
}
#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */
static void __nvt_aes_crypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16], int dataSize)
{
unsigned char* pIn;
unsigned char* pOut;
// mbedtls_trace("=== %s \r\n", __FUNCTION__);
dumpHex(input,16);
AES_Open(ctx->channel, ctx->encDec, ctx->opMode, ctx->keySize, ctx->swapType);
AES_SetInitVect(ctx->channel, ctx->iv);
if( ((uint32_t)input) & 0x03 )
{
memcpy(au8InputData, input, dataSize);
pIn = au8InputData;
}else{
pIn = (unsigned char*)input;
}
if( (((uint32_t)output) & 0x03) || (dataSize%4)) // HW CFB output byte count must be multiple of word
{
pOut = au8OutputData;
} else {
pOut = output;
}
AES_SetDMATransfer(ctx->channel, (uint32_t)pIn, (uint32_t)pOut, dataSize);
g_AES_done = 0;
AES_Start(ctx->channel, CRYPTO_DMA_ONE_SHOT);
while (!g_AES_done);
if( pOut != output ) memcpy(output, au8OutputData, dataSize);
dumpHex(output,16);
}
/*
* AES-ECB block encryption
*/
#if defined(MBEDTLS_AES_ENCRYPT_ALT)
void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
mbedtls_trace("=== %s \r\n", __FUNCTION__);
ctx->encDec = 1;
__nvt_aes_crypt(ctx, input, output, 16);
}
#endif /* MBEDTLS_AES_ENCRYPT_ALT */
/*
* AES-ECB block decryption
*/
#if defined(MBEDTLS_AES_DECRYPT_ALT)
void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
mbedtls_trace("=== %s \r\n", __FUNCTION__);
ctx->encDec = 0;
__nvt_aes_crypt(ctx, input, output, 16);
}
#endif /* MBEDTLS_AES_DECRYPT_ALT */
/*
* AES-ECB block encryption/decryption
*/
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] )
{
mbedtls_trace("=== %s \r\n", __FUNCTION__);
ctx->opMode = AES_MODE_ECB;
if( mode == MBEDTLS_AES_ENCRYPT )
mbedtls_aes_encrypt( ctx, input, output );
else
mbedtls_aes_decrypt( ctx, input, output );
return( 0 );
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/*
* AES-CBC buffer encryption/decryption
*/
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int mode,
size_t len,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
unsigned char temp[16];
int length = len;
int blockChainLen;
mbedtls_trace("=== %s [0x%x]\r\n", __FUNCTION__,length);
if( length % 16 )
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
if( (((uint32_t)input) & 0x03) || (((uint32_t)output) & 0x03) )
{
blockChainLen = (( length > MAX_DMA_CHAIN_SIZE ) ? MAX_DMA_CHAIN_SIZE : length );
} else {
blockChainLen = length;
}
while( length > 0 )
{
ctx->opMode = AES_MODE_CBC;
swapInitVector(iv); // iv SWAP
ctx->iv = (uint32_t *)iv;
if( mode == MBEDTLS_AES_ENCRYPT )
{
ctx->encDec = 1;
__nvt_aes_crypt(ctx, input, output, blockChainLen);
// if( blockChainLen == length ) break; // finish last block chain but still need to prepare next iv for mbedtls_aes_self_test()
memcpy( iv, output+blockChainLen-16, 16 );
}else{
memcpy( temp, input+blockChainLen-16, 16 );
ctx->encDec = 0;
__nvt_aes_crypt(ctx, input, output, blockChainLen);
// if( blockChainLen == length ) break; // finish last block chain but still need to prepare next iv for mbedtls_aes_self_test()
memcpy( iv, temp, 16 );
}
length -= blockChainLen;
input += blockChainLen;
output += blockChainLen;
if(length < MAX_DMA_CHAIN_SIZE ) blockChainLen = length; // For last remainder block chain
}
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/*
* AES-CFB128 buffer encryption/decryption
*/
/* Support partial block encryption/decryption */
static int __nvt_aes_crypt_partial_block_cfb128( mbedtls_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int c;
size_t n = *iv_off;
unsigned char iv_tmp[16];
mbedtls_trace("=== %s \r\n", __FUNCTION__);
if( mode == MBEDTLS_AES_DECRYPT )
{
while( length-- )
{
if( n == 0)
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
else if( ctx->opMode == AES_MODE_CFB) // For previous cryption is CFB mode
{
memcpy(iv_tmp, iv, n);
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, ctx->prv_iv, iv );
memcpy(iv, iv_tmp, n);
}
c = *input++;
*output++ = (unsigned char)( c ^ iv[n] );
iv[n] = (unsigned char) c;
n = ( n + 1 ) & 0x0F;
}
}
else
{
while( length-- )
{
if( n == 0 )
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
else if( ctx->opMode == AES_MODE_CFB) // For previous cryption is CFB mode
{
memcpy(iv_tmp, iv, n);
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, ctx->prv_iv, iv );
memcpy(iv, iv_tmp, n);
}
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
n = ( n + 1 ) & 0x0F;
}
}
*iv_off = n;
return( 0 );
}
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
int mode,
size_t len,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
size_t n = *iv_off;
unsigned char temp[16];
int length=len;
int blockChainLen;
int remLen=0;
int ivLen;
mbedtls_trace("=== %s \r\n", __FUNCTION__);
// proceed: start with partial block by ECB mode first
if( n !=0 ) {
__nvt_aes_crypt_partial_block_cfb128(ctx, mode, 16 - n , iv_off, iv, input, output);
input += (16 - n);
output += (16 - n);
length -= (16 - n);
}
// For address or byte count non-word alignment, go through reserved DMA buffer.
if( (((uint32_t)input) & 0x03) || (((uint32_t)output) & 0x03) ) // Must reserved DMA buffer for each block
{
blockChainLen = (( length > MAX_DMA_CHAIN_SIZE ) ? MAX_DMA_CHAIN_SIZE : length );
} else if(length%4) { // Need reserved DMA buffer once for last chain
blockChainLen = (( length > MAX_DMA_CHAIN_SIZE ) ? (length - length%16) : length );
} else { // Not need reserved DMA buffer
blockChainLen = length;
}
// proceed: start with block alignment
while( length > 0 )
{
ctx->opMode = AES_MODE_CFB;
swapInitVector(iv); // iv SWAP
ctx->iv = (uint32_t *)iv;
remLen = blockChainLen%16;
ivLen = (( remLen > 0) ? remLen: 16 );
if( mode == MBEDTLS_AES_DECRYPT )
{
memcpy(temp, input+blockChainLen - ivLen, ivLen);
if(blockChainLen >= 16) memcpy(ctx->prv_iv, input+blockChainLen-remLen-16 , 16);
ctx->encDec = 0;
__nvt_aes_crypt(ctx, input, output, blockChainLen);
memcpy(iv,temp, ivLen);
}
else
{
ctx->encDec = 1;
__nvt_aes_crypt(ctx, input, output, blockChainLen);
if(blockChainLen >= 16) memcpy(ctx->prv_iv, output+blockChainLen-remLen-16 , 16);
memcpy(iv,output+blockChainLen-ivLen,ivLen);
}
length -= blockChainLen;
input += blockChainLen;
output += blockChainLen;
if(length < MAX_DMA_CHAIN_SIZE ) blockChainLen = length; // For last remainder block chain
}
*iv_off = remLen;
return( 0 );
}
/*
* AES-CFB8 buffer encryption/decryption
*/
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
unsigned char c;
unsigned char ov[17];
mbedtls_trace("=== %s \r\n", __FUNCTION__);
while( length-- )
{
memcpy( ov, iv, 16 );
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
if( mode == MBEDTLS_AES_DECRYPT )
ov[16] = *input;
c = *output++ = (unsigned char)( iv[0] ^ *input++ );
if( mode == MBEDTLS_AES_ENCRYPT )
ov[16] = c;
memcpy( iv, ov + 1, 16 );
}
return( 0 );
}
#endif /*MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
* AES-CTR buffer encryption/decryption
*/
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output )
{
int c, i;
size_t n = *nc_off;
mbedtls_trace("=== %s \r\n", __FUNCTION__);
while( length-- )
{
if( n == 0 ) {
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
for( i = 16; i > 0; i-- )
if( ++nonce_counter[i - 1] != 0 )
break;
}
c = *input++;
*output++ = (unsigned char)( c ^ stream_block[n] );
n = ( n + 1 ) & 0x0F;
}
*nc_off = n;
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#endif /* MBEDTLS_AES_ALT */
#endif /* MBEDTLS_AES_C */

View File

@ -0,0 +1,284 @@
/**
* \file aes_alt.h
*
* \brief AES block cipher
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_AES_ALT_H
#define MBEDTLS_AES_ALT_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_AES_ALT)
// Regular implementation
//
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief AES context structure
*
* \note buf is able to hold 32 extra bytes, which can be used:
* - for alignment purposes if VIA padlock is used, and/or
* - to simplify key expansion in the 256-bit case by
* generating an extra round key
*/
typedef struct
{
uint32_t keySize;
uint32_t encDec;
uint32_t opMode;
uint32_t channel;
uint32_t swapType;
uint32_t *iv;
unsigned char prv_iv[16];
#if 1
uint32_t buf[8];
/* For comparsion with software AES for correctness */
#else
uint32_t buf[68]; /*!< unaligned data */
int nr; /*!< number of rounds */
uint32_t *rk; /*!< AES round keys */
#endif
}
mbedtls_aes_context;
/**
* \brief Initialize AES context
*
* \param ctx AES context to be initialized
*/
void mbedtls_aes_init( mbedtls_aes_context *ctx );
/**
* \brief Clear AES context
*
* \param ctx AES context to be cleared
*/
void mbedtls_aes_free( mbedtls_aes_context *ctx );
/**
* \brief AES key schedule (encryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits );
/**
* \brief AES key schedule (decryption)
*
* \param ctx AES context to be initialized
* \param key decryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits );
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
*/
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/**
* \brief AES-CFB128 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CFB8 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#endif /*MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/**
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
*
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \param ctx AES context
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to
* should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten
* by the function.
* \param input The input data stream
* \param output The output data stream
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CTR */
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_ENCRYPT_ALT)
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*/
void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_DECRYPT_ALT)
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*/
void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_AES_ALT */
#endif /* MBEDTLS_AES_C */
#endif /* aes_alt.h */

View File

@ -0,0 +1,63 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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.
*/
#include "cmsis.h"
#include "mbed_assert.h"
#include "nu_modutil.h"
#include "nu_bitutil.h"
#include "crypto-misc.h"
static int crypto_inited = 0;
static int crypto_sha_avail = 1;
void crypto_init(void)
{
if (crypto_inited) {
return;
}
crypto_inited = 1;
CLK_EnableModuleClock(CRPT_MODULE);
}
/* Implementation that should never be optimized out by the compiler */
void crypto_zeroize(void *v, size_t n)
{
volatile unsigned char *p = (unsigned char*) v;
while (n--) {
*p++ = 0;
}
}
int crypto_sha_acquire(void)
{
if (crypto_sha_avail) {
crypto_sha_avail = 0;
return 1;
}
else {
return 0;
}
}
void crypto_sha_release(void)
{
if (! crypto_sha_avail) {
crypto_sha_avail = 1;
}
}

View File

@ -0,0 +1,33 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBED_CRYPTO_MISC_H
#define MBED_CRYPTO_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
void crypto_init(void);
void crypto_zeroize(void *v, size_t n);
int crypto_sha_acquire(void);
void crypto_sha_release(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,410 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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.
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_DES_C)
#if defined(MBEDTLS_DES_ALT)
#include <string.h>
#include "mbedtls/des.h"
#include "des_alt.h"
#include "crypto-misc.h"
#include "nu_bitutil.h"
#include "mbed_toolchain.h"
// Must be a multiple of 64-bit block size
#define MAXSIZE_DMABUF (8 * 5)
static uint8_t dmabuf_in[MAXSIZE_DMABUF] MBED_ALIGN(4);
static uint8_t dmabuf_out[MAXSIZE_DMABUF] MBED_ALIGN(4);
static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length,
unsigned char iv[8], const unsigned char *input, unsigned char *output);
void mbedtls_des_init(mbedtls_des_context *ctx)
{
crypto_init();
memset(ctx, 0, sizeof(mbedtls_des_context));
}
void mbedtls_des_free( mbedtls_des_context *ctx )
{
if (ctx == NULL) {
return;
}
crypto_zeroize(ctx, sizeof(mbedtls_des_context));
}
void mbedtls_des3_init( mbedtls_des3_context *ctx )
{
crypto_init();
memset(ctx, 0, sizeof(mbedtls_des3_context));
}
void mbedtls_des3_free( mbedtls_des3_context *ctx )
{
if (ctx == NULL) {
return;
}
crypto_zeroize(ctx, sizeof (mbedtls_des3_context));
}
static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
254 };
void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE])
{
int i;
for (i = 0; i < MBEDTLS_DES_KEY_SIZE; i++) {
key[i] = odd_parity_table[key[i] / 2];
}
}
/*
* Check the given key's parity, returns 1 on failure, 0 on SUCCESS
*/
int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
{
int i;
for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ )
if( key[i] != odd_parity_table[key[i] / 2] )
return( 1 );
return( 0 );
}
/*
* Table of weak and semi-weak keys
*
* Source: http://en.wikipedia.org/wiki/Weak_key
*
* Weak:
* Alternating ones + zeros (0x0101010101010101)
* Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
* '0xE0E0E0E0F1F1F1F1'
* '0x1F1F1F1F0E0E0E0E'
*
* Semi-weak:
* 0x011F011F010E010E and 0x1F011F010E010E01
* 0x01E001E001F101F1 and 0xE001E001F101F101
* 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
* 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
* 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
* 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
*
*/
#define WEAK_KEY_COUNT 16
static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] =
{
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
{ 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
{ 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
{ 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
{ 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
{ 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
{ 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
{ 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
{ 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
{ 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
{ 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
{ 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
{ 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
{ 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
};
int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
{
int i;
for( i = 0; i < WEAK_KEY_COUNT; i++ )
if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 )
return( 1 );
return( 0 );
}
/*
* DES key schedule (56-bit, encryption)
*/
int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
{
ctx->enc = 1;
// Keying option 3: All three keys are identical, i.e. K1 = K2 = K3.
ctx->keyopt = 3;
memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[1], key, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE);
return 0;
}
/*
* DES key schedule (56-bit, decryption)
*/
int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
{
ctx->enc = 0;
// Keying option 3: All three keys are identical, i.e. K1 = K2 = K3.
ctx->keyopt = 3;
memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[1], key, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE);
return 0;
}
/*
* Triple-DES key schedule (112-bit, encryption)
*/
int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
{
ctx->enc = 1;
// Keying option 2: K1 and K2 are independent, and K3 = K1.
ctx->keyopt = 2;
memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[1], key + MBEDTLS_DES_KEY_SIZE, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE);
return 0;
}
/*
* Triple-DES key schedule (112-bit, decryption)
*/
int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
{
ctx->enc = 0;
// Keying option 2: K1 and K2 are independent, and K3 = K1.
ctx->keyopt = 2;
memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[1], key + MBEDTLS_DES_KEY_SIZE, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[2], key, MBEDTLS_DES_KEY_SIZE);
return 0;
}
/*
* Triple-DES key schedule (168-bit, encryption)
*/
int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
{
ctx->enc = 1;
// Keying option 1: All three keys are independent.
ctx->keyopt = 1;
memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[1], key + MBEDTLS_DES_KEY_SIZE, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[2], key + MBEDTLS_DES_KEY_SIZE * 2, MBEDTLS_DES_KEY_SIZE);
return 0;
}
/*
* Triple-DES key schedule (168-bit, decryption)
*/
int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
{
ctx->enc = 0;
// Keying option 1: All three keys are independent.
ctx->keyopt = 1;
memcpy(ctx->key[0], key, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[1], key + MBEDTLS_DES_KEY_SIZE, MBEDTLS_DES_KEY_SIZE);
memcpy(ctx->key[2], key + MBEDTLS_DES_KEY_SIZE * 2, MBEDTLS_DES_KEY_SIZE);
return 0;
}
/*
* DES-ECB block encryption/decryption
*/
int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
const unsigned char input[8],
unsigned char output[8] )
{
unsigned char iv[8] = {0x00};
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, DES_MODE_ECB, 8, iv, input, output);
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/*
* DES-CBC buffer encryption/decryption
*/
int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
int mode,
size_t length,
unsigned char iv[8],
const unsigned char *input,
unsigned char *output )
{
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, DES_MODE_CBC, length, iv, input, output);
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
/*
* 3DES-ECB block encryption/decryption
*/
int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
const unsigned char input[8],
unsigned char output[8] )
{
unsigned char iv[8] = {0x00};
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, ctx->enc, TDES_MODE_ECB, 8, iv, input, output);
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/*
* 3DES-CBC buffer encryption/decryption
*/
int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
int mode,
size_t length,
unsigned char iv[8],
const unsigned char *input,
unsigned char *output )
{
return mbedtls_des_docrypt(ctx->keyopt, ctx->key, mode == MBEDTLS_DES_ENCRYPT, TDES_MODE_CBC, length, iv, input, output);
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_SIZE], int enc, uint32_t tdes_opmode, size_t length,
unsigned char iv[8], const unsigned char *input, unsigned char *output)
{
if (length % 8) {
return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH;
}
// NOTE: Don't call driver function TDES_Open in BSP because it doesn't support TDES_CTL[3KEYS] setting.
CRPT->TDES_CTL = (0 << CRPT_TDES_CTL_CHANNEL_Pos) | (enc << CRPT_TDES_CTL_ENCRPT_Pos) |
tdes_opmode | (TDES_IN_OUT_WHL_SWAP << CRPT_TDES_CTL_BLKSWAP_Pos);
// Keying option 1: All three keys are independent.
// Keying option 2: K1 and K2 are independent, and K3 = K1.
// Keying option 3: All three keys are identical, i.e. K1 = K2 = K3.
if (keyopt == 1) {
CRPT->TDES_CTL |= CRPT_TDES_CTL_3KEYS_Msk;
}
else {
CRPT->TDES_CTL &= ~CRPT_TDES_CTL_3KEYS_Msk;
}
// Set DES/TDES keys
// NOTE: Don't call driver function TDES_SetKey in BSP because it doesn't support endian swap.
uint32_t val;
volatile uint32_t *tdes_key = (uint32_t *) ((uint32_t) &CRPT->TDES0_KEY1H + (0x40 * 0));
val = nu_get32_be(key[0] + 0);
*tdes_key ++ = val;
val = nu_get32_be(key[0] + 4);
*tdes_key ++ = val;
val = nu_get32_be(key[1] + 0);
*tdes_key ++ = val;
val = nu_get32_be(key[1] + 4);
*tdes_key ++ = val;
val = nu_get32_be(key[2] + 0);
*tdes_key ++ = val;
val = nu_get32_be(key[2] + 4);
*tdes_key ++ = val;
uint32_t rmn = length;
const unsigned char *in_pos = input;
unsigned char *out_pos = output;
while (rmn) {
uint32_t data_len = (rmn <= MAXSIZE_DMABUF) ? rmn : MAXSIZE_DMABUF;
uint32_t ivh, ivl;
ivh = nu_get32_be(iv);
ivl = nu_get32_be(iv + 4);
TDES_SetInitVect(0, ivh, ivl);
memcpy(dmabuf_in, in_pos, data_len);
TDES_SetDMATransfer(0, (uint32_t) dmabuf_in, (uint32_t) dmabuf_out, data_len);
// Start enc/dec.
// NOTE: Don't call driver function TDES_Start in BSP because it will override TDES_CTL[3KEYS] setting.
CRPT->TDES_CTL |= CRPT_TDES_CTL_START_Msk | (CRYPTO_DMA_ONE_SHOT << CRPT_TDES_CTL_DMALAST_Pos);
while (CRPT->TDES_STS & CRPT_TDES_STS_BUSY_Msk);
memcpy(out_pos, dmabuf_out, data_len);
in_pos += data_len;
out_pos += data_len;
rmn -= data_len;
// Update IV for next block enc/dec in next function call
switch (tdes_opmode) {
case DES_MODE_OFB:
case TDES_MODE_OFB: {
// OFB: IV (enc/dec) = output block XOR input block
uint32_t lbh, lbl;
// Last block of input data
lbh = nu_get32_be(dmabuf_in + data_len - 8 + 4);
lbl = nu_get32_be(dmabuf_in + data_len - 8 + 0);
// Last block of output data
ivh = nu_get32_be(dmabuf_out + 4);
ivl = nu_get32_be(dmabuf_out + 0);
ivh = ivh ^ lbh;
ivl = ivl ^ lbl;
nu_set32_be(iv + 4, ivh);
nu_set32_be(iv, ivl);
break;
}
case DES_MODE_CBC:
case DES_MODE_CFB:
case TDES_MODE_CBC:
case TDES_MODE_CFB: {
// CBC/CFB: IV (enc) = output block
// IV (dec) = input block
if (enc) {
memcpy(iv, dmabuf_out + data_len - 8, 8);
}
else {
memcpy(iv, dmabuf_in + data_len - 8, 8);
}
}
}
}
return 0;
}
#endif /* MBEDTLS_DES_ALT */
#endif /* MBEDTLS_DES_C */

View File

@ -0,0 +1,282 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBEDTLS_DES_ALT_H
#define MBEDTLS_DES_ALT_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_DES_C)
#if defined(MBEDTLS_DES_ALT)
#include <stddef.h>
#include <stdint.h>
#include "des.h"
#include "des_alt_sw.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief DES context structure
*/
typedef struct
{
int enc; /*!< 0: dec, 1: enc */
uint16_t keyopt;
uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /*!< 3DES keys */
}
mbedtls_des_context;
/**
* \brief Triple-DES context structure
*/
typedef struct
{
int enc; /*!< 0: dec, 1: enc */
uint16_t keyopt;
uint8_t key[3][MBEDTLS_DES_KEY_SIZE]; /*!< 3DES keys */
}
mbedtls_des3_context;
/**
* \brief Initialize DES context
*
* \param ctx DES context to be initialized
*/
void mbedtls_des_init( mbedtls_des_context *ctx );
/**
* \brief Clear DES context
*
* \param ctx DES context to be cleared
*/
void mbedtls_des_free( mbedtls_des_context *ctx );
/**
* \brief Initialize Triple-DES context
*
* \param ctx DES3 context to be initialized
*/
void mbedtls_des3_init( mbedtls_des3_context *ctx );
/**
* \brief Clear Triple-DES context
*
* \param ctx DES3 context to be cleared
*/
void mbedtls_des3_free( mbedtls_des3_context *ctx );
/**
* \brief Set key parity on the given key to odd.
*
* DES keys are 56 bits long, but each byte is padded with
* a parity bit to allow verification.
*
* \param key 8-byte secret key
*/
void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/**
* \brief Check that key parity on the given key is odd.
*
* DES keys are 56 bits long, but each byte is padded with
* a parity bit to allow verification.
*
* \param key 8-byte secret key
*
* \return 0 is parity was ok, 1 if parity was not correct.
*/
int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/**
* \brief Check that key is not a weak or semi-weak DES key
*
* \param key 8-byte secret key
*
* \return 0 if no weak key was found, 1 if a weak key was identified.
*/
int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/**
* \brief DES key schedule (56-bit, encryption)
*
* \param ctx DES context to be initialized
* \param key 8-byte secret key
*
* \return 0
*/
int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/**
* \brief DES key schedule (56-bit, decryption)
*
* \param ctx DES context to be initialized
* \param key 8-byte secret key
*
* \return 0
*/
int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/**
* \brief Triple-DES key schedule (112-bit, encryption)
*
* \param ctx 3DES context to be initialized
* \param key 16-byte secret key
*
* \return 0
*/
int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
/**
* \brief Triple-DES key schedule (112-bit, decryption)
*
* \param ctx 3DES context to be initialized
* \param key 16-byte secret key
*
* \return 0
*/
int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
/**
* \brief Triple-DES key schedule (168-bit, encryption)
*
* \param ctx 3DES context to be initialized
* \param key 24-byte secret key
*
* \return 0
*/
int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
/**
* \brief Triple-DES key schedule (168-bit, decryption)
*
* \param ctx 3DES context to be initialized
* \param key 24-byte secret key
*
* \return 0
*/
int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
/**
* \brief DES-ECB block encryption/decryption
*
* \param ctx DES context
* \param input 64-bit input block
* \param output 64-bit output block
*
* \return 0 if successful
*/
int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
const unsigned char input[8],
unsigned char output[8] );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/**
* \brief DES-CBC buffer encryption/decryption
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx DES context
* \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*/
int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
int mode,
size_t length,
unsigned char iv[8],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */
/**
* \brief 3DES-ECB block encryption/decryption
*
* \param ctx 3DES context
* \param input 64-bit input block
* \param output 64-bit output block
*
* \return 0 if successful
*/
int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
const unsigned char input[8],
unsigned char output[8] );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/**
* \brief 3DES-CBC buffer encryption/decryption
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx 3DES context
* \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
*/
int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
int mode,
size_t length,
unsigned char iv[8],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */
/**
* \brief Internal function for key expansion.
* (Only exposed to allow overriding it,
* see MBEDTLS_DES_SETKEY_ALT)
*
* \param SK Round keys
* \param key Base key
*/
void mbedtls_des_setkey( uint32_t SK[32],
const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_DES_ALT */
#endif /* MBEDTLS_DES_C */
#endif /* des_alt.h */

View File

@ -0,0 +1,797 @@
/*
* FIPS-46-3 compliant Triple-DES implementation
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* DES, on which TDES is based, was originally designed by Horst Feistel
* at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
*
* http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_DES_C)
#if defined(MBEDTLS_DES_ALT)
#include "mbedtls/des.h"
#include <string.h>
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/*
* Expanded DES S-boxes
*/
static const uint32_t SB1[64] =
{
0x01010400, 0x00000000, 0x00010000, 0x01010404,
0x01010004, 0x00010404, 0x00000004, 0x00010000,
0x00000400, 0x01010400, 0x01010404, 0x00000400,
0x01000404, 0x01010004, 0x01000000, 0x00000004,
0x00000404, 0x01000400, 0x01000400, 0x00010400,
0x00010400, 0x01010000, 0x01010000, 0x01000404,
0x00010004, 0x01000004, 0x01000004, 0x00010004,
0x00000000, 0x00000404, 0x00010404, 0x01000000,
0x00010000, 0x01010404, 0x00000004, 0x01010000,
0x01010400, 0x01000000, 0x01000000, 0x00000400,
0x01010004, 0x00010000, 0x00010400, 0x01000004,
0x00000400, 0x00000004, 0x01000404, 0x00010404,
0x01010404, 0x00010004, 0x01010000, 0x01000404,
0x01000004, 0x00000404, 0x00010404, 0x01010400,
0x00000404, 0x01000400, 0x01000400, 0x00000000,
0x00010004, 0x00010400, 0x00000000, 0x01010004
};
static const uint32_t SB2[64] =
{
0x80108020, 0x80008000, 0x00008000, 0x00108020,
0x00100000, 0x00000020, 0x80100020, 0x80008020,
0x80000020, 0x80108020, 0x80108000, 0x80000000,
0x80008000, 0x00100000, 0x00000020, 0x80100020,
0x00108000, 0x00100020, 0x80008020, 0x00000000,
0x80000000, 0x00008000, 0x00108020, 0x80100000,
0x00100020, 0x80000020, 0x00000000, 0x00108000,
0x00008020, 0x80108000, 0x80100000, 0x00008020,
0x00000000, 0x00108020, 0x80100020, 0x00100000,
0x80008020, 0x80100000, 0x80108000, 0x00008000,
0x80100000, 0x80008000, 0x00000020, 0x80108020,
0x00108020, 0x00000020, 0x00008000, 0x80000000,
0x00008020, 0x80108000, 0x00100000, 0x80000020,
0x00100020, 0x80008020, 0x80000020, 0x00100020,
0x00108000, 0x00000000, 0x80008000, 0x00008020,
0x80000000, 0x80100020, 0x80108020, 0x00108000
};
static const uint32_t SB3[64] =
{
0x00000208, 0x08020200, 0x00000000, 0x08020008,
0x08000200, 0x00000000, 0x00020208, 0x08000200,
0x00020008, 0x08000008, 0x08000008, 0x00020000,
0x08020208, 0x00020008, 0x08020000, 0x00000208,
0x08000000, 0x00000008, 0x08020200, 0x00000200,
0x00020200, 0x08020000, 0x08020008, 0x00020208,
0x08000208, 0x00020200, 0x00020000, 0x08000208,
0x00000008, 0x08020208, 0x00000200, 0x08000000,
0x08020200, 0x08000000, 0x00020008, 0x00000208,
0x00020000, 0x08020200, 0x08000200, 0x00000000,
0x00000200, 0x00020008, 0x08020208, 0x08000200,
0x08000008, 0x00000200, 0x00000000, 0x08020008,
0x08000208, 0x00020000, 0x08000000, 0x08020208,
0x00000008, 0x00020208, 0x00020200, 0x08000008,
0x08020000, 0x08000208, 0x00000208, 0x08020000,
0x00020208, 0x00000008, 0x08020008, 0x00020200
};
static const uint32_t SB4[64] =
{
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802080, 0x00800081, 0x00800001, 0x00002001,
0x00000000, 0x00802000, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00800080, 0x00800001,
0x00000001, 0x00002000, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002001, 0x00002080,
0x00800081, 0x00000001, 0x00002080, 0x00800080,
0x00002000, 0x00802080, 0x00802081, 0x00000081,
0x00800080, 0x00800001, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00000000, 0x00802000,
0x00002080, 0x00800080, 0x00800081, 0x00000001,
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802081, 0x00000081, 0x00000001, 0x00002000,
0x00800001, 0x00002001, 0x00802080, 0x00800081,
0x00002001, 0x00002080, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002000, 0x00802080
};
static const uint32_t SB5[64] =
{
0x00000100, 0x02080100, 0x02080000, 0x42000100,
0x00080000, 0x00000100, 0x40000000, 0x02080000,
0x40080100, 0x00080000, 0x02000100, 0x40080100,
0x42000100, 0x42080000, 0x00080100, 0x40000000,
0x02000000, 0x40080000, 0x40080000, 0x00000000,
0x40000100, 0x42080100, 0x42080100, 0x02000100,
0x42080000, 0x40000100, 0x00000000, 0x42000000,
0x02080100, 0x02000000, 0x42000000, 0x00080100,
0x00080000, 0x42000100, 0x00000100, 0x02000000,
0x40000000, 0x02080000, 0x42000100, 0x40080100,
0x02000100, 0x40000000, 0x42080000, 0x02080100,
0x40080100, 0x00000100, 0x02000000, 0x42080000,
0x42080100, 0x00080100, 0x42000000, 0x42080100,
0x02080000, 0x00000000, 0x40080000, 0x42000000,
0x00080100, 0x02000100, 0x40000100, 0x00080000,
0x00000000, 0x40080000, 0x02080100, 0x40000100
};
static const uint32_t SB6[64] =
{
0x20000010, 0x20400000, 0x00004000, 0x20404010,
0x20400000, 0x00000010, 0x20404010, 0x00400000,
0x20004000, 0x00404010, 0x00400000, 0x20000010,
0x00400010, 0x20004000, 0x20000000, 0x00004010,
0x00000000, 0x00400010, 0x20004010, 0x00004000,
0x00404000, 0x20004010, 0x00000010, 0x20400010,
0x20400010, 0x00000000, 0x00404010, 0x20404000,
0x00004010, 0x00404000, 0x20404000, 0x20000000,
0x20004000, 0x00000010, 0x20400010, 0x00404000,
0x20404010, 0x00400000, 0x00004010, 0x20000010,
0x00400000, 0x20004000, 0x20000000, 0x00004010,
0x20000010, 0x20404010, 0x00404000, 0x20400000,
0x00404010, 0x20404000, 0x00000000, 0x20400010,
0x00000010, 0x00004000, 0x20400000, 0x00404010,
0x00004000, 0x00400010, 0x20004010, 0x00000000,
0x20404000, 0x20000000, 0x00400010, 0x20004010
};
static const uint32_t SB7[64] =
{
0x00200000, 0x04200002, 0x04000802, 0x00000000,
0x00000800, 0x04000802, 0x00200802, 0x04200800,
0x04200802, 0x00200000, 0x00000000, 0x04000002,
0x00000002, 0x04000000, 0x04200002, 0x00000802,
0x04000800, 0x00200802, 0x00200002, 0x04000800,
0x04000002, 0x04200000, 0x04200800, 0x00200002,
0x04200000, 0x00000800, 0x00000802, 0x04200802,
0x00200800, 0x00000002, 0x04000000, 0x00200800,
0x04000000, 0x00200800, 0x00200000, 0x04000802,
0x04000802, 0x04200002, 0x04200002, 0x00000002,
0x00200002, 0x04000000, 0x04000800, 0x00200000,
0x04200800, 0x00000802, 0x00200802, 0x04200800,
0x00000802, 0x04000002, 0x04200802, 0x04200000,
0x00200800, 0x00000000, 0x00000002, 0x04200802,
0x00000000, 0x00200802, 0x04200000, 0x00000800,
0x04000002, 0x04000800, 0x00000800, 0x00200002
};
static const uint32_t SB8[64] =
{
0x10001040, 0x00001000, 0x00040000, 0x10041040,
0x10000000, 0x10001040, 0x00000040, 0x10000000,
0x00040040, 0x10040000, 0x10041040, 0x00041000,
0x10041000, 0x00041040, 0x00001000, 0x00000040,
0x10040000, 0x10000040, 0x10001000, 0x00001040,
0x00041000, 0x00040040, 0x10040040, 0x10041000,
0x00001040, 0x00000000, 0x00000000, 0x10040040,
0x10000040, 0x10001000, 0x00041040, 0x00040000,
0x00041040, 0x00040000, 0x10041000, 0x00001000,
0x00000040, 0x10040040, 0x00001000, 0x00041040,
0x10001000, 0x00000040, 0x10000040, 0x10040000,
0x10040040, 0x10000000, 0x00040000, 0x10001040,
0x00000000, 0x10041040, 0x00040040, 0x10000040,
0x10040000, 0x10001000, 0x10001040, 0x00000000,
0x10041040, 0x00041000, 0x00041000, 0x00001040,
0x00001040, 0x00040040, 0x10000000, 0x10041000
};
/*
* PC1: left and right halves bit-swap
*/
static const uint32_t LHs[16] =
{
0x00000000, 0x00000001, 0x00000100, 0x00000101,
0x00010000, 0x00010001, 0x00010100, 0x00010101,
0x01000000, 0x01000001, 0x01000100, 0x01000101,
0x01010000, 0x01010001, 0x01010100, 0x01010101
};
static const uint32_t RHs[16] =
{
0x00000000, 0x01000000, 0x00010000, 0x01010000,
0x00000100, 0x01000100, 0x00010100, 0x01010100,
0x00000001, 0x01000001, 0x00010001, 0x01010001,
0x00000101, 0x01000101, 0x00010101, 0x01010101,
};
/*
* Initial Permutation macro
*/
#define DES_IP(X,Y) \
{ \
T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \
T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \
X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \
}
/*
* Final Permutation macro
*/
#define DES_FP(X,Y) \
{ \
X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \
T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \
Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \
T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
}
/*
* DES round macro
*/
#define DES_ROUND(X,Y) \
{ \
T = *SK++ ^ X; \
Y ^= SB8[ (T ) & 0x3F ] ^ \
SB6[ (T >> 8) & 0x3F ] ^ \
SB4[ (T >> 16) & 0x3F ] ^ \
SB2[ (T >> 24) & 0x3F ]; \
\
T = *SK++ ^ ((X << 28) | (X >> 4)); \
Y ^= SB7[ (T ) & 0x3F ] ^ \
SB5[ (T >> 8) & 0x3F ] ^ \
SB3[ (T >> 16) & 0x3F ] ^ \
SB1[ (T >> 24) & 0x3F ]; \
}
#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; }
void mbedtls_des_sw_init( mbedtls_des_sw_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_des_sw_context ) );
}
void mbedtls_des_sw_free( mbedtls_des_sw_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_zeroize( ctx, sizeof( mbedtls_des_sw_context ) );
}
void mbedtls_des3_sw_init( mbedtls_des3_sw_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_des3_sw_context ) );
}
void mbedtls_des3_sw_free( mbedtls_des3_sw_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_zeroize( ctx, sizeof( mbedtls_des3_sw_context ) );
}
static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
254 };
void mbedtls_des_sw_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] )
{
int i;
for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ )
key[i] = odd_parity_table[key[i] / 2];
}
/*
* Check the given key's parity, returns 1 on failure, 0 on SUCCESS
*/
int mbedtls_des_sw_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
{
int i;
for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ )
if( key[i] != odd_parity_table[key[i] / 2] )
return( 1 );
return( 0 );
}
/*
* Table of weak and semi-weak keys
*
* Source: http://en.wikipedia.org/wiki/Weak_key
*
* Weak:
* Alternating ones + zeros (0x0101010101010101)
* Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
* '0xE0E0E0E0F1F1F1F1'
* '0x1F1F1F1F0E0E0E0E'
*
* Semi-weak:
* 0x011F011F010E010E and 0x1F011F010E010E01
* 0x01E001E001F101F1 and 0xE001E001F101F101
* 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
* 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
* 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
* 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
*
*/
#define WEAK_KEY_COUNT 16
static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] =
{
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
{ 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
{ 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
{ 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
{ 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
{ 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
{ 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
{ 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
{ 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
{ 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
{ 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
{ 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
{ 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
{ 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
};
int mbedtls_des_sw_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
{
int i;
for( i = 0; i < WEAK_KEY_COUNT; i++ )
if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 )
return( 1 );
return( 0 );
}
void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
{
int i;
uint32_t X, Y, T;
GET_UINT32_BE( X, key, 0 );
GET_UINT32_BE( Y, key, 4 );
/*
* Permuted Choice 1
*/
T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4);
T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T );
X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2)
| (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] )
| (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
| (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2)
| (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] )
| (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
| (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
X &= 0x0FFFFFFF;
Y &= 0x0FFFFFFF;
/*
* calculate subkeys
*/
for( i = 0; i < 16; i++ )
{
if( i < 2 || i == 8 || i == 15 )
{
X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF;
Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF;
}
else
{
X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF;
Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF;
}
*SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000)
| ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
| ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000)
| ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000)
| ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000)
| ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000)
| ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400)
| ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100)
| ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010)
| ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004)
| ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
*SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
| ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
| ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000)
| ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
| ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000)
| ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000)
| ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000)
| ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400)
| ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100)
| ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011)
| ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002);
}
}
/*
* DES key schedule (56-bit, encryption)
*/
int mbedtls_des_sw_setkey_enc( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
{
mbedtls_des_setkey( ctx->sk, key );
return( 0 );
}
/*
* DES key schedule (56-bit, decryption)
*/
int mbedtls_des_sw_setkey_dec( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
{
int i;
mbedtls_des_setkey( ctx->sk, key );
for( i = 0; i < 16; i += 2 )
{
SWAP( ctx->sk[i ], ctx->sk[30 - i] );
SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
}
return( 0 );
}
static void des3_set2key( uint32_t esk[96],
uint32_t dsk[96],
const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] )
{
int i;
mbedtls_des_setkey( esk, key );
mbedtls_des_setkey( dsk + 32, key + 8 );
for( i = 0; i < 32; i += 2 )
{
dsk[i ] = esk[30 - i];
dsk[i + 1] = esk[31 - i];
esk[i + 32] = dsk[62 - i];
esk[i + 33] = dsk[63 - i];
esk[i + 64] = esk[i ];
esk[i + 65] = esk[i + 1];
dsk[i + 64] = dsk[i ];
dsk[i + 65] = dsk[i + 1];
}
}
/*
* Triple-DES key schedule (112-bit, encryption)
*/
int mbedtls_des3_sw_set2key_enc( mbedtls_des3_sw_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
{
uint32_t sk[96];
des3_set2key( ctx->sk, sk, key );
mbedtls_zeroize( sk, sizeof( sk ) );
return( 0 );
}
/*
* Triple-DES key schedule (112-bit, decryption)
*/
int mbedtls_des3_sw_set2key_dec( mbedtls_des3_sw_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
{
uint32_t sk[96];
des3_set2key( sk, ctx->sk, key );
mbedtls_zeroize( sk, sizeof( sk ) );
return( 0 );
}
static void des3_set3key( uint32_t esk[96],
uint32_t dsk[96],
const unsigned char key[24] )
{
int i;
mbedtls_des_setkey( esk, key );
mbedtls_des_setkey( dsk + 32, key + 8 );
mbedtls_des_setkey( esk + 64, key + 16 );
for( i = 0; i < 32; i += 2 )
{
dsk[i ] = esk[94 - i];
dsk[i + 1] = esk[95 - i];
esk[i + 32] = dsk[62 - i];
esk[i + 33] = dsk[63 - i];
dsk[i + 64] = esk[30 - i];
dsk[i + 65] = esk[31 - i];
}
}
/*
* Triple-DES key schedule (168-bit, encryption)
*/
int mbedtls_des3_sw_set3key_enc( mbedtls_des3_sw_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
{
uint32_t sk[96];
des3_set3key( ctx->sk, sk, key );
mbedtls_zeroize( sk, sizeof( sk ) );
return( 0 );
}
/*
* Triple-DES key schedule (168-bit, decryption)
*/
int mbedtls_des3_sw_set3key_dec( mbedtls_des3_sw_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
{
uint32_t sk[96];
des3_set3key( sk, ctx->sk, key );
mbedtls_zeroize( sk, sizeof( sk ) );
return( 0 );
}
/*
* DES-ECB block encryption/decryption
*/
int mbedtls_des_sw_crypt_ecb( mbedtls_des_sw_context *ctx,
const unsigned char input[8],
unsigned char output[8] )
{
int i;
uint32_t X, Y, T, *SK;
SK = ctx->sk;
GET_UINT32_BE( X, input, 0 );
GET_UINT32_BE( Y, input, 4 );
DES_IP( X, Y );
for( i = 0; i < 8; i++ )
{
DES_ROUND( Y, X );
DES_ROUND( X, Y );
}
DES_FP( Y, X );
PUT_UINT32_BE( Y, output, 0 );
PUT_UINT32_BE( X, output, 4 );
return( 0 );
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/*
* DES-CBC buffer encryption/decryption
*/
int mbedtls_des_sw_crypt_cbc( mbedtls_des_sw_context *ctx,
int mode,
size_t length,
unsigned char iv[8],
const unsigned char *input,
unsigned char *output )
{
int i;
unsigned char temp[8];
if( length % 8 )
return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH );
if( mode == MBEDTLS_DES_ENCRYPT )
{
while( length > 0 )
{
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( input[i] ^ iv[i] );
mbedtls_des_sw_crypt_ecb( ctx, output, output );
memcpy( iv, output, 8 );
input += 8;
output += 8;
length -= 8;
}
}
else /* MBEDTLS_DES_DECRYPT */
{
while( length > 0 )
{
memcpy( temp, input, 8 );
mbedtls_des_sw_crypt_ecb( ctx, input, output );
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( output[i] ^ iv[i] );
memcpy( iv, temp, 8 );
input += 8;
output += 8;
length -= 8;
}
}
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
/*
* 3DES-ECB block encryption/decryption
*/
int mbedtls_des3_sw_crypt_ecb( mbedtls_des3_sw_context *ctx,
const unsigned char input[8],
unsigned char output[8] )
{
int i;
uint32_t X, Y, T, *SK;
SK = ctx->sk;
GET_UINT32_BE( X, input, 0 );
GET_UINT32_BE( Y, input, 4 );
DES_IP( X, Y );
for( i = 0; i < 8; i++ )
{
DES_ROUND( Y, X );
DES_ROUND( X, Y );
}
for( i = 0; i < 8; i++ )
{
DES_ROUND( X, Y );
DES_ROUND( Y, X );
}
for( i = 0; i < 8; i++ )
{
DES_ROUND( Y, X );
DES_ROUND( X, Y );
}
DES_FP( Y, X );
PUT_UINT32_BE( Y, output, 0 );
PUT_UINT32_BE( X, output, 4 );
return( 0 );
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/*
* 3DES-CBC buffer encryption/decryption
*/
int mbedtls_des3_sw_crypt_cbc( mbedtls_des3_sw_context *ctx,
int mode,
size_t length,
unsigned char iv[8],
const unsigned char *input,
unsigned char *output )
{
int i;
unsigned char temp[8];
if( length % 8 )
return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH );
if( mode == MBEDTLS_DES_ENCRYPT )
{
while( length > 0 )
{
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( input[i] ^ iv[i] );
mbedtls_des3_sw_crypt_ecb( ctx, output, output );
memcpy( iv, output, 8 );
input += 8;
output += 8;
length -= 8;
}
}
else /* MBEDTLS_DES_DECRYPT */
{
while( length > 0 )
{
memcpy( temp, input, 8 );
mbedtls_des3_sw_crypt_ecb( ctx, input, output );
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( output[i] ^ iv[i] );
memcpy( iv, temp, 8 );
input += 8;
output += 8;
length -= 8;
}
}
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#endif /* MBEDTLS_DES_ALT */
#endif /* MBEDTLS_DES_C */

View File

@ -0,0 +1,283 @@
/**
* \file des.h
*
* \brief DES block cipher
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_DES_ALT_SW_H
#define MBEDTLS_DES_ALT_SW_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_DES_C)
#if defined(MBEDTLS_DES_ALT)
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief DES context structure
*/
typedef struct
{
uint32_t sk[32]; /*!< DES subkeys */
}
mbedtls_des_sw_context;
/**
* \brief Triple-DES context structure
*/
typedef struct
{
uint32_t sk[96]; /*!< 3DES subkeys */
}
mbedtls_des3_sw_context;
/**
* \brief Initialize DES context
*
* \param ctx DES context to be initialized
*/
void mbedtls_des_sw_init( mbedtls_des_sw_context *ctx );
/**
* \brief Clear DES context
*
* \param ctx DES context to be cleared
*/
void mbedtls_des_sw_free( mbedtls_des_sw_context *ctx );
/**
* \brief Initialize Triple-DES context
*
* \param ctx DES3 context to be initialized
*/
void mbedtls_des3_sw_init( mbedtls_des3_sw_context *ctx );
/**
* \brief Clear Triple-DES context
*
* \param ctx DES3 context to be cleared
*/
void mbedtls_des3_sw_free( mbedtls_des3_sw_context *ctx );
/**
* \brief Set key parity on the given key to odd.
*
* DES keys are 56 bits long, but each byte is padded with
* a parity bit to allow verification.
*
* \param key 8-byte secret key
*/
void mbedtls_des_sw_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/**
* \brief Check that key parity on the given key is odd.
*
* DES keys are 56 bits long, but each byte is padded with
* a parity bit to allow verification.
*
* \param key 8-byte secret key
*
* \return 0 is parity was ok, 1 if parity was not correct.
*/
int mbedtls_des_sw_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/**
* \brief Check that key is not a weak or semi-weak DES key
*
* \param key 8-byte secret key
*
* \return 0 if no weak key was found, 1 if a weak key was identified.
*/
int mbedtls_des_sw_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/**
* \brief DES key schedule (56-bit, encryption)
*
* \param ctx DES context to be initialized
* \param key 8-byte secret key
*
* \return 0
*/
int mbedtls_des_sw_setkey_enc( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/**
* \brief DES key schedule (56-bit, decryption)
*
* \param ctx DES context to be initialized
* \param key 8-byte secret key
*
* \return 0
*/
int mbedtls_des_sw_setkey_dec( mbedtls_des_sw_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/**
* \brief Triple-DES key schedule (112-bit, encryption)
*
* \param ctx 3DES context to be initialized
* \param key 16-byte secret key
*
* \return 0
*/
int mbedtls_des3_sw_set2key_enc( mbedtls_des3_sw_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
/**
* \brief Triple-DES key schedule (112-bit, decryption)
*
* \param ctx 3DES context to be initialized
* \param key 16-byte secret key
*
* \return 0
*/
int mbedtls_des3_sw_set2key_dec( mbedtls_des3_sw_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
/**
* \brief Triple-DES key schedule (168-bit, encryption)
*
* \param ctx 3DES context to be initialized
* \param key 24-byte secret key
*
* \return 0
*/
int mbedtls_des3_sw_set3key_enc( mbedtls_des3_sw_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
/**
* \brief Triple-DES key schedule (168-bit, decryption)
*
* \param ctx 3DES context to be initialized
* \param key 24-byte secret key
*
* \return 0
*/
int mbedtls_des3_sw_set3key_dec( mbedtls_des3_sw_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
/**
* \brief DES-ECB block encryption/decryption
*
* \param ctx DES context
* \param input 64-bit input block
* \param output 64-bit output block
*
* \return 0 if successful
*/
int mbedtls_des_sw_crypt_ecb( mbedtls_des_sw_context *ctx,
const unsigned char input[8],
unsigned char output[8] );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/**
* \brief DES-CBC buffer encryption/decryption
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx DES context
* \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*/
int mbedtls_des_sw_crypt_cbc( mbedtls_des_sw_context *ctx,
int mode,
size_t length,
unsigned char iv[8],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */
/**
* \brief 3DES-ECB block encryption/decryption
*
* \param ctx 3DES context
* \param input 64-bit input block
* \param output 64-bit output block
*
* \return 0 if successful
*/
int mbedtls_des3_sw_crypt_ecb( mbedtls_des3_sw_context *ctx,
const unsigned char input[8],
unsigned char output[8] );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/**
* \brief 3DES-CBC buffer encryption/decryption
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx 3DES context
* \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
*/
int mbedtls_des3_sw_crypt_cbc( mbedtls_des3_sw_context *ctx,
int mode,
size_t length,
unsigned char iv[8],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */
/**
* \brief Internal function for key expansion.
* (Only exposed to allow overriding it,
* see MBEDTLS_DES_SETKEY_ALT)
*
* \param SK Round keys
* \param key Base key
*/
void mbedtls_des_sw_setkey( uint32_t SK[32],
const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_DES_ALT */
#endif /* MBEDTLS_DES_C */
#endif /* des.h */

View File

@ -0,0 +1,138 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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.
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA1_C)
#if defined(MBEDTLS_SHA1_ALT)
#include "sha1_alt.h"
#include "crypto-misc.h"
#include "nu_bitutil.h"
#include "string.h"
void mbedtls_sha1_init(mbedtls_sha1_context *ctx)
{
if (crypto_sha_acquire()) {
ctx->ishw = 1;
mbedtls_sha1_hw_init(&ctx->hw_ctx);
}
else {
ctx->ishw = 0;
mbedtls_sha1_sw_init(&ctx->sw_ctx);
}
}
void mbedtls_sha1_free(mbedtls_sha1_context *ctx)
{
if (ctx == NULL) {
return;
}
if (ctx->ishw) {
mbedtls_sha1_hw_free(&ctx->hw_ctx);
crypto_sha_release();
}
else {
mbedtls_sha1_sw_free(&ctx->sw_ctx);
}
}
void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src)
{
if (src->ishw) {
// Clone S/W ctx from H/W ctx
dst->ishw = 0;
dst->sw_ctx.total[0] = src->hw_ctx.total;
dst->sw_ctx.total[1] = 0;
{
unsigned char output[20];
crypto_sha_getinternstate(output, sizeof (output));
unsigned char *output_pos = output;
unsigned char *output_end = output + (sizeof (output) / sizeof (output[0]));
uint32_t *state_pos = (uint32_t *) &(dst->sw_ctx.state[0]);
while (output_pos != output_end) {
*state_pos ++ = nu_get32_be(output_pos);
output_pos += 4;
}
}
memcpy(dst->sw_ctx.buffer, src->hw_ctx.buffer, src->hw_ctx.buffer_left);
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
mbedtls_sha1_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
}
}
else {
// Clone S/W ctx from S/W ctx
dst->sw_ctx = src->sw_ctx;
}
}
/*
* SHA-1 context setup
*/
void mbedtls_sha1_starts(mbedtls_sha1_context *ctx)
{
if (ctx->ishw) {
mbedtls_sha1_hw_starts(&ctx->hw_ctx);
}
else {
mbedtls_sha1_sw_starts(&ctx->sw_ctx);
}
}
/*
* SHA-1 process buffer
*/
void mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen)
{
if (ctx->ishw) {
mbedtls_sha1_hw_update(&ctx->hw_ctx, input, ilen);
}
else {
mbedtls_sha1_sw_update(&ctx->sw_ctx, input, ilen);
}
}
/*
* SHA-1 final digest
*/
void mbedtls_sha1_finish(mbedtls_sha1_context *ctx, unsigned char output[20])
{
if (ctx->ishw) {
mbedtls_sha1_hw_finish(&ctx->hw_ctx, output);
}
else {
mbedtls_sha1_sw_finish(&ctx->sw_ctx, output);
}
}
void mbedtls_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64])
{
if (ctx->ishw) {
mbedtls_sha1_hw_process(&ctx->hw_ctx, data);
}
else {
mbedtls_sha1_sw_process(&ctx->sw_ctx, data);
}
}
#endif /* MBEDTLS_SHA1_ALT */
#endif /* MBEDTLS_SHA1_C */

View File

@ -0,0 +1,105 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBEDTLS_SHA1_ALT_H
#define MBEDTLS_SHA1_ALT_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA1_C)
#if defined(MBEDTLS_SHA1_ALT)
#include "sha_alt_hw.h"
#include "sha1_alt_sw.h"
#ifdef __cplusplus
extern "C" {
#endif
struct mbedtls_sha1_context_s;
/**
* \brief SHA-1 context structure
*/
typedef struct mbedtls_sha1_context_s
{
int ishw;
crypto_sha_context hw_ctx;
mbedtls_sha1_sw_context sw_ctx;
}
mbedtls_sha1_context;
/**
* \brief Initialize SHA-1 context
*
* \param ctx SHA-1 context to be initialized
*/
void mbedtls_sha1_init( mbedtls_sha1_context *ctx );
/**
* \brief Clear SHA-1 context
*
* \param ctx SHA-1 context to be cleared
*/
void mbedtls_sha1_free( mbedtls_sha1_context *ctx );
/**
* \brief Clone (the state of) a SHA-1 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src );
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] );
/* Internal use */
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] );
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_SHA1_ALT */
#endif /* MBEDTLS_SHA1_C */
#endif /* sha1_alt.h */

View File

@ -0,0 +1,344 @@
/*
* FIPS-180-1 compliant SHA-1 implementation
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA1_C)
#if defined(MBEDTLS_SHA1_ALT)
#include "mbedtls/sha1.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
void mbedtls_sha1_sw_init( mbedtls_sha1_sw_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha1_sw_context ) );
}
void mbedtls_sha1_sw_free( mbedtls_sha1_sw_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_sw_context ) );
}
void mbedtls_sha1_sw_clone( mbedtls_sha1_sw_context *dst,
const mbedtls_sha1_sw_context *src )
{
*dst = *src;
}
/*
* SHA-1 context setup
*/
void mbedtls_sha1_sw_starts( mbedtls_sha1_sw_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
void mbedtls_sha1_sw_process( mbedtls_sha1_sw_context *ctx, const unsigned char data[64] )
{
uint32_t temp, W[16], A, B, C, D, E;
GET_UINT32_BE( W[ 0], data, 0 );
GET_UINT32_BE( W[ 1], data, 4 );
GET_UINT32_BE( W[ 2], data, 8 );
GET_UINT32_BE( W[ 3], data, 12 );
GET_UINT32_BE( W[ 4], data, 16 );
GET_UINT32_BE( W[ 5], data, 20 );
GET_UINT32_BE( W[ 6], data, 24 );
GET_UINT32_BE( W[ 7], data, 28 );
GET_UINT32_BE( W[ 8], data, 32 );
GET_UINT32_BE( W[ 9], data, 36 );
GET_UINT32_BE( W[10], data, 40 );
GET_UINT32_BE( W[11], data, 44 );
GET_UINT32_BE( W[12], data, 48 );
GET_UINT32_BE( W[13], data, 52 );
GET_UINT32_BE( W[14], data, 56 );
GET_UINT32_BE( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/*
* SHA-1 process buffer
*/
void mbedtls_sha1_sw_update( mbedtls_sha1_sw_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen == 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha1_sw_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
mbedtls_sha1_sw_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha1_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-1 final digest
*/
void mbedtls_sha1_sw_finish( mbedtls_sha1_sw_context *ctx, unsigned char output[20] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_sha1_sw_update( ctx, sha1_padding, padn );
mbedtls_sha1_sw_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
}
#endif /* MBEDTLS_SHA1_ALT */
#endif /* MBEDTLS_SHA1_C */

View File

@ -0,0 +1,110 @@
/**
* \file sha1.h
*
* \brief SHA-1 cryptographic hash function
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_SHA1_ALT_SW_H
#define MBEDTLS_SHA1_ALT_SW_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA1_C)
#if defined(MBEDTLS_SHA1_ALT)
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-1 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
}
mbedtls_sha1_sw_context;
/**
* \brief Initialize SHA-1 context
*
* \param ctx SHA-1 context to be initialized
*/
void mbedtls_sha1_sw_init( mbedtls_sha1_sw_context *ctx );
/**
* \brief Clear SHA-1 context
*
* \param ctx SHA-1 context to be cleared
*/
void mbedtls_sha1_sw_free( mbedtls_sha1_sw_context *ctx );
/**
* \brief Clone (the state of) a SHA-1 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha1_sw_clone( mbedtls_sha1_sw_context *dst,
const mbedtls_sha1_sw_context *src );
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void mbedtls_sha1_sw_starts( mbedtls_sha1_sw_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha1_sw_update( mbedtls_sha1_sw_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void mbedtls_sha1_sw_finish( mbedtls_sha1_sw_context *ctx, unsigned char output[20] );
/* Internal use */
void mbedtls_sha1_sw_process( mbedtls_sha1_sw_context *ctx, const unsigned char data[64] );
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_SHA1_ALT */
#endif /* MBEDTLS_SHA1_C */
#endif /* sha1_alt_sw.h */

View File

@ -0,0 +1,139 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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.
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA256_C)
#if defined(MBEDTLS_SHA256_ALT)
#include "sha256_alt.h"
#include "crypto-misc.h"
#include "nu_bitutil.h"
#include "string.h"
void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
{
if (crypto_sha_acquire()) {
ctx->ishw = 1;
mbedtls_sha256_hw_init(&ctx->hw_ctx);
}
else {
ctx->ishw = 0;
mbedtls_sha256_sw_init(&ctx->sw_ctx);
}
}
void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
{
if (ctx == NULL) {
return;
}
if (ctx->ishw) {
mbedtls_sha256_hw_free(&ctx->hw_ctx);
crypto_sha_release();
}
else {
mbedtls_sha256_sw_free(&ctx->sw_ctx);
}
}
void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src)
{
if (src->ishw) {
// Clone S/W ctx from H/W ctx
dst->ishw = 0;
dst->sw_ctx.total[0] = src->hw_ctx.total;
dst->sw_ctx.total[1] = 0;
{
unsigned char output[32];
crypto_sha_getinternstate(output, sizeof (output));
unsigned char *output_pos = output;
unsigned char *output_end = output + (sizeof (output) / sizeof (output[0]));
uint32_t *state_pos = (uint32_t *) &(dst->sw_ctx.state[0]);
while (output_pos != output_end) {
*state_pos ++ = nu_get32_be(output_pos);
output_pos += 4;
}
}
memcpy(dst->sw_ctx.buffer, src->hw_ctx.buffer, src->hw_ctx.buffer_left);
dst->sw_ctx.is224 = src->hw_ctx.is224_384;
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
mbedtls_sha256_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
}
}
else {
// Clone S/W ctx from S/W ctx
dst->sw_ctx = src->sw_ctx;
}
}
/*
* SHA-256 context setup
*/
void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
{
if (ctx->ishw) {
mbedtls_sha256_hw_starts(&ctx->hw_ctx, is224);
}
else {
mbedtls_sha256_sw_starts(&ctx->sw_ctx, is224);
}
}
/*
* SHA-256 process buffer
*/
void mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen)
{
if (ctx->ishw) {
mbedtls_sha256_hw_update(&ctx->hw_ctx, input, ilen);
}
else {
mbedtls_sha256_sw_update(&ctx->sw_ctx, input, ilen);
}
}
/*
* SHA-256 final digest
*/
void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, unsigned char output[32])
{
if (ctx->ishw) {
mbedtls_sha256_hw_finish(&ctx->hw_ctx, output);
}
else {
mbedtls_sha256_sw_finish(&ctx->sw_ctx, output);
}
}
void mbedtls_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64])
{
if (ctx->ishw) {
mbedtls_sha256_hw_process(&ctx->hw_ctx, data);
}
else {
mbedtls_sha256_sw_process(&ctx->sw_ctx, data);
}
}
#endif /* MBEDTLS_SHA256_ALT */
#endif /* MBEDTLS_SHA256_C */

View File

@ -0,0 +1,107 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBEDTLS_SHA256_ALT_H
#define MBEDTLS_SHA256_ALT_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA256_C)
#if defined(MBEDTLS_SHA256_ALT)
#include "sha_alt_hw.h"
#include "sha256_alt_sw.h"
#ifdef __cplusplus
extern "C" {
#endif
struct mbedtls_sha256_context_s;
/**
* \brief SHA-256 context structure
*/
typedef struct mbedtls_sha256_context_s
{
int ishw;
crypto_sha_context hw_ctx;
mbedtls_sha256_sw_context sw_ctx;
}
mbedtls_sha256_context;
/**
* \brief Initialize SHA-256 context
*
* \param ctx SHA-256 context to be initialized
*/
void mbedtls_sha256_init( mbedtls_sha256_context *ctx );
/**
* \brief Clear SHA-256 context
*
* \param ctx SHA-256 context to be cleared
*/
void mbedtls_sha256_free( mbedtls_sha256_context *ctx );
/**
* \brief Clone (the state of) a SHA-256 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src );
/**
* \brief SHA-256 context setup
*
* \param ctx context to be initialized
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 );
/**
* \brief SHA-256 process buffer
*
* \param ctx SHA-256 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-256 final digest
*
* \param ctx SHA-256 context
* \param output SHA-224/256 checksum result
*/
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] );
/* Internal use */
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] );
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_SHA256_ALT */
#endif /* MBEDTLS_SHA256_C */
#endif /* sha256_alt.h */

View File

@ -0,0 +1,318 @@
/*
* FIPS-180-2 compliant SHA-256 implementation
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA256_C)
#if defined(MBEDTLS_SHA256_ALT)
#include "mbedtls/sha256.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf printf
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
do { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
} while( 0 )
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
} while( 0 )
#endif
void mbedtls_sha256_sw_init( mbedtls_sha256_sw_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha256_sw_context ) );
}
void mbedtls_sha256_sw_free( mbedtls_sha256_sw_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_sw_context ) );
}
void mbedtls_sha256_sw_clone( mbedtls_sha256_sw_context *dst,
const mbedtls_sha256_sw_context *src )
{
*dst = *src;
}
/*
* SHA-256 context setup
*/
void mbedtls_sha256_sw_starts( mbedtls_sha256_sw_context *ctx, int is224 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is224 == 0 )
{
/* SHA-256 */
ctx->state[0] = 0x6A09E667;
ctx->state[1] = 0xBB67AE85;
ctx->state[2] = 0x3C6EF372;
ctx->state[3] = 0xA54FF53A;
ctx->state[4] = 0x510E527F;
ctx->state[5] = 0x9B05688C;
ctx->state[6] = 0x1F83D9AB;
ctx->state[7] = 0x5BE0CD19;
}
else
{
/* SHA-224 */
ctx->state[0] = 0xC1059ED8;
ctx->state[1] = 0x367CD507;
ctx->state[2] = 0x3070DD17;
ctx->state[3] = 0xF70E5939;
ctx->state[4] = 0xFFC00B31;
ctx->state[5] = 0x68581511;
ctx->state[6] = 0x64F98FA7;
ctx->state[7] = 0xBEFA4FA4;
}
ctx->is224 = is224;
}
static const uint32_t K[] =
{
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
};
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned char data[64] )
{
uint32_t temp1, temp2, W[64];
uint32_t A[8];
unsigned int i;
for( i = 0; i < 8; i++ )
A[i] = ctx->state[i];
#if defined(MBEDTLS_SHA256_SMALLER)
for( i = 0; i < 64; i++ )
{
if( i < 16 )
GET_UINT32_BE( W[i], data, 4 * i );
else
R( i );
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
}
#else /* MBEDTLS_SHA256_SMALLER */
for( i = 0; i < 16; i++ )
GET_UINT32_BE( W[i], data, 4 * i );
for( i = 0; i < 16; i += 8 )
{
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );
}
for( i = 16; i < 64; i += 8 )
{
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] );
}
#endif /* MBEDTLS_SHA256_SMALLER */
for( i = 0; i < 8; i++ )
ctx->state[i] += A[i];
}
/*
* SHA-256 process buffer
*/
void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned char *input,
size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen == 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha256_sw_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
mbedtls_sha256_sw_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha256_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-256 final digest
*/
void mbedtls_sha256_sw_finish( mbedtls_sha256_sw_context *ctx, unsigned char output[32] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_sha256_sw_update( ctx, sha256_padding, padn );
mbedtls_sha256_sw_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
PUT_UINT32_BE( ctx->state[5], output, 20 );
PUT_UINT32_BE( ctx->state[6], output, 24 );
if( ctx->is224 == 0 )
PUT_UINT32_BE( ctx->state[7], output, 28 );
}
#endif /* MBEDTLS_SHA256_ALT */
#endif /* MBEDTLS_SHA256_C */

View File

@ -0,0 +1,113 @@
/**
* \file sha256.h
*
* \brief SHA-224 and SHA-256 cryptographic hash function
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_SHA256_ALT_SW_H
#define MBEDTLS_SHA256_ALT_SW_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA256_C)
#if defined(MBEDTLS_SHA256_ALT)
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-256 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[8]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
int is224; /*!< 0 => SHA-256, else SHA-224 */
}
mbedtls_sha256_sw_context;
/**
* \brief Initialize SHA-256 context
*
* \param ctx SHA-256 context to be initialized
*/
void mbedtls_sha256_sw_init( mbedtls_sha256_sw_context *ctx );
/**
* \brief Clear SHA-256 context
*
* \param ctx SHA-256 context to be cleared
*/
void mbedtls_sha256_sw_free( mbedtls_sha256_sw_context *ctx );
/**
* \brief Clone (the state of) a SHA-256 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha256_sw_clone( mbedtls_sha256_sw_context *dst,
const mbedtls_sha256_sw_context *src );
/**
* \brief SHA-256 context setup
*
* \param ctx context to be initialized
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void mbedtls_sha256_sw_starts( mbedtls_sha256_sw_context *ctx, int is224 );
/**
* \brief SHA-256 process buffer
*
* \param ctx SHA-256 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha256_sw_update( mbedtls_sha256_sw_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-256 final digest
*
* \param ctx SHA-256 context
* \param output SHA-224/256 checksum result
*/
void mbedtls_sha256_sw_finish( mbedtls_sha256_sw_context *ctx, unsigned char output[32] );
/* Internal use */
void mbedtls_sha256_sw_process( mbedtls_sha256_sw_context *ctx, const unsigned char data[64] );
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_SHA256_ALT */
#endif /* MBEDTLS_SHA256_C */
#endif /* sha256_alt_sw.h */

View File

@ -0,0 +1,140 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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.
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_SHA512_ALT)
#include "sha512_alt.h"
#include "crypto-misc.h"
#include "nu_bitutil.h"
#include "string.h"
void mbedtls_sha512_init(mbedtls_sha512_context *ctx)
{
if (crypto_sha_acquire()) {
ctx->ishw = 1;
mbedtls_sha512_hw_init(&ctx->hw_ctx);
}
else {
ctx->ishw = 0;
mbedtls_sha512_sw_init(&ctx->sw_ctx);
}
}
void mbedtls_sha512_free(mbedtls_sha512_context *ctx)
{
if (ctx == NULL) {
return;
}
if (ctx->ishw) {
mbedtls_sha512_hw_free(&ctx->hw_ctx);
crypto_sha_release();
}
else {
mbedtls_sha512_sw_free(&ctx->sw_ctx);
}
}
void mbedtls_sha512_clone(mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src)
{
if (src->ishw) {
// Clone S/W ctx from H/W ctx
dst->ishw = 0;
dst->sw_ctx.total[0] = src->hw_ctx.total;
dst->sw_ctx.total[1] = 0;
{
unsigned char output[128];
crypto_sha_getinternstate(output, sizeof (output));
unsigned char *output_pos = output;
unsigned char *output_end = output + (sizeof (output) / sizeof (output[0]));
uint32_t *state_pos = (uint32_t *) &(dst->sw_ctx.state[0]);
while (output_pos != output_end) {
*state_pos ++ = nu_get32_be(output_pos + 4);
*state_pos ++ = nu_get32_be(output_pos);
output_pos += 8;
}
}
memcpy(dst->sw_ctx.buffer, src->hw_ctx.buffer, src->hw_ctx.buffer_left);
dst->sw_ctx.is384 = src->hw_ctx.is224_384;
if (src->hw_ctx.buffer_left == src->hw_ctx.blocksize) {
mbedtls_sha512_sw_process(&dst->sw_ctx, dst->sw_ctx.buffer);
}
}
else {
// Clone S/W ctx from S/W ctx
dst->sw_ctx = src->sw_ctx;
}
}
/*
* SHA-512 context setup
*/
void mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384)
{
if (ctx->ishw) {
mbedtls_sha512_hw_starts(&ctx->hw_ctx, is384);
}
else {
mbedtls_sha512_sw_starts(&ctx->sw_ctx, is384);
}
}
/*
* SHA-512 process buffer
*/
void mbedtls_sha512_update(mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen)
{
if (ctx->ishw) {
mbedtls_sha512_hw_update(&ctx->hw_ctx, input, ilen);
}
else {
mbedtls_sha512_sw_update(&ctx->sw_ctx, input, ilen);
}
}
/*
* SHA-512 final digest
*/
void mbedtls_sha512_finish(mbedtls_sha512_context *ctx, unsigned char output[64])
{
if (ctx->ishw) {
mbedtls_sha512_hw_finish(&ctx->hw_ctx, output);
}
else {
mbedtls_sha512_sw_finish(&ctx->sw_ctx, output);
}
}
void mbedtls_sha512_process(mbedtls_sha512_context *ctx, const unsigned char data[128])
{
if (ctx->ishw) {
mbedtls_sha512_hw_process(&ctx->hw_ctx, data);
}
else {
mbedtls_sha512_sw_process(&ctx->sw_ctx, data);
}
}
#endif /* MBEDTLS_SHA512_ALT */
#endif /* MBEDTLS_SHA512_C */

View File

@ -0,0 +1,107 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBEDTLS_SHA512_ALT_H
#define MBEDTLS_SHA512_ALT_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_SHA512_ALT)
#include "sha_alt_hw.h"
#include "sha512_alt_sw.h"
#ifdef __cplusplus
extern "C" {
#endif
struct mbedtls_sha512_context_s;
/**
* \brief SHA-512 context structure
*/
typedef struct mbedtls_sha512_context_s
{
int ishw;
crypto_sha_context hw_ctx;
mbedtls_sha512_sw_context sw_ctx;
}
mbedtls_sha512_context;
/**
* \brief Initialize SHA-512 context
*
* \param ctx SHA-512 context to be initialized
*/
void mbedtls_sha512_init( mbedtls_sha512_context *ctx );
/**
* \brief Clear SHA-512 context
*
* \param ctx SHA-512 context to be cleared
*/
void mbedtls_sha512_free( mbedtls_sha512_context *ctx );
/**
* \brief Clone (the state of) a SHA-512 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src );
/**
* \brief SHA-512 context setup
*
* \param ctx context to be initialized
* \param is384 0 = use SHA512, 1 = use SHA384
*/
void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 );
/**
* \brief SHA-512 process buffer
*
* \param ctx SHA-512 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-512 final digest
*
* \param ctx SHA-512 context
* \param output SHA-384/512 checksum result
*/
void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] );
/* Internal use */
void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] );
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_SHA512_ALT */
#endif /* MBEDTLS_SHA512_C */
#endif /* sha512_alt.h */

View File

@ -0,0 +1,357 @@
/*
* FIPS-180-2 compliant SHA-384/512 implementation
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* The SHA-512 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_SHA512_ALT)
#include "mbedtls/sha512.h"
#if defined(_MSC_VER) || defined(__WATCOMC__)
#define UL64(x) x##ui64
#else
#define UL64(x) x##ULL
#endif
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf printf
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
/*
* 64-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT64_BE
#define GET_UINT64_BE(n,b,i) \
{ \
(n) = ( (uint64_t) (b)[(i) ] << 56 ) \
| ( (uint64_t) (b)[(i) + 1] << 48 ) \
| ( (uint64_t) (b)[(i) + 2] << 40 ) \
| ( (uint64_t) (b)[(i) + 3] << 32 ) \
| ( (uint64_t) (b)[(i) + 4] << 24 ) \
| ( (uint64_t) (b)[(i) + 5] << 16 ) \
| ( (uint64_t) (b)[(i) + 6] << 8 ) \
| ( (uint64_t) (b)[(i) + 7] ); \
}
#endif /* GET_UINT64_BE */
#ifndef PUT_UINT64_BE
#define PUT_UINT64_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 7] = (unsigned char) ( (n) ); \
}
#endif /* PUT_UINT64_BE */
void mbedtls_sha512_sw_init( mbedtls_sha512_sw_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha512_sw_context ) );
}
void mbedtls_sha512_sw_free( mbedtls_sha512_sw_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_sw_context ) );
}
void mbedtls_sha512_sw_clone( mbedtls_sha512_sw_context *dst,
const mbedtls_sha512_sw_context *src )
{
*dst = *src;
}
/*
* SHA-512 context setup
*/
void mbedtls_sha512_sw_starts( mbedtls_sha512_sw_context *ctx, int is384 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is384 == 0 )
{
/* SHA-512 */
ctx->state[0] = UL64(0x6A09E667F3BCC908);
ctx->state[1] = UL64(0xBB67AE8584CAA73B);
ctx->state[2] = UL64(0x3C6EF372FE94F82B);
ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
ctx->state[4] = UL64(0x510E527FADE682D1);
ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
ctx->state[7] = UL64(0x5BE0CD19137E2179);
}
else
{
/* SHA-384 */
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
ctx->state[1] = UL64(0x629A292A367CD507);
ctx->state[2] = UL64(0x9159015A3070DD17);
ctx->state[3] = UL64(0x152FECD8F70E5939);
ctx->state[4] = UL64(0x67332667FFC00B31);
ctx->state[5] = UL64(0x8EB44A8768581511);
ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
}
ctx->is384 = is384;
}
#if !defined(MBEDTLS_SHA512_PROCESS_ALT)
/*
* Round constants
*/
static const uint64_t K[80] =
{
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
};
void mbedtls_sha512_sw_process( mbedtls_sha512_sw_context *ctx, const unsigned char data[128] )
{
int i;
uint64_t temp1, temp2, W[80];
uint64_t A, B, C, D, E, F, G, H;
#define SHR(x,n) (x >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
for( i = 0; i < 16; i++ )
{
GET_UINT64_BE( W[i], data, i << 3 );
}
for( ; i < 80; i++ )
{
W[i] = S1(W[i - 2]) + W[i - 7] +
S0(W[i - 15]) + W[i - 16];
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
i = 0;
do
{
P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
}
while( i < 80 );
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
#endif /* !MBEDTLS_SHA512_PROCESS_ALT */
/*
* SHA-512 process buffer
*/
void mbedtls_sha512_sw_update( mbedtls_sha512_sw_context *ctx, const unsigned char *input,
size_t ilen )
{
size_t fill;
unsigned int left;
if( ilen == 0 )
return;
left = (unsigned int) (ctx->total[0] & 0x7F);
fill = 128 - left;
ctx->total[0] += (uint64_t) ilen;
if( ctx->total[0] < (uint64_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha512_sw_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 128 )
{
mbedtls_sha512_sw_process( ctx, input );
input += 128;
ilen -= 128;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha512_padding[128] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-512 final digest
*/
void mbedtls_sha512_sw_finish( mbedtls_sha512_sw_context *ctx, unsigned char output[64] )
{
size_t last, padn;
uint64_t high, low;
unsigned char msglen[16];
high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT64_BE( high, msglen, 0 );
PUT_UINT64_BE( low, msglen, 8 );
last = (size_t)( ctx->total[0] & 0x7F );
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
mbedtls_sha512_sw_update( ctx, sha512_padding, padn );
mbedtls_sha512_sw_update( ctx, msglen, 16 );
PUT_UINT64_BE( ctx->state[0], output, 0 );
PUT_UINT64_BE( ctx->state[1], output, 8 );
PUT_UINT64_BE( ctx->state[2], output, 16 );
PUT_UINT64_BE( ctx->state[3], output, 24 );
PUT_UINT64_BE( ctx->state[4], output, 32 );
PUT_UINT64_BE( ctx->state[5], output, 40 );
if( ctx->is384 == 0 )
{
PUT_UINT64_BE( ctx->state[6], output, 48 );
PUT_UINT64_BE( ctx->state[7], output, 56 );
}
}
#endif /* MBEDTLS_SHA512_ALT */
#endif /* MBEDTLS_SHA512_C */

View File

@ -0,0 +1,113 @@
/**
* \file sha512.h
*
* \brief SHA-384 and SHA-512 cryptographic hash function
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_SHA512_ALT_SW_H
#define MBEDTLS_SHA512_ALT_SW_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_SHA512_ALT)
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-512 context structure
*/
typedef struct
{
uint64_t total[2]; /*!< number of bytes processed */
uint64_t state[8]; /*!< intermediate digest state */
unsigned char buffer[128]; /*!< data block being processed */
int is384; /*!< 0 => SHA-512, else SHA-384 */
}
mbedtls_sha512_sw_context;
/**
* \brief Initialize SHA-512 context
*
* \param ctx SHA-512 context to be initialized
*/
void mbedtls_sha512_sw_init( mbedtls_sha512_sw_context *ctx );
/**
* \brief Clear SHA-512 context
*
* \param ctx SHA-512 context to be cleared
*/
void mbedtls_sha512_sw_free( mbedtls_sha512_sw_context *ctx );
/**
* \brief Clone (the state of) a SHA-512 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha512_sw_clone( mbedtls_sha512_sw_context *dst,
const mbedtls_sha512_sw_context *src );
/**
* \brief SHA-512 context setup
*
* \param ctx context to be initialized
* \param is384 0 = use SHA512, 1 = use SHA384
*/
void mbedtls_sha512_sw_starts( mbedtls_sha512_sw_context *ctx, int is384 );
/**
* \brief SHA-512 process buffer
*
* \param ctx SHA-512 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha512_sw_update( mbedtls_sha512_sw_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-512 final digest
*
* \param ctx SHA-512 context
* \param output SHA-384/512 checksum result
*/
void mbedtls_sha512_sw_finish( mbedtls_sha512_sw_context *ctx, unsigned char output[64] );
/* Internal use */
void mbedtls_sha512_sw_process( mbedtls_sha512_sw_context *ctx, const unsigned char data[128] );
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_SHA512_ALT */
#endif /* MBEDTLS_SHA512_C */
#endif /* sha512_alt_sw.h */

View File

@ -0,0 +1,439 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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.
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
#if defined(MBEDTLS_SHA1_ALT)
#include "sha1_alt.h"
#endif /* MBEDTLS_SHA1_ALT */
#if defined(MBEDTLS_SHA256_ALT)
#include "sha256_alt.h"
#endif /* MBEDTLS_SHA256_ALT */
#if defined(MBEDTLS_SHA512_ALT)
#include "sha512_alt.h"
#endif /* MBEDTLS_SHA512_ALT */
#include "nu_bitutil.h"
#include "mbed_assert.h"
#include "crypto-misc.h"
#include <string.h>
void crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size_t ilen);
void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input, size_t ilen, int islast);
void crypto_sha_getinternstate(unsigned char output[], size_t olen);
#endif /* MBEDTLS_SHA1_ALT || MBEDTLS_SHA256_ALT || MBEDTLS_SHA512_ALT */
#if defined(MBEDTLS_SHA1_C)
#if defined(MBEDTLS_SHA1_ALT)
void mbedtls_sha1_hw_init(crypto_sha_context *ctx)
{
crypto_init();
memset(ctx, 0, sizeof(crypto_sha_context));
}
void mbedtls_sha1_hw_free(crypto_sha_context *ctx)
{
if (ctx == NULL) {
return;
}
crypto_zeroize(ctx, sizeof(crypto_sha_context));
}
void mbedtls_sha1_hw_clone(crypto_sha_context *dst,
const crypto_sha_context *src)
{
*dst = *src;
}
void mbedtls_sha1_hw_starts(crypto_sha_context *ctx)
{
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
ctx->total = 0;
ctx->buffer_left = 0;
ctx->blocksize = 64;
ctx->blocksize_mask = 0x3F;
SHA_Open(SHA_MODE_SHA1, SHA_NO_SWAP, 0);
// Ensure we have correct initial internal states in SHA_DGST registers even though SHA H/W is not actually started.
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
return;
}
void mbedtls_sha1_hw_update(crypto_sha_context *ctx, const unsigned char *input, size_t ilen)
{
crypto_sha_update(ctx, input, ilen);
}
void mbedtls_sha1_hw_finish(crypto_sha_context *ctx, unsigned char output[20])
{
// H/W SHA cannot handle zero data well. Fall back to S/W SHA.
if (ctx->total) {
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
ctx->buffer_left = 0;
crypto_sha_getinternstate(output, 20);
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
}
else {
mbedtls_sha1_sw_context ctx_sw;
mbedtls_sha1_sw_init(&ctx_sw);
mbedtls_sha1_sw_starts(&ctx_sw);
mbedtls_sha1_sw_finish(&ctx_sw, output);
mbedtls_sha1_sw_free(&ctx_sw);
}
}
void mbedtls_sha1_hw_process(crypto_sha_context *ctx, const unsigned char data[64])
{
mbedtls_sha1_hw_update(ctx, data, 64);
}
#endif /* MBEDTLS_SHA1_ALT */
#endif /* MBEDTLS_SHA1_C */
#if defined(MBEDTLS_SHA256_C)
#if defined(MBEDTLS_SHA256_ALT)
void mbedtls_sha256_hw_init(crypto_sha_context *ctx)
{
crypto_init();
memset(ctx, 0, sizeof(crypto_sha_context));
}
void mbedtls_sha256_hw_free(crypto_sha_context *ctx)
{
if (ctx == NULL) {
return;
}
crypto_zeroize(ctx, sizeof(crypto_sha_context));
}
void mbedtls_sha256_hw_clone(crypto_sha_context *dst,
const crypto_sha_context *src)
{
*dst = *src;
}
void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224)
{
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
ctx->total = 0;
ctx->buffer_left = 0;
ctx->blocksize = 64;
ctx->blocksize_mask = 0x3F;
ctx->is224_384 = is224;
SHA_Open(is224 ? SHA_MODE_SHA224 : SHA_MODE_SHA256, SHA_NO_SWAP, 0);
// Ensure we have correct initial inernal states in SHA_DGST registers even though SHA H/W is not actually started.
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
return;
}
void mbedtls_sha256_hw_update(crypto_sha_context *ctx, const unsigned char *input, size_t ilen)
{
crypto_sha_update(ctx, input, ilen);
}
void mbedtls_sha256_hw_finish(crypto_sha_context *ctx, unsigned char output[32])
{
// H/W SHA cannot handle zero data well. Fall back to S/W SHA.
if (ctx->total) {
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
ctx->buffer_left = 0;
crypto_sha_getinternstate(output, ctx->is224_384 ? 28 : 32);
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
}
else {
mbedtls_sha256_sw_context ctx_sw;
mbedtls_sha256_sw_init(&ctx_sw);
mbedtls_sha256_sw_starts(&ctx_sw, ctx->is224_384);
mbedtls_sha256_sw_finish(&ctx_sw, output);
mbedtls_sha256_sw_free(&ctx_sw);
}
}
void mbedtls_sha256_hw_process(crypto_sha_context *ctx, const unsigned char data[64])
{
mbedtls_sha256_hw_update(ctx, data, 64);
}
#endif /* MBEDTLS_SHA256_ALT */
#endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_SHA512_ALT)
void mbedtls_sha512_hw_init(crypto_sha_context *ctx)
{
crypto_init();
memset(ctx, 0, sizeof(crypto_sha_context));
}
void mbedtls_sha512_hw_free(crypto_sha_context *ctx)
{
if (ctx == NULL) {
return;
}
crypto_zeroize(ctx, sizeof(crypto_sha_context));
}
void mbedtls_sha512_hw_clone(crypto_sha_context *dst,
const crypto_sha_context *src)
{
*dst = *src;
}
void mbedtls_sha512_hw_starts( crypto_sha_context *ctx, int is384)
{
// NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it.
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
ctx->total = 0;
ctx->buffer_left = 0;
ctx->blocksize = 128;
ctx->blocksize_mask = 0x7F;
ctx->is224_384 = is384;
SHA_Open(is384 ? SHA_MODE_SHA384 : SHA_MODE_SHA512, SHA_NO_SWAP, 0);
// Ensure we have correct initial inernal states in SHA_DGST registers even though SHA H/W is not actually started.
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk;
return;
}
void mbedtls_sha512_hw_update(crypto_sha_context *ctx, const unsigned char *input, size_t ilen)
{
crypto_sha_update(ctx, input, ilen);
}
void mbedtls_sha512_hw_finish(crypto_sha_context *ctx, unsigned char output[64])
{
// H/W SHA cannot handle zero data well. Fall back to S/W SHA.
if (ctx->total) {
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 1);
ctx->buffer_left = 0;
crypto_sha_getinternstate(output, ctx->is224_384 ? 48 : 64);
CRPT->HMAC_CTL |= CRPT_HMAC_CTL_STOP_Msk;
}
else {
mbedtls_sha512_sw_context ctx_sw;
mbedtls_sha512_sw_init(&ctx_sw);
mbedtls_sha512_sw_starts(&ctx_sw, ctx->is224_384);
mbedtls_sha512_sw_finish(&ctx_sw, output);
mbedtls_sha512_sw_free(&ctx_sw);
}
}
void mbedtls_sha512_hw_process(crypto_sha_context *ctx, const unsigned char data[128])
{
mbedtls_sha512_hw_update(ctx, data, 128);
}
#endif /* MBEDTLS_SHA512_ALT */
#endif /* MBEDTLS_SHA512_C */
#if defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
void crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size_t ilen)
{
if (ilen == 0) {
return;
}
size_t fill = ctx->blocksize - ctx->buffer_left;
ctx->total += (uint32_t) ilen;
if (ctx->buffer_left && ilen >= fill) {
memcpy((void *) (ctx->buffer + ctx->buffer_left), input, fill);
input += fill;
ilen -= fill;
ctx->buffer_left += fill;
if (ilen) {
crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, 0);
ctx->buffer_left = 0;
}
}
while (ilen > ctx->blocksize) {
crypto_sha_update_nobuf(ctx, input, ctx->blocksize, 0);
input += ctx->blocksize;
ilen -= ctx->blocksize;
}
if (ilen > 0) {
memcpy((void *) (ctx->buffer + ctx->buffer_left), input, ilen);
ctx->buffer_left += ilen;
}
}
void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input, size_t ilen, int islast)
{
// Accept only:
// 1. Last block which may be incomplete
// 2. Non-last block which is complete
MBED_ASSERT(islast || ilen == ctx->blocksize);
const unsigned char *in_pos = input;
int rmn = ilen;
uint32_t sha_ctl_start = (CRPT->HMAC_CTL & ~(CRPT_HMAC_CTL_DMALAST_Msk | CRPT_HMAC_CTL_DMAEN_Msk | CRPT_HMAC_CTL_HMACEN_Msk)) | CRPT_HMAC_CTL_START_Msk;
uint32_t sha_opmode = (CRPT->HMAC_CTL & CRPT_HMAC_CTL_OPMODE_Msk) >> CRPT_HMAC_CTL_OPMODE_Pos;
uint32_t DGST0_old = 0, DGST1_old = 0, DGST2_old = 0, DGST3_old = 0, DGST4_old = 0, DGST5_old = 0, DGST6_old = 0, DGST7_old = 0,
DGST8_old = 0, DGST9_old = 0, DGST10_old = 0, DGST11_old = 0, DGST12_old = 0, DGST13_old = 0, DGST14_old = 0, DGST15_old = 0;
while (rmn > 0) {
CRPT->HMAC_CTL = sha_ctl_start;
uint32_t data = nu_get32_be(in_pos);
if (rmn <= 4) { // Last word of a (in)complete block
if (islast) {
uint32_t lastblock_size = ctx->total & ctx->blocksize_mask;
if (lastblock_size == 0) {
lastblock_size = ctx->blocksize;
}
CRPT->HMAC_DMACNT = lastblock_size;
CRPT->HMAC_CTL = sha_ctl_start | CRPT_HMAC_CTL_DMALAST_Msk;
}
else {
switch (sha_opmode) {
case SHA_MODE_SHA512:
DGST15_old = CRPT->HMAC_DGST[15];
DGST14_old = CRPT->HMAC_DGST[14];
DGST13_old = CRPT->HMAC_DGST[13];
DGST12_old = CRPT->HMAC_DGST[12];
case SHA_MODE_SHA384:
DGST11_old = CRPT->HMAC_DGST[11];
DGST10_old = CRPT->HMAC_DGST[10];
DGST9_old = CRPT->HMAC_DGST[9];
DGST8_old = CRPT->HMAC_DGST[8];
case SHA_MODE_SHA256:
DGST7_old = CRPT->HMAC_DGST[7];
case SHA_MODE_SHA224:
DGST5_old = CRPT->HMAC_DGST[5];
DGST6_old = CRPT->HMAC_DGST[6];
case SHA_MODE_SHA1:
DGST0_old = CRPT->HMAC_DGST[0];
DGST1_old = CRPT->HMAC_DGST[1];
DGST2_old = CRPT->HMAC_DGST[2];
DGST3_old = CRPT->HMAC_DGST[3];
DGST4_old = CRPT->HMAC_DGST[4];
}
CRPT->HMAC_CTL = sha_ctl_start;
}
}
else { // Non-last word of a complete block
CRPT->HMAC_CTL = sha_ctl_start;
}
while (! (CRPT->HMAC_STS & CRPT_HMAC_STS_DATINREQ_Msk));
CRPT->HMAC_DATIN = data;
in_pos += 4;
rmn -= 4;
}
if (islast) { // Finish of last block
while (CRPT->HMAC_STS & CRPT_HMAC_STS_BUSY_Msk);
}
else { // Finish of non-last block
// No H/W flag to indicate finish of non-last block process.
// Values of SHA_DGSTx registers will change as last word of the block is input, so use it for judgement.
int isfinish = 0;
while (! isfinish) {
switch (sha_opmode) {
case SHA_MODE_SHA512:
if (DGST12_old != CRPT->HMAC_DGST[12] || DGST13_old != CRPT->HMAC_DGST[13] || DGST14_old != CRPT->HMAC_DGST[14] ||
DGST15_old != CRPT->HMAC_DGST[15]) {
isfinish = 1;
break;
}
case SHA_MODE_SHA384:
if (DGST8_old != CRPT->HMAC_DGST[8] || DGST9_old != CRPT->HMAC_DGST[9] || DGST10_old != CRPT->HMAC_DGST[10] ||
DGST11_old != CRPT->HMAC_DGST[11]) {
isfinish = 1;
break;
}
case SHA_MODE_SHA256:
if (DGST7_old != CRPT->HMAC_DGST[7]) {
isfinish = 1;
break;
}
case SHA_MODE_SHA224:
if (DGST5_old != CRPT->HMAC_DGST[5] || DGST6_old != CRPT->HMAC_DGST[6]) {
isfinish = 1;
break;
}
case SHA_MODE_SHA1:
if (DGST0_old != CRPT->HMAC_DGST[0] || DGST1_old != CRPT->HMAC_DGST[1] || DGST2_old != CRPT->HMAC_DGST[2] ||
DGST3_old != CRPT->HMAC_DGST[3] || DGST4_old != CRPT->HMAC_DGST[4]) {
isfinish = 1;
break;
}
}
}
}
}
void crypto_sha_getinternstate(unsigned char output[], size_t olen)
{
uint32_t *in_pos = (uint32_t *) &CRPT->HMAC_DGST[0];
unsigned char *out_pos = output;
uint32_t rmn = olen;
while (rmn) {
uint32_t val = *in_pos ++;
nu_set32_be(out_pos, val);
out_pos += 4;
rmn -= 4;
}
}
#endif /* MBEDTLS_SHA1_ALT || MBEDTLS_SHA256_ALT || MBEDTLS_SHA512_ALT */
#endif /* MBEDTLS_SHA1_C || MBEDTLS_SHA256_C || MBEDTLS_SHA512_C */
#endif /* MBEDTLS_SHA1_C || MBEDTLS_SHA256_C || MBEDTLS_SHA512_C */

View File

@ -0,0 +1,108 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBEDTLS_SHA_ALT_HW_H
#define MBEDTLS_SHA_ALT_HW_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA context structure
*/
typedef struct
{
uint32_t total; /*!< number of bytes processed */
unsigned char buffer[128]; /*!< data block being processed. Max of SHA-1/SHA-256/SHA-512 */
uint16_t buffer_left;
uint16_t blocksize; /*!< block size */
uint32_t blocksize_mask; /*!< block size mask */
int is224_384; /*!< 0 => SHA-256/SHA-512, else SHA-224/384 */
}
crypto_sha_context;
void crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size_t ilen);
void crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input, size_t ilen, int islast);
void crypto_sha_getinternstate(unsigned char output[], size_t olen);
#if defined(MBEDTLS_SHA1_C)
#if defined(MBEDTLS_SHA1_ALT)
void mbedtls_sha1_hw_init( crypto_sha_context *ctx );
void mbedtls_sha1_hw_free( crypto_sha_context *ctx );
void mbedtls_sha1_hw_clone( crypto_sha_context *dst,
const crypto_sha_context *src );
void mbedtls_sha1_hw_starts( crypto_sha_context *ctx );
void mbedtls_sha1_hw_update( crypto_sha_context *ctx, const unsigned char *input, size_t ilen );
void mbedtls_sha1_hw_finish( crypto_sha_context *ctx, unsigned char output[20] );
void mbedtls_sha1_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
#endif /* MBEDTLS_SHA1_ALT */
#endif /* MBEDTLS_SHA1_C */
#if defined(MBEDTLS_SHA256_C)
#if defined(MBEDTLS_SHA256_ALT)
void mbedtls_sha256_hw_init( crypto_sha_context *ctx );
void mbedtls_sha256_hw_free( crypto_sha_context *ctx );
void mbedtls_sha256_hw_clone( crypto_sha_context *dst,
const crypto_sha_context *src );
void mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224 );
void mbedtls_sha256_hw_update( crypto_sha_context *ctx, const unsigned char *input,
size_t ilen );
void mbedtls_sha256_hw_finish( crypto_sha_context *ctx, unsigned char output[32] );
void mbedtls_sha256_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
#endif /* MBEDTLS_SHA256_ALT */
#endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_SHA512_ALT)
void mbedtls_sha512_hw_init( crypto_sha_context *ctx );
void mbedtls_sha512_hw_free( crypto_sha_context *ctx );
void mbedtls_sha512_hw_clone( crypto_sha_context *dst,
const crypto_sha_context *src );
void mbedtls_sha512_hw_starts( crypto_sha_context *ctx, int is384 );
void mbedtls_sha512_hw_update( crypto_sha_context *ctx, const unsigned char *input,
size_t ilen );
void mbedtls_sha512_hw_finish( crypto_sha_context *ctx, unsigned char output[64] );
void mbedtls_sha512_hw_process( crypto_sha_context *ctx, const unsigned char data[128] );
#endif /* MBEDTLS_SHA512_ALT */
#endif /* MBEDTLS_SHA512_C */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_SHA1_ALT || MBEDTLS_SHA256_ALT || MBEDTLS_SHA512_ALT */
#endif /* MBEDTLS_SHA1_C || MBEDTLS_SHA256_C || MBEDTLS_SHA512_C*/
#endif /* sha_alt.h */

View File

@ -682,11 +682,11 @@ extern "C" uint32_t __HeapLimit;
extern "C" int errno;
// Dynamic memory allocation related syscall.
#if defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NUMAKER_PFM_M453)
#if defined(TARGET_NUVOTON)
// Overwrite _sbrk() to support two region model (heap and stack are two distinct regions).
// __wrap__sbrk() is implemented in:
// TARGET_NUMAKER_PFM_NUC472 hal/targets/cmsis/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/retarget.c
// TARGET_NUMAKER_PFM_M453 hal/targets/cmsis/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/retarget.c
// TARGET_NUMAKER_PFM_NUC472 targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/nuc472_retarget.c
// TARGET_NUMAKER_PFM_M453 targets/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/m451_retarget.c
extern "C" void *__wrap__sbrk(int incr);
extern "C" caddr_t _sbrk(int incr) {
return (caddr_t) __wrap__sbrk(incr);

View File

@ -0,0 +1,140 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBED_PERIPHERALNAMES_H
#define MBED_PERIPHERALNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
// NOTE: Check all module base addresses (XXX_BASE in BSP) for free bit fields to define module name
// which encodes module base address and module index/subindex.
#define NU_MODSUBINDEX_Pos 0
#define NU_MODSUBINDEX_Msk (0x1Ful << NU_MODSUBINDEX_Pos)
#define NU_MODINDEX_Pos 20
#define NU_MODINDEX_Msk (0xFul << NU_MODINDEX_Pos)
#define NU_MODNAME(MODBASE, INDEX, SUBINDEX) ((MODBASE) | ((INDEX) << NU_MODINDEX_Pos) | ((SUBINDEX) << NU_MODSUBINDEX_Pos))
#define NU_MODBASE(MODNAME) ((MODNAME) & ~(NU_MODINDEX_Msk | NU_MODSUBINDEX_Msk))
#define NU_MODINDEX(MODNAME) (((MODNAME) & NU_MODINDEX_Msk) >> NU_MODINDEX_Pos)
#define NU_MODSUBINDEX(MODNAME) (((MODNAME) & NU_MODSUBINDEX_Msk) >> NU_MODSUBINDEX_Pos)
#if 0
typedef enum {
GPIO_A = (int) NU_MODNAME(GPIOA_BASE, 0, 0),
GPIO_B = (int) NU_MODNAME(GPIOB_BASE, 1, 0),
GPIO_C = (int) NU_MODNAME(GPIOC_BASE, 2, 0),
GPIO_D = (int) NU_MODNAME(GPIOD_BASE, 3, 0),
GPIO_E = (int) NU_MODNAME(GPIOE_BASE, 4, 0),
GPIO_F = (int) NU_MODNAME(GPIOF_BASE, 5, 0),
GPIO_G = (int) NU_MODNAME(GPIOG_BASE, 6, 0),
GPIO_H = (int) NU_MODNAME(GPIOH_BASE, 7, 0)
} GPIOName;
#endif
typedef enum {
ADC_0_0 = (int) NU_MODNAME(EADC_BASE, 0, 0),
ADC_0_1 = (int) NU_MODNAME(EADC_BASE, 0, 1),
ADC_0_2 = (int) NU_MODNAME(EADC_BASE, 0, 2),
ADC_0_3 = (int) NU_MODNAME(EADC_BASE, 0, 3),
ADC_0_4 = (int) NU_MODNAME(EADC_BASE, 0, 4),
ADC_0_5 = (int) NU_MODNAME(EADC_BASE, 0, 5),
ADC_0_6 = (int) NU_MODNAME(EADC_BASE, 0, 6),
ADC_0_7 = (int) NU_MODNAME(EADC_BASE, 0, 7),
ADC_0_8 = (int) NU_MODNAME(EADC_BASE, 0, 8),
ADC_0_9 = (int) NU_MODNAME(EADC_BASE, 0, 9),
ADC_0_10 = (int) NU_MODNAME(EADC_BASE, 0, 10),
ADC_0_11 = (int) NU_MODNAME(EADC_BASE, 0, 11),
ADC_0_12 = (int) NU_MODNAME(EADC_BASE, 0, 12),
ADC_0_13 = (int) NU_MODNAME(EADC_BASE, 0, 13),
ADC_0_14 = (int) NU_MODNAME(EADC_BASE, 0, 14),
ADC_0_15 = (int) NU_MODNAME(EADC_BASE, 0, 15)
} ADCName;
typedef enum {
UART_0 = (int) NU_MODNAME(UART0_BASE, 0, 0),
UART_1 = (int) NU_MODNAME(UART1_BASE, 1, 0),
UART_2 = (int) NU_MODNAME(UART2_BASE, 2, 0),
UART_3 = (int) NU_MODNAME(UART3_BASE, 3, 0),
UART_4 = (int) NU_MODNAME(UART4_BASE, 4, 0),
UART_5 = (int) NU_MODNAME(UART5_BASE, 5, 0),
// NOTE: board-specific
STDIO_UART = UART_0
} UARTName;
typedef enum {
SPI_0 = (int) NU_MODNAME(SPI0_BASE, 0, 0),
SPI_1 = (int) NU_MODNAME(SPI1_BASE, 1, 0),
SPI_2 = (int) NU_MODNAME(SPI2_BASE, 2, 0),
SPI_3 = (int) NU_MODNAME(SPI3_BASE, 3, 0),
SPI_4 = (int) NU_MODNAME(SPI4_BASE, 4, 0)
} SPIName;
typedef enum {
I2C_0 = (int) NU_MODNAME(I2C0_BASE, 0, 0),
I2C_1 = (int) NU_MODNAME(I2C1_BASE, 1, 0),
I2C_2 = (int) NU_MODNAME(I2C2_BASE, 2, 0)
} I2CName;
typedef enum {
PWM_0_0 = (int) NU_MODNAME(EPWM0_BASE, 0, 0),
PWM_0_1 = (int) NU_MODNAME(EPWM0_BASE, 0, 1),
PWM_0_2 = (int) NU_MODNAME(EPWM0_BASE, 0, 2),
PWM_0_3 = (int) NU_MODNAME(EPWM0_BASE, 0, 3),
PWM_0_4 = (int) NU_MODNAME(EPWM0_BASE, 0, 4),
PWM_0_5 = (int) NU_MODNAME(EPWM0_BASE, 0, 5),
PWM_1_0 = (int) NU_MODNAME(EPWM1_BASE, 1, 0),
PWM_1_1 = (int) NU_MODNAME(EPWM1_BASE, 1, 1),
PWM_1_2 = (int) NU_MODNAME(EPWM1_BASE, 1, 2),
PWM_1_3 = (int) NU_MODNAME(EPWM1_BASE, 1, 3),
PWM_1_4 = (int) NU_MODNAME(EPWM1_BASE, 1, 4),
PWM_1_5 = (int) NU_MODNAME(EPWM1_BASE, 1, 5)
} PWMName;
typedef enum {
TIMER_0 = (int) NU_MODNAME(TIMER0_BASE, 0, 0),
TIMER_1 = (int) NU_MODNAME(TIMER1_BASE, 1, 0),
TIMER_2 = (int) NU_MODNAME(TIMER2_BASE, 2, 0),
TIMER_3 = (int) NU_MODNAME(TIMER3_BASE, 3, 0),
} TIMERName;
typedef enum {
RTC_0 = (int) NU_MODNAME(RTC_BASE, 0, 0)
} RTCName;
typedef enum {
DMA_0 = (int) NU_MODNAME(PDMA_BASE, 0, 0)
} DMAName;
typedef enum {
SD_0 = (int) NU_MODNAME(SDH0_BASE, 0, 0),
SD_1 = (int) NU_MODNAME(SDH1_BASE, 1, 0)
} SDName;
typedef enum {
CAN_0 = (int) NU_MODNAME(CAN0_BASE, 0, 0),
CAN_1 = (int) NU_MODNAME(CAN1_BASE, 1, 0)
} CANName;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,586 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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.
*/
#include "PeripheralPins.h"
//*** ADC ***
const PinMap PinMap_ADC[] = {
{PB_0, ADC_0_0, SYS_GPB_MFPL_PB0MFP_EADC0_CH0},
{PB_1, ADC_0_1, SYS_GPB_MFPL_PB1MFP_EADC0_CH1},
{PB_2, ADC_0_2, SYS_GPB_MFPL_PB2MFP_EADC0_CH2},
{PB_3, ADC_0_3, SYS_GPB_MFPL_PB3MFP_EADC0_CH3},
{PB_4, ADC_0_4, SYS_GPB_MFPL_PB4MFP_EADC0_CH4},
{PB_5, ADC_0_5, SYS_GPB_MFPL_PB5MFP_EADC0_CH5},
{PB_6, ADC_0_6, SYS_GPB_MFPL_PB6MFP_EADC0_CH6},
{PB_7, ADC_0_7, SYS_GPB_MFPL_PB7MFP_EADC0_CH7},
{PB_8, ADC_0_8, SYS_GPB_MFPH_PB8MFP_EADC0_CH8},
{PB_9, ADC_0_9, SYS_GPB_MFPH_PB9MFP_EADC0_CH9},
{PB_10, ADC_0_10, SYS_GPB_MFPH_PB10MFP_EADC0_CH10},
{PB_11, ADC_0_11, SYS_GPB_MFPH_PB11MFP_EADC0_CH11},
{PB_12, ADC_0_12, SYS_GPB_MFPH_PB12MFP_EADC0_CH12},
{PB_13, ADC_0_13, SYS_GPB_MFPH_PB13MFP_EADC0_CH13},
{PB_14, ADC_0_14, SYS_GPB_MFPH_PB14MFP_EADC0_CH14},
{PB_15, ADC_0_15, SYS_GPB_MFPH_PB15MFP_EADC0_CH15},
{NC, NC, 0}
};
//*** I2C ***
const PinMap PinMap_I2C_SDA[] = {
{PA_0, I2C_2, SYS_GPA_MFPL_PA0MFP_I2C2_SDA},
{PA_2, I2C_1, SYS_GPA_MFPL_PA2MFP_I2C1_SDA},
{PA_4, I2C_0, SYS_GPA_MFPL_PA4MFP_I2C0_SDA},
{PA_6, I2C_1, SYS_GPA_MFPL_PA6MFP_I2C1_SDA},
{PA_10, I2C_2, SYS_GPA_MFPH_PA10MFP_I2C2_SDA},
{PA_13, I2C_1, SYS_GPA_MFPH_PA13MFP_I2C1_SDA},
{PA_15, I2C_2, SYS_GPA_MFPH_PA15MFP_I2C2_SDA},
{PB_0, I2C_1, SYS_GPB_MFPL_PB0MFP_I2C1_SDA},
{PB_4, I2C_0, SYS_GPB_MFPL_PB4MFP_I2C0_SDA},
{PB_10, I2C_1, SYS_GPB_MFPH_PB10MFP_I2C1_SDA},
{PB_12, I2C_2, SYS_GPB_MFPH_PB12MFP_I2C2_SDA},
{PC_0, I2C_0, SYS_GPC_MFPL_PC0MFP_I2C0_SDA},
{PC_4, I2C_1, SYS_GPC_MFPL_PC4MFP_I2C1_SDA},
{PC_8, I2C_0, SYS_GPC_MFPH_PC8MFP_I2C0_SDA},
{PC_11, I2C_0, SYS_GPC_MFPH_PC11MFP_I2C0_SDA},
{PD_0, I2C_2, SYS_GPD_MFPL_PD0MFP_I2C2_SDA},
{PD_4, I2C_1, SYS_GPD_MFPL_PD4MFP_I2C1_SDA},
{PD_6, I2C_0, SYS_GPD_MFPL_PD6MFP_I2C0_SDA},
{PD_8, I2C_2, SYS_GPD_MFPH_PD8MFP_I2C2_SDA},
{PE_0, I2C_1, SYS_GPE_MFPL_PE0MFP_I2C1_SDA},
{PF_1, I2C_1, SYS_GPF_MFPL_PF1MFP_I2C1_SDA},
{PF_2, I2C_0, SYS_GPF_MFPL_PF2MFP_I2C0_SDA},
{PG_1, I2C_0, SYS_GPG_MFPL_PG1MFP_I2C0_SDA},
{PG_3, I2C_1, SYS_GPG_MFPL_PG3MFP_I2C1_SDA},
{PH_3, I2C_0, SYS_GPH_MFPL_PH3MFP_I2C0_SDA},
{PH_9, I2C_2, SYS_GPH_MFPH_PH9MFP_I2C2_SDA},
{NC, NC, 0}
};
const PinMap PinMap_I2C_SCL[] = {
{PA_1, I2C_2, SYS_GPA_MFPL_PA1MFP_I2C2_SCL},
{PA_3, I2C_1, SYS_GPA_MFPL_PA3MFP_I2C1_SCL},
{PA_5, I2C_0, SYS_GPA_MFPL_PA5MFP_I2C0_SCL},
{PA_7, I2C_1, (int) SYS_GPA_MFPL_PA7MFP_I2C1_SCL},
{PA_11, I2C_2, SYS_GPA_MFPH_PA11MFP_I2C2_SCL},
{PA_12, I2C_1, SYS_GPA_MFPH_PA12MFP_I2C1_SCL},
{PA_14, I2C_2, SYS_GPA_MFPH_PA14MFP_I2C2_SCL},
{PB_1, I2C_1, SYS_GPB_MFPL_PB1MFP_I2C1_SCL},
{PB_5, I2C_0, SYS_GPB_MFPL_PB5MFP_I2C0_SCL},
{PB_11, I2C_1, SYS_GPB_MFPH_PB11MFP_I2C1_SCL},
{PB_13, I2C_2, SYS_GPB_MFPH_PB13MFP_I2C2_SCL},
{PC_1, I2C_0, SYS_GPC_MFPL_PC1MFP_I2C0_SCL},
{PC_5, I2C_1, SYS_GPC_MFPL_PC5MFP_I2C1_SCL},
{PC_12, I2C_0, SYS_GPC_MFPH_PC12MFP_I2C0_SCL},
{PD_1, I2C_2, SYS_GPD_MFPL_PD1MFP_I2C2_SCL},
{PD_5, I2C_1, SYS_GPD_MFPL_PD5MFP_I2C1_SCL},
{PD_7, I2C_0, SYS_GPD_MFPL_PD7MFP_I2C0_SCL},
{PD_9, I2C_2, SYS_GPD_MFPH_PD9MFP_I2C2_SCL},
{PE_1, I2C_1, SYS_GPE_MFPL_PE1MFP_I2C1_SCL},
{PE_13, I2C_0, SYS_GPE_MFPH_PE13MFP_I2C0_SCL},
{PF_0, I2C_1, SYS_GPF_MFPL_PF0MFP_I2C1_SCL},
{PF_3, I2C_0, SYS_GPF_MFPL_PF3MFP_I2C0_SCL},
{PG_0, I2C_0, SYS_GPG_MFPL_PG0MFP_I2C0_SCL},
{PG_2, I2C_1, SYS_GPG_MFPL_PG2MFP_I2C1_SCL},
{PH_2, I2C_0, SYS_GPH_MFPL_PH2MFP_I2C0_SCL},
{PH_8, I2C_2, SYS_GPH_MFPH_PH8MFP_I2C2_SCL},
{NC, NC, 0}
};
//*** PWM ***
const PinMap PinMap_PWM[] = {
{PA_0, PWM_0_5, SYS_GPA_MFPL_PA0MFP_EPWM0_CH5},
{PA_1, PWM_0_4, SYS_GPA_MFPL_PA1MFP_EPWM0_CH4},
{PA_2, PWM_0_3, SYS_GPA_MFPL_PA2MFP_EPWM0_CH3},
{PA_3, PWM_0_2, SYS_GPA_MFPL_PA3MFP_EPWM0_CH2},
{PA_4, PWM_0_1, SYS_GPA_MFPL_PA4MFP_EPWM0_CH1},
{PA_5, PWM_0_0, SYS_GPA_MFPL_PA5MFP_EPWM0_CH0},
{PA_6, PWM_1_5, SYS_GPA_MFPL_PA6MFP_EPWM1_CH5},
{PA_7, PWM_1_4, (int) SYS_GPA_MFPL_PA7MFP_EPWM1_CH4},
{PB_0, PWM_0_5, SYS_GPB_MFPL_PB0MFP_EPWM0_CH5},
{NU_PINNAME_BIND(PB_0, PWM_0_5), PWM_0_5, SYS_GPB_MFPL_PB0MFP_EPWM0_CH5},
{PB_0, PWM_1_5, SYS_GPB_MFPL_PB0MFP_EPWM1_CH5},
{NU_PINNAME_BIND(PB_0, PWM_1_5), PWM_1_5, SYS_GPB_MFPL_PB0MFP_EPWM1_CH5},
{PB_1, PWM_0_4, SYS_GPB_MFPL_PB1MFP_EPWM0_CH4},
{NU_PINNAME_BIND(PB_1, PWM_0_4), PWM_0_4, SYS_GPB_MFPL_PB1MFP_EPWM0_CH4},
{PB_1, PWM_1_4, SYS_GPB_MFPL_PB1MFP_EPWM1_CH4},
{NU_PINNAME_BIND(PB_1, PWM_1_4), PWM_1_4, SYS_GPB_MFPL_PB1MFP_EPWM1_CH4},
{PB_2, PWM_0_3, SYS_GPB_MFPL_PB2MFP_EPWM0_CH3},
{PB_3, PWM_0_2, SYS_GPB_MFPL_PB3MFP_EPWM0_CH2},
{PB_4, PWM_0_1, SYS_GPB_MFPL_PB4MFP_EPWM0_CH1},
{PB_5, PWM_0_0, SYS_GPB_MFPL_PB5MFP_EPWM0_CH0},
{PB_6, PWM_1_5, SYS_GPB_MFPL_PB6MFP_EPWM1_CH5},
{PB_7, PWM_1_4, (int) SYS_GPB_MFPL_PB7MFP_EPWM1_CH4},
{PB_12, PWM_1_3, SYS_GPB_MFPH_PB12MFP_EPWM1_CH3},
{PB_13, PWM_1_2, SYS_GPB_MFPH_PB13MFP_EPWM1_CH2},
{PB_14, PWM_1_1, SYS_GPB_MFPH_PB14MFP_EPWM1_CH1},
{PB_15, PWM_1_0, (int) SYS_GPB_MFPH_PB15MFP_EPWM1_CH0},
{PC_0, PWM_1_5, SYS_GPC_MFPL_PC0MFP_EPWM1_CH5},
{PC_1, PWM_1_4, SYS_GPC_MFPL_PC1MFP_EPWM1_CH4},
{PC_2, PWM_1_3, SYS_GPC_MFPL_PC2MFP_EPWM1_CH3},
{PC_3, PWM_1_2, SYS_GPC_MFPL_PC3MFP_EPWM1_CH2},
{PC_4, PWM_1_1, SYS_GPC_MFPL_PC4MFP_EPWM1_CH1},
{PC_5, PWM_1_0, SYS_GPC_MFPL_PC5MFP_EPWM1_CH0},
{PC_6, PWM_1_3, SYS_GPC_MFPL_PC6MFP_EPWM1_CH3},
{PC_7, PWM_1_2, (int) SYS_GPC_MFPL_PC7MFP_EPWM1_CH2},
{PC_8, PWM_1_1, SYS_GPC_MFPH_PC8MFP_EPWM1_CH1},
{PC_9, PWM_1_3, SYS_GPC_MFPH_PC9MFP_EPWM1_CH3},
{PC_10, PWM_1_2, SYS_GPC_MFPH_PC10MFP_EPWM1_CH2},
{PC_11, PWM_1_1, SYS_GPC_MFPH_PC11MFP_EPWM1_CH1},
{PC_12, PWM_1_0, SYS_GPC_MFPH_PC12MFP_EPWM1_CH0},
{PD_14, PWM_0_4, SYS_GPD_MFPH_PD14MFP_EPWM0_CH4},
{PE_2, PWM_0_5, SYS_GPE_MFPL_PE2MFP_EPWM0_CH5},
{PE_3, PWM_0_4, SYS_GPE_MFPL_PE3MFP_EPWM0_CH4},
{PE_4, PWM_0_3, SYS_GPE_MFPL_PE4MFP_EPWM0_CH3},
{PE_5, PWM_0_2, SYS_GPE_MFPL_PE5MFP_EPWM0_CH2},
{PE_6, PWM_0_1, SYS_GPE_MFPL_PE6MFP_EPWM0_CH1},
{PE_7, PWM_0_0, (int) SYS_GPE_MFPL_PE7MFP_EPWM0_CH0},
{PE_8, PWM_0_0, SYS_GPE_MFPH_PE8MFP_EPWM0_CH0},
{PE_9, PWM_0_1, SYS_GPE_MFPH_PE9MFP_EPWM0_CH1},
{PE_10, PWM_0_2, SYS_GPE_MFPH_PE10MFP_EPWM0_CH2},
{PE_11, PWM_0_3, SYS_GPE_MFPH_PE11MFP_EPWM0_CH3},
{PE_12, PWM_0_4, SYS_GPE_MFPH_PE12MFP_EPWM0_CH4},
{PE_13, PWM_0_5, SYS_GPE_MFPH_PE13MFP_EPWM0_CH5},
{NU_PINNAME_BIND(PE_13, PWM_0_5), PWM_0_5, SYS_GPE_MFPH_PE13MFP_EPWM0_CH5},
{PE_13, PWM_1_0, SYS_GPE_MFPH_PE13MFP_EPWM1_CH0},
{NU_PINNAME_BIND(PE_13, PWM_1_0), PWM_1_0, SYS_GPE_MFPH_PE13MFP_EPWM1_CH0},
{PG_5, PWM_0_3, SYS_GPG_MFPL_PG5MFP_EPWM0_CH3},
{PG_6, PWM_0_2, SYS_GPG_MFPL_PG6MFP_EPWM0_CH2},
{PG_7, PWM_0_1, (int) SYS_GPG_MFPL_PG7MFP_EPWM0_CH1},
{PG_8, PWM_0_0, SYS_GPG_MFPH_PG8MFP_EPWM0_CH0},
{PH_11, PWM_0_5, SYS_GPH_MFPH_PH11MFP_EPWM0_CH5},
{NC, NC, 0}
};
//*** SERIAL ***
const PinMap PinMap_UART_TX[] = {
{PA_1, UART_0, SYS_GPA_MFPL_PA1MFP_UART0_TXD},
{PA_3, UART_1, SYS_GPA_MFPL_PA3MFP_UART1_TXD},
{NU_PINNAME_BIND(PA_3, UART_1), UART_1, SYS_GPA_MFPL_PA3MFP_UART1_TXD},
{PA_3, UART_4, SYS_GPA_MFPL_PA3MFP_UART4_TXD},
{NU_PINNAME_BIND(PA_3, UART_4), UART_4, SYS_GPA_MFPL_PA3MFP_UART4_TXD},
{PA_5, UART_5, SYS_GPA_MFPL_PA5MFP_UART5_TXD},
{PA_7, UART_0, SYS_GPA_MFPL_PA7MFP_UART0_TXD},
{PA_9, UART_1, SYS_GPA_MFPH_PA9MFP_UART1_TXD},
{PA_12, UART_4, SYS_GPA_MFPH_PA12MFP_UART4_TXD},
{PA_14, UART_0, SYS_GPA_MFPH_PA14MFP_UART0_TXD},
{PB_1, UART_2, SYS_GPB_MFPL_PB1MFP_UART2_TXD},
{PB_3, UART_1, SYS_GPB_MFPL_PB3MFP_UART1_TXD},
{PB_5, UART_5, SYS_GPB_MFPL_PB5MFP_UART5_TXD},
{PB_7, UART_1, SYS_GPB_MFPL_PB7MFP_UART1_TXD},
{PB_9, UART_0, SYS_GPB_MFPH_PB9MFP_UART0_TXD},
{PB_11, UART_4, SYS_GPB_MFPH_PB11MFP_UART4_TXD},
{PB_13, UART_0, SYS_GPB_MFPH_PB13MFP_UART0_TXD},
{PB_15, UART_3, SYS_GPB_MFPH_PB15MFP_UART3_TXD},
{PC_1, UART_2, SYS_GPC_MFPL_PC1MFP_UART2_TXD},
{PC_3, UART_3, SYS_GPC_MFPL_PC3MFP_UART3_TXD},
{PC_5, UART_2, SYS_GPC_MFPL_PC5MFP_UART2_TXD},
{NU_PINNAME_BIND(PC_5, UART_2), UART_2, SYS_GPC_MFPL_PC5MFP_UART2_TXD},
{PC_5, UART_4, SYS_GPC_MFPL_PC5MFP_UART4_TXD},
{NU_PINNAME_BIND(PC_5, UART_4), UART_4, SYS_GPC_MFPL_PC5MFP_UART4_TXD},
{PC_7, UART_4, SYS_GPC_MFPL_PC7MFP_UART4_TXD},
{PC_10, UART_3, SYS_GPC_MFPH_PC10MFP_UART3_TXD},
{PC_12, UART_0, SYS_GPC_MFPH_PC12MFP_UART0_TXD},
{PC_13, UART_2, SYS_GPC_MFPH_PC13MFP_UART2_TXD},
{PD_1, UART_3, SYS_GPD_MFPL_PD1MFP_UART3_TXD},
{PD_3, UART_0, SYS_GPD_MFPL_PD3MFP_UART0_TXD},
{PD_7, UART_1, SYS_GPD_MFPL_PD7MFP_UART1_TXD},
{PD_11, UART_1, SYS_GPD_MFPH_PD11MFP_UART1_TXD},
{PE_1, UART_3, SYS_GPE_MFPL_PE1MFP_UART3_TXD},
{PE_7, UART_5, (int) SYS_GPE_MFPL_PE7MFP_UART5_TXD},
{PE_8, UART_2, SYS_GPE_MFPH_PE8MFP_UART2_TXD},
{PE_10, UART_3, SYS_GPE_MFPH_PE10MFP_UART3_TXD},
{PE_13, UART_1, SYS_GPE_MFPH_PE13MFP_UART1_TXD},
{PE_14, UART_2, SYS_GPE_MFPH_PE14MFP_UART2_TXD},
{PF_0, UART_1, SYS_GPF_MFPL_PF0MFP_UART1_TXD},
{PF_3, UART_0, SYS_GPF_MFPL_PF3MFP_UART0_TXD},
{PF_4, UART_2, SYS_GPF_MFPL_PF4MFP_UART2_TXD},
{PF_7, UART_4, SYS_GPF_MFPL_PF7MFP_UART4_TXD},
{PG_0, UART_1, SYS_GPG_MFPL_PG0MFP_UART1_TXD},
{PG_1, UART_2, SYS_GPG_MFPL_PG1MFP_UART2_TXD},
{PH_0, UART_5, SYS_GPH_MFPL_PH0MFP_UART5_TXD},
{PH_2, UART_4, SYS_GPH_MFPL_PH2MFP_UART4_TXD},
{PH_8, UART_1, SYS_GPH_MFPH_PH8MFP_UART1_TXD},
{PH_10, UART_0, SYS_GPH_MFPH_PH10MFP_UART0_TXD},
{NU_PINNAME_BIND(PH_10, UART_0), UART_0, SYS_GPH_MFPH_PH10MFP_UART0_TXD},
{PH_10, UART_4, SYS_GPH_MFPH_PH10MFP_UART4_TXD},
{NU_PINNAME_BIND(PH_10, UART_4), UART_4, SYS_GPH_MFPH_PH10MFP_UART4_TXD},
{NC, NC, 0}
};
const PinMap PinMap_UART_RX[] = {
{PA_0, UART_0, SYS_GPA_MFPL_PA0MFP_UART0_RXD},
{PA_2, UART_1, SYS_GPA_MFPL_PA2MFP_UART1_RXD},
{NU_PINNAME_BIND(PA_2, UART_1), UART_1, SYS_GPA_MFPL_PA2MFP_UART1_RXD},
{PA_2, UART_4, SYS_GPA_MFPL_PA2MFP_UART4_RXD},
{NU_PINNAME_BIND(PA_2, UART_4), UART_4, SYS_GPA_MFPL_PA2MFP_UART4_RXD},
{PA_4, UART_5, SYS_GPA_MFPL_PA4MFP_UART5_RXD},
{PA_6, UART_0, SYS_GPA_MFPL_PA6MFP_UART0_RXD},
{PA_8, UART_1, SYS_GPA_MFPH_PA8MFP_UART1_RXD},
{PA_13, UART_4, SYS_GPA_MFPH_PA13MFP_UART4_RXD},
{PA_15, UART_0, SYS_GPA_MFPH_PA15MFP_UART0_RXD},
{PB_0, UART_2, SYS_GPB_MFPL_PB0MFP_UART2_RXD},
{PB_2, UART_1, SYS_GPB_MFPL_PB2MFP_UART1_RXD},
{PB_4, UART_5, SYS_GPB_MFPL_PB4MFP_UART5_RXD},
{PB_6, UART_1, SYS_GPB_MFPL_PB6MFP_UART1_RXD},
{PB_8, UART_0, SYS_GPB_MFPH_PB8MFP_UART0_RXD},
{PB_10, UART_4, SYS_GPB_MFPH_PB10MFP_UART4_RXD},
{PB_12, UART_0, SYS_GPB_MFPH_PB12MFP_UART0_RXD},
{PB_14, UART_3, SYS_GPB_MFPH_PB14MFP_UART3_RXD},
{PC_0, UART_2, SYS_GPC_MFPL_PC0MFP_UART2_RXD},
{PC_2, UART_3, SYS_GPC_MFPL_PC2MFP_UART3_RXD},
{PC_4, UART_2, SYS_GPC_MFPL_PC4MFP_UART2_RXD},
{NU_PINNAME_BIND(PC_4, UART_2), UART_2, SYS_GPC_MFPL_PC4MFP_UART2_RXD},
{PC_4, UART_4, SYS_GPC_MFPL_PC4MFP_UART4_RXD},
{NU_PINNAME_BIND(PC_4, UART_4), UART_4, SYS_GPC_MFPL_PC4MFP_UART4_RXD},
{PC_6, UART_4, SYS_GPC_MFPL_PC6MFP_UART4_RXD},
{PC_8, UART_1, SYS_GPC_MFPH_PC8MFP_UART1_RXD},
{PC_9, UART_3, SYS_GPC_MFPH_PC9MFP_UART3_RXD},
{PC_11, UART_0, SYS_GPC_MFPH_PC11MFP_UART0_RXD},
{PD_0, UART_3, SYS_GPD_MFPL_PD0MFP_UART3_RXD},
{PD_2, UART_0, SYS_GPD_MFPL_PD2MFP_UART0_RXD},
{PD_6, UART_1, SYS_GPD_MFPL_PD6MFP_UART1_RXD},
{PD_10, UART_1, SYS_GPD_MFPH_PD10MFP_UART1_RXD},
{PD_12, UART_2, SYS_GPD_MFPH_PD12MFP_UART2_RXD},
{PE_0, UART_3, SYS_GPE_MFPL_PE0MFP_UART3_RXD},
{PE_6, UART_5, SYS_GPE_MFPL_PE6MFP_UART5_RXD},
{PE_9, UART_2, SYS_GPE_MFPH_PE9MFP_UART2_RXD},
{PE_11, UART_3, SYS_GPE_MFPH_PE11MFP_UART3_RXD},
{PE_15, UART_2, SYS_GPE_MFPH_PE15MFP_UART2_RXD},
{PF_1, UART_1, SYS_GPF_MFPL_PF1MFP_UART1_RXD},
{PF_2, UART_0, SYS_GPF_MFPL_PF2MFP_UART0_RXD},
{PF_5, UART_2, SYS_GPF_MFPL_PF5MFP_UART2_RXD},
{PF_6, UART_4, SYS_GPF_MFPL_PF6MFP_UART4_RXD},
{PG_0, UART_2, SYS_GPG_MFPL_PG0MFP_UART2_RXD},
{PG_1, UART_1, SYS_GPG_MFPL_PG1MFP_UART1_RXD},
{PH_1, UART_5, SYS_GPH_MFPL_PH1MFP_UART5_RXD},
{PH_3, UART_4, SYS_GPH_MFPL_PH3MFP_UART4_RXD},
{PH_9, UART_1, SYS_GPH_MFPH_PH9MFP_UART1_RXD},
{PH_11, UART_0, SYS_GPH_MFPH_PH11MFP_UART0_RXD},
{NU_PINNAME_BIND(PH_11, UART_0), UART_0, SYS_GPH_MFPH_PH11MFP_UART0_RXD},
{PH_11, UART_4, SYS_GPH_MFPH_PH11MFP_UART4_RXD},
{NU_PINNAME_BIND(PH_11, UART_4), UART_4, SYS_GPH_MFPH_PH11MFP_UART4_RXD},
{NC, NC, 0}
};
const PinMap PinMap_UART_RTS[] = {
{PA_0, UART_1, SYS_GPA_MFPL_PA0MFP_UART1_nRTS},
{PA_4, UART_0, SYS_GPA_MFPL_PA4MFP_UART0_nRTS},
{PB_3, UART_5, SYS_GPB_MFPL_PB3MFP_UART5_nRTS},
{PB_8, UART_1, SYS_GPB_MFPH_PB8MFP_UART1_nRTS},
{PB_10, UART_0, SYS_GPB_MFPH_PB10MFP_UART0_nRTS},
{PB_13, UART_3, SYS_GPB_MFPH_PB13MFP_UART3_nRTS},
{PB_14, UART_0, SYS_GPB_MFPH_PB14MFP_UART0_nRTS},
{PC_3, UART_2, SYS_GPC_MFPL_PC3MFP_UART2_nRTS},
{PC_6, UART_0, SYS_GPC_MFPL_PC6MFP_UART0_nRTS},
{PD_3, UART_3, SYS_GPD_MFPL_PD3MFP_UART3_nRTS},
{PD_8, UART_2, SYS_GPD_MFPH_PD8MFP_UART2_nRTS},
{PE_0, UART_4, SYS_GPE_MFPL_PE0MFP_UART4_nRTS},
{PE_12, UART_1, SYS_GPE_MFPH_PE12MFP_UART1_nRTS},
{PE_13, UART_4, SYS_GPE_MFPH_PE13MFP_UART4_nRTS},
{PF_4, UART_2, SYS_GPF_MFPL_PF4MFP_UART2_nRTS},
{PH_2, UART_5, SYS_GPH_MFPL_PH2MFP_UART5_nRTS},
{PH_8, UART_3, SYS_GPH_MFPH_PH8MFP_UART3_nRTS},
{NC, NC, 0}
};
const PinMap PinMap_UART_CTS[] = {
{PA_1, UART_1, SYS_GPA_MFPL_PA1MFP_UART1_nCTS},
{PA_5, UART_0, SYS_GPA_MFPL_PA5MFP_UART0_nCTS},
{PB_2, UART_5, SYS_GPB_MFPL_PB2MFP_UART5_nCTS},
{PB_9, UART_1, SYS_GPB_MFPH_PB9MFP_UART1_nCTS},
{PB_11, UART_0, SYS_GPB_MFPH_PB11MFP_UART0_nCTS},
{PB_12, UART_3, SYS_GPB_MFPH_PB12MFP_UART3_nCTS},
{PB_15, UART_0, SYS_GPB_MFPH_PB15MFP_UART0_nCTS},
{PC_2, UART_2, SYS_GPC_MFPL_PC2MFP_UART2_nCTS},
{PC_7, UART_0, SYS_GPC_MFPL_PC7MFP_UART0_nCTS},
{PC_8, UART_4, SYS_GPC_MFPH_PC8MFP_UART4_nCTS},
{PD_2, UART_3, SYS_GPD_MFPL_PD2MFP_UART3_nCTS},
{PD_9, UART_2, SYS_GPD_MFPH_PD9MFP_UART2_nCTS},
{PE_1, UART_4, SYS_GPE_MFPL_PE1MFP_UART4_nCTS},
{PE_11, UART_1, SYS_GPE_MFPH_PE11MFP_UART1_nCTS},
{PF_5, UART_2, SYS_GPF_MFPL_PF5MFP_UART2_nCTS},
{PH_3, UART_5, SYS_GPH_MFPL_PH3MFP_UART5_nCTS},
{PH_9, UART_3, SYS_GPH_MFPH_PH9MFP_UART3_nCTS},
{NC, NC, 0}
};
//*** SPI ***
const PinMap PinMap_SPI_MOSI[] = {
{PA_0, SPI_0, SYS_GPA_MFPL_PA0MFP_SPI0_MOSI0},
{NU_PINNAME_BIND(PA_0, SPI_0), SPI_0, SYS_GPA_MFPL_PA0MFP_SPI0_MOSI0},
{PA_0, SPI_1, SYS_GPA_MFPL_PA0MFP_SPI1_MOSI},
{NU_PINNAME_BIND(PA_0, SPI_1), SPI_1, SYS_GPA_MFPL_PA0MFP_SPI1_MOSI},
{PA_8, SPI_3, SYS_GPA_MFPH_PA8MFP_SPI3_MOSI},
{PA_15, SPI_3, SYS_GPA_MFPH_PA15MFP_SPI3_MOSI},
{PB_4, SPI_2, SYS_GPB_MFPL_PB4MFP_SPI2_MOSI},
{PB_8, SPI_4, SYS_GPB_MFPH_PB8MFP_SPI4_MOSI},
{PB_12, SPI_1, SYS_GPB_MFPH_PB12MFP_SPI1_MOSI},
{PC_0, SPI_0, SYS_GPC_MFPL_PC0MFP_SPI0_MOSI0},
{PC_2, SPI_2, SYS_GPC_MFPL_PC2MFP_SPI2_MOSI},
{PC_6, SPI_2, SYS_GPC_MFPL_PC6MFP_SPI2_MOSI},
{PC_11, SPI_4, SYS_GPC_MFPH_PC11MFP_SPI4_MOSI},
{PD_0, SPI_1, SYS_GPD_MFPL_PD0MFP_SPI1_MOSI},
{PD_6, SPI_2, SYS_GPD_MFPL_PD6MFP_SPI2_MOSI},
{PE_0, SPI_0, SYS_GPE_MFPL_PE0MFP_SPI0_MOSI0},
{NU_PINNAME_BIND(PE_0, SPI_0), SPI_0, SYS_GPE_MFPL_PE0MFP_SPI0_MOSI0},
{PE_0, SPI_2, SYS_GPE_MFPL_PE0MFP_SPI2_MOSI},
{NU_PINNAME_BIND(PE_0, SPI_2), SPI_2, SYS_GPE_MFPL_PE0MFP_SPI2_MOSI},
{PE_2, SPI_4, SYS_GPE_MFPL_PE2MFP_SPI4_MOSI},
{PE_10, SPI_3, SYS_GPE_MFPH_PE10MFP_SPI3_MOSI},
{PF_6, SPI_1, SYS_GPF_MFPL_PF6MFP_SPI1_MOSI},
{PF_11, SPI_3, SYS_GPF_MFPH_PF11MFP_SPI3_MOSI},
{PG_8, SPI_4, SYS_GPG_MFPH_PG8MFP_SPI4_MOSI},
{PH_5, SPI_2, SYS_GPH_MFPL_PH5MFP_SPI2_MOSI},
{NC, NC, 0}
};
const PinMap PinMap_SPI_MISO[] = {
{PA_1, SPI_0, SYS_GPA_MFPL_PA1MFP_SPI0_MISO0},
{NU_PINNAME_BIND(PA_1, SPI_0), SPI_0, SYS_GPA_MFPL_PA1MFP_SPI0_MISO0},
{PA_1, SPI_1, SYS_GPA_MFPL_PA1MFP_SPI1_MISO},
{NU_PINNAME_BIND(PA_1, SPI_1), SPI_1, SYS_GPA_MFPL_PA1MFP_SPI1_MISO},
{PA_9, SPI_3, SYS_GPA_MFPH_PA9MFP_SPI3_MISO},
{PA_14, SPI_3, SYS_GPA_MFPH_PA14MFP_SPI3_MISO},
{PB_5, SPI_2, SYS_GPB_MFPL_PB5MFP_SPI2_MISO},
{PB_9, SPI_4, SYS_GPB_MFPH_PB9MFP_SPI4_MISO},
{PB_13, SPI_1, SYS_GPB_MFPH_PB13MFP_SPI1_MISO},
{PC_1, SPI_0, SYS_GPC_MFPL_PC1MFP_SPI0_MISO0},
{PC_3, SPI_2, SYS_GPC_MFPL_PC3MFP_SPI2_MISO},
{PC_7, SPI_2, SYS_GPC_MFPL_PC7MFP_SPI2_MISO},
{PC_12, SPI_4, SYS_GPC_MFPH_PC12MFP_SPI4_MISO},
{PD_1, SPI_1, SYS_GPD_MFPL_PD1MFP_SPI1_MISO},
{PD_7, SPI_2, SYS_GPD_MFPL_PD7MFP_SPI2_MISO},
{PE_1, SPI_0, SYS_GPE_MFPL_PE1MFP_SPI0_MISO0},
{NU_PINNAME_BIND(PE_1, SPI_0), SPI_0, SYS_GPE_MFPL_PE1MFP_SPI0_MISO0},
{PE_1, SPI_2, SYS_GPE_MFPL_PE1MFP_SPI2_MISO},
{NU_PINNAME_BIND(PE_1, SPI_2), SPI_2, SYS_GPE_MFPL_PE1MFP_SPI2_MISO},
{PE_3, SPI_4, SYS_GPE_MFPL_PE3MFP_SPI4_MISO},
{PE_9, SPI_3, SYS_GPE_MFPH_PE9MFP_SPI3_MISO},
{PF_7, SPI_1, SYS_GPF_MFPL_PF7MFP_SPI1_MISO},
{PG_4, SPI_3, SYS_GPG_MFPL_PG4MFP_SPI3_MISO},
{PG_7, SPI_4, SYS_GPG_MFPL_PG7MFP_SPI4_MISO},
{PH_4, SPI_2, SYS_GPH_MFPL_PH4MFP_SPI2_MISO},
{NC, NC, 0}
};
const PinMap PinMap_SPI_SCLK[] = {
{PA_2, SPI_0, SYS_GPA_MFPL_PA2MFP_SPI0_CLK},
{NU_PINNAME_BIND(PA_2, SPI_0), SPI_0, SYS_GPA_MFPL_PA2MFP_SPI0_CLK},
{PA_2, SPI_1, SYS_GPA_MFPL_PA2MFP_SPI1_CLK},
{NU_PINNAME_BIND(PA_2, SPI_1), SPI_1, SYS_GPA_MFPL_PA2MFP_SPI1_CLK},
{PA_7, SPI_2, SYS_GPA_MFPL_PA7MFP_SPI2_CLK},
{PA_10, SPI_3, SYS_GPA_MFPH_PA10MFP_SPI3_CLK},
{PA_13, SPI_3, SYS_GPA_MFPH_PA13MFP_SPI3_CLK},
{PB_3, SPI_2, SYS_GPB_MFPL_PB3MFP_SPI2_CLK},
{PB_11, SPI_4, SYS_GPB_MFPH_PB11MFP_SPI4_CLK},
{PB_14, SPI_1, SYS_GPB_MFPH_PB14MFP_SPI1_CLK},
{PC_1, SPI_2, SYS_GPC_MFPL_PC1MFP_SPI2_CLK},
{PC_2, SPI_0, SYS_GPC_MFPL_PC2MFP_SPI0_CLK},
{PC_10, SPI_4, SYS_GPC_MFPH_PC10MFP_SPI4_CLK},
{PC_14, SPI_0, SYS_GPC_MFPH_PC14MFP_SPI0_CLK},
{PD_2, SPI_1, SYS_GPD_MFPL_PD2MFP_SPI1_CLK},
{PD_5, SPI_2, SYS_GPD_MFPL_PD5MFP_SPI2_CLK},
{PE_4, SPI_4, SYS_GPE_MFPL_PE4MFP_SPI4_CLK},
{PE_8, SPI_3, SYS_GPE_MFPH_PE8MFP_SPI3_CLK},
{PF_2, SPI_0, SYS_GPF_MFPL_PF2MFP_SPI0_CLK},
{PF_8, SPI_1, SYS_GPF_MFPH_PF8MFP_SPI1_CLK},
{PG_3, SPI_3, SYS_GPG_MFPL_PG3MFP_SPI3_CLK},
{PG_6, SPI_4, SYS_GPG_MFPL_PG6MFP_SPI4_CLK},
{PH_6, SPI_2, SYS_GPH_MFPL_PH6MFP_SPI2_CLK},
{PH_8, SPI_0, SYS_GPH_MFPH_PH8MFP_SPI0_CLK},
{NU_PINNAME_BIND(PH_8, SPI_0), SPI_0, SYS_GPH_MFPH_PH8MFP_SPI0_CLK},
{PH_8, SPI_2, SYS_GPH_MFPH_PH8MFP_SPI2_CLK},
{NU_PINNAME_BIND(PH_8, SPI_2), SPI_2, SYS_GPH_MFPH_PH8MFP_SPI2_CLK},
{NC, NC, 0}
};
const PinMap PinMap_SPI_SSEL[] = {
{PA_3, SPI_0, SYS_GPA_MFPL_PA3MFP_SPI0_SS},
{NU_PINNAME_BIND(PA_3, SPI_0), SPI_0, SYS_GPA_MFPL_PA3MFP_SPI0_SS},
{PA_3, SPI_1, SYS_GPA_MFPL_PA3MFP_SPI1_SS},
{NU_PINNAME_BIND(PA_3, SPI_1), SPI_1, SYS_GPA_MFPL_PA3MFP_SPI1_SS},
{PA_6, SPI_2, SYS_GPA_MFPL_PA6MFP_SPI2_SS},
{PA_11, SPI_3, SYS_GPA_MFPH_PA11MFP_SPI3_SS},
{PA_12, SPI_3, SYS_GPA_MFPH_PA12MFP_SPI3_SS},
{PB_2, SPI_2, SYS_GPB_MFPL_PB2MFP_SPI2_SS},
{PB_10, SPI_4, SYS_GPB_MFPH_PB10MFP_SPI4_SS},
{PB_15, SPI_1, SYS_GPB_MFPH_PB15MFP_SPI1_SS},
{PC_0, SPI_2, SYS_GPC_MFPL_PC0MFP_SPI2_SS},
{PC_3, SPI_0, SYS_GPC_MFPL_PC3MFP_SPI0_SS},
{PC_9, SPI_4, SYS_GPC_MFPH_PC9MFP_SPI4_SS},
{PD_3, SPI_1, SYS_GPD_MFPL_PD3MFP_SPI1_SS},
{PD_4, SPI_2, SYS_GPD_MFPL_PD4MFP_SPI2_SS},
{PE_5, SPI_4, SYS_GPE_MFPL_PE5MFP_SPI4_SS},
{PE_11, SPI_3, SYS_GPE_MFPH_PE11MFP_SPI3_SS},
{PF_9, SPI_1, SYS_GPF_MFPH_PF9MFP_SPI1_SS},
{PG_2, SPI_3, SYS_GPG_MFPL_PG2MFP_SPI3_SS},
{PG_5, SPI_4, SYS_GPG_MFPL_PG5MFP_SPI4_SS},
{PH_7, SPI_2, SYS_GPH_MFPL_PH7MFP_SPI2_SS},
{PH_9, SPI_0, SYS_GPH_MFPH_PH9MFP_SPI0_SS},
{NU_PINNAME_BIND(PH_9, SPI_0), SPI_0, SYS_GPH_MFPH_PH9MFP_SPI0_SS},
{PH_9, SPI_2, SYS_GPH_MFPH_PH9MFP_SPI2_SS},
{NU_PINNAME_BIND(PH_9, SPI_2), SPI_2, SYS_GPH_MFPH_PH9MFP_SPI2_SS},
{NC, NC, 0}
};
//*** SD ***
const PinMap PinMap_SD_DAT0[] = {
{PA_0, SD_1, SYS_GPA_MFPL_PA0MFP_SD1_DAT0},
{PA_8, SD_1, SYS_GPA_MFPH_PA8MFP_SD1_DAT0},
{PB_2, SD_0, SYS_GPB_MFPL_PB2MFP_SD0_DAT0},
{PE_2, SD_0, SYS_GPE_MFPL_PE2MFP_SD0_DAT0},
{PG_12, SD_1, SYS_GPG_MFPH_PG12MFP_SD1_DAT0},
{NC, NC, 0}
};
const PinMap PinMap_SD_DAT1[] = {
{PA_1, SD_1, SYS_GPA_MFPL_PA1MFP_SD1_DAT1},
{PA_9, SD_1, SYS_GPA_MFPH_PA9MFP_SD1_DAT1},
{PB_3, SD_0, SYS_GPB_MFPL_PB3MFP_SD0_DAT1},
{PE_3, SD_0, SYS_GPE_MFPL_PE3MFP_SD0_DAT1},
{PG_11, SD_1, SYS_GPG_MFPH_PG11MFP_SD1_DAT1},
{NC, NC, 0}
};
const PinMap PinMap_SD_DAT2[] = {
{PA_2, SD_1, SYS_GPA_MFPL_PA2MFP_SD1_DAT2},
{PA_10, SD_1, SYS_GPA_MFPH_PA10MFP_SD1_DAT2},
{PB_4, SD_0, SYS_GPB_MFPL_PB4MFP_SD0_DAT2},
{PE_4, SD_0, SYS_GPE_MFPL_PE4MFP_SD0_DAT2},
{PG_10, SD_1, SYS_GPG_MFPH_PG10MFP_SD1_DAT2},
{NC, NC, 0}
};
const PinMap PinMap_SD_DAT3[] = {
{PA_3, SD_1, SYS_GPA_MFPL_PA3MFP_SD1_DAT3},
{PA_11, SD_1, SYS_GPA_MFPH_PA11MFP_SD1_DAT3},
{PB_5, SD_0, SYS_GPB_MFPL_PB5MFP_SD0_DAT3},
{PE_5, SD_0, SYS_GPE_MFPL_PE5MFP_SD0_DAT3},
{PG_9, SD_1, SYS_GPG_MFPH_PG9MFP_SD1_DAT3},
{NC, NC, 0}
};
const PinMap PinMap_SD_CMD[] = {
{PA_5, SD_1, SYS_GPA_MFPL_PA5MFP_SD1_CMD},
{PB_0, SD_0, SYS_GPB_MFPL_PB0MFP_SD0_CMD},
{PB_7, SD_1, SYS_GPB_MFPL_PB7MFP_SD1_CMD},
{PE_7, SD_0, SYS_GPE_MFPL_PE7MFP_SD0_CMD},
{PG_13, SD_1, SYS_GPG_MFPH_PG13MFP_SD1_CMD},
{NC, NC, 0}
};
const PinMap PinMap_SD_CLK[] = {
{PA_4, SD_1, SYS_GPA_MFPL_PA4MFP_SD1_CLK},
{PB_1, SD_0, SYS_GPB_MFPL_PB1MFP_SD0_CLK},
{PB_6, SD_1, SYS_GPB_MFPL_PB6MFP_SD1_CLK},
{PE_6, SD_0, SYS_GPE_MFPL_PE6MFP_SD0_CLK},
{PG_14, SD_1, SYS_GPG_MFPH_PG14MFP_SD1_CLK},
{NC, NC, 0}
};
const PinMap PinMap_SD_CD[] = {
{PA_6, SD_1, SYS_GPA_MFPL_PA6MFP_SD1_nCD},
{PB_12, SD_0, SYS_GPB_MFPH_PB12MFP_SD0_nCD},
{PD_13, SD_0, SYS_GPD_MFPH_PD13MFP_SD0_nCD},
{PE_14, SD_1, SYS_GPE_MFPH_PE14MFP_SD1_nCD},
{PG_15, SD_1, SYS_GPG_MFPH_PG15MFP_SD1_nCD},
{NC, NC, 0}
};
//*** CAN ***
const PinMap PinMap_CAN_TD[] = {
{PA_5, CAN_0, SYS_GPA_MFPL_PA5MFP_CAN0_TXD},
{PA_12, CAN_0, SYS_GPA_MFPH_PA12MFP_CAN0_TXD},
{PB_7, CAN_1, SYS_GPB_MFPL_PB7MFP_CAN1_TXD},
{PB_11, CAN_0, SYS_GPB_MFPH_PB11MFP_CAN0_TXD},
{PC_3, CAN_1, SYS_GPC_MFPL_PC3MFP_CAN1_TXD},
{PC_5, CAN_0, SYS_GPC_MFPL_PC5MFP_CAN0_TXD},
{PC_10, CAN_1, SYS_GPC_MFPH_PC10MFP_CAN1_TXD},
{PC_13, CAN_1, SYS_GPC_MFPH_PC13MFP_CAN1_TXD},
{PD_11, CAN_0, SYS_GPD_MFPH_PD11MFP_CAN0_TXD},
{PE_7, CAN_1, (int) SYS_GPE_MFPL_PE7MFP_CAN1_TXD},
{PE_14, CAN_0, SYS_GPE_MFPH_PE14MFP_CAN0_TXD},
{PG_0, CAN_1, SYS_GPG_MFPL_PG0MFP_CAN1_TXD},
{NC, NC, 0}
};
const PinMap PinMap_CAN_RD[] = {
{PA_4, CAN_0, SYS_GPA_MFPL_PA4MFP_CAN0_RXD},
{PA_13, CAN_0, SYS_GPA_MFPH_PA13MFP_CAN0_RXD},
{PB_6, CAN_1, SYS_GPB_MFPL_PB6MFP_CAN1_RXD},
{PB_10, CAN_0, SYS_GPB_MFPH_PB10MFP_CAN0_RXD},
{PC_2, CAN_1, SYS_GPC_MFPL_PC2MFP_CAN1_RXD},
{PC_4, CAN_0, SYS_GPC_MFPL_PC4MFP_CAN0_RXD},
{PC_9, CAN_1, SYS_GPC_MFPH_PC9MFP_CAN1_RXD},
{PD_10, CAN_0, SYS_GPD_MFPH_PD10MFP_CAN0_RXD},
{PD_12, CAN_1, SYS_GPD_MFPH_PD12MFP_CAN1_RXD},
{PE_6, CAN_1, SYS_GPE_MFPL_PE6MFP_CAN1_RXD},
{PE_15, CAN_0, SYS_GPE_MFPH_PE15MFP_CAN0_RXD},
{PG_1, CAN_1, SYS_GPG_MFPL_PG1MFP_CAN1_RXD},
{NC, NC, 0}
};

View File

@ -0,0 +1,77 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBED_PERIPHERALPINS_H
#define MBED_PERIPHERALPINS_H
#include "pinmap.h"
#include "PeripheralNames.h"
#ifdef __cplusplus
extern "C" {
#endif
//*** GPIO ***
extern const PinMap PinMap_GPIO[];
//*** ADC ***
extern const PinMap PinMap_ADC[];
//*** I2C ***
extern const PinMap PinMap_I2C_SDA[];
extern const PinMap PinMap_I2C_SCL[];
//*** PWM ***
extern const PinMap PinMap_PWM[];
//*** SERIAL ***
extern const PinMap PinMap_UART_TX[];
extern const PinMap PinMap_UART_RX[];
extern const PinMap PinMap_UART_RTS[];
extern const PinMap PinMap_UART_CTS[];
//*** SPI ***
extern const PinMap PinMap_SPI_MOSI[];
extern const PinMap PinMap_SPI_MISO[];
extern const PinMap PinMap_SPI_SCLK[];
extern const PinMap PinMap_SPI_SSEL[];
//*** SD ***
extern const PinMap PinMap_SD_CD[];
extern const PinMap PinMap_SD_CMD[];
extern const PinMap PinMap_SD_CLK[];
extern const PinMap PinMap_SD_DAT0[];
extern const PinMap PinMap_SD_DAT1[];
extern const PinMap PinMap_SD_DAT2[];
extern const PinMap PinMap_SD_DAT3[];
//*** CAN ***
extern PinMap const PinMap_CAN_TD[];
extern PinMap const PinMap_CAN_RD[];
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,132 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBED_PINNAMES_H
#define MBED_PINNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NU_PININDEX_Pos 0
#define NU_PININDEX_Msk (0xFFul << NU_PININDEX_Pos)
#define NU_PINPORT_Pos 8
#define NU_PINPORT_Msk (0xFul << NU_PINPORT_Pos)
#define NU_PIN_MODINDEX_Pos 12
#define NU_PIN_MODINDEX_Msk (0xFul << NU_PIN_MODINDEX_Pos)
#define NU_PIN_BIND_Pos 16
#define NU_PIN_BIND_Msk (0x1ul << NU_PIN_BIND_Pos)
#define NU_PININDEX(PINNAME) (((unsigned int)(PINNAME) & NU_PININDEX_Msk) >> NU_PININDEX_Pos)
#define NU_PINPORT(PINNAME) (((unsigned int)(PINNAME) & NU_PINPORT_Msk) >> NU_PINPORT_Pos)
#define NU_PIN_BIND(PINNAME) (((unsigned int)(PINNAME) & NU_PIN_BIND_Msk) >> NU_PIN_BIND_Pos)
#define NU_PIN_MODINDEX(PINNAME) (((unsigned int)(PINNAME) & NU_PIN_MODINDEX_Msk) >> NU_PIN_MODINDEX_Pos)
#define NU_PINNAME(PORT, PIN) ((((unsigned int) (PORT)) << (NU_PINPORT_Pos)) | (((unsigned int) (PIN)) << NU_PININDEX_Pos))
#define NU_PINNAME_BIND(PINNAME, modname) ((PinName) NU_PINNAME_BIND_(NU_PINPORT(PINNAME), NU_PININDEX(PINNAME), modname))
#define NU_PINNAME_BIND_(PORT, PIN, modname) ((((unsigned int)(PORT)) << NU_PINPORT_Pos) | (((unsigned int)(PIN)) << NU_PININDEX_Pos) | (NU_MODINDEX(modname) << NU_PIN_MODINDEX_Pos) | NU_PIN_BIND_Msk)
#define NU_PORT_BASE(PORT) ((GPIO_T *)(((uint32_t) GPIOA_BASE) + 0x40 * PORT))
#define NU_MFP_POS(PIN) ((PIN % 8) * 4)
#define NU_MFP_MSK(PIN) (0xful << NU_MFP_POS(PIN))
// LEGACY
#define NU_PINNAME_TO_PIN(PINNAME) NU_PININDEX(PINNAME)
#define NU_PINNAME_TO_PORT(PINNAME) NU_PINPORT(PINNAME)
#define NU_PINNAME_TO_MODSUBINDEX(PINNAME) NU_PIN_MODINDEX(PINNAME)
#define NU_PORT_N_PIN_TO_PINNAME(PORT, PIN) NU_PINNAME((PORT), (PIN))
typedef enum {
PIN_INPUT,
PIN_OUTPUT
} PinDirection;
typedef enum {
PullNone = 0,
PullDown,
PullUp,
PushPull,
OpenDrain,
Quasi,
PullDefault = PullUp,
} PinMode;
typedef enum {
// Not connected
NC = (int)0xFFFFFFFF,
// Generic naming
PA_0 = NU_PORT_N_PIN_TO_PINNAME(0, 0), PA_1, PA_2, PA_3, PA_4, PA_5, PA_6, PA_7, PA_8, PA_9, PA_10, PA_11, PA_12, PA_13, PA_14, PA_15,
PB_0 = NU_PORT_N_PIN_TO_PINNAME(1, 0), PB_1, PB_2, PB_3, PB_4, PB_5, PB_6, PB_7, PB_8, PB_9, PB_10, PB_11, PB_12, PB_13, PB_14, PB_15,
PC_0 = NU_PORT_N_PIN_TO_PINNAME(2, 0), PC_1, PC_2, PC_3, PC_4, PC_5, PC_6, PC_7, PC_8, PC_9, PC_10, PC_11, PC_12, PC_13, PC_14,
PD_0 = NU_PORT_N_PIN_TO_PINNAME(3, 0), PD_1, PD_2, PD_3, PD_4, PD_5, PD_6, PD_7, PD_8, PD_9, PD_10, PD_11, PD_12, PD_13, PD_14,
PE_0 = NU_PORT_N_PIN_TO_PINNAME(4, 0), PE_1, PE_2, PE_3, PE_4, PE_5, PE_6, PE_7, PE_8, PE_9, PE_10, PE_11, PE_12, PE_13, PE_14, PE_15,
PF_0 = NU_PORT_N_PIN_TO_PINNAME(5, 0), PF_1, PF_2, PF_3, PF_4, PF_5, PF_6, PF_7, PF_8, PF_9, PF_10, PF_11,
PG_0 = NU_PORT_N_PIN_TO_PINNAME(6, 0), PG_1, PG_2, PG_3, PG_4, PG_5, PG_6, PG_7, PG_8, PG_9, PG_10, PG_11, PG_12, PG_13, PG_14, PG_15,
PH_0 = NU_PORT_N_PIN_TO_PINNAME(7, 0), PH_1, PH_2, PH_3, PH_4, PH_5, PH_6, PH_7, PH_8, PH_9, PH_10, PH_11,
// Arduino UNO naming
A0 = PB_6,
A1 = PB_7,
A2 = PB_8,
A3 = PB_3,
A4 = PB_4,
A5 = PB_5,
D0 = PH_9,
D1 = PH_8,
D2 = PB_9,
D3 = PF_11,
D4 = PG_4,
D5 = PC_11,
D6 = PC_12,
D7 = PC_13,
D8 = PA_5,
D9 = PA_4,
D10 = PA_3,
D11 = PA_0,
D12 = PA_1,
D13 = PA_2,
D14 = PG_3,
D15 = PG_2,
// Note: board-specific
// UART naming
USBTX = PD_3,
USBRX = PD_2,
STDIO_UART_TX = USBTX,
STDIO_UART_RX = USBRX,
// LED naming
LED_RED = PH_0,
LED_YELLOW = PH_1,
LED_GREEN = PH_2,
LED1 = LED_RED,
LED2 = LED_YELLOW,
LED3 = LED_GREEN,
LED4 = LED1, // No real LED. Just for passing ATS.
// Button naming
SW2 = PC_10,
SW3 = PC_9,
} PinName;
#ifdef __cplusplus
}
#endif
#endif // MBED_PINNAMES_H

View File

@ -0,0 +1,38 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBED_PORTNAMES_H
#define MBED_PORTNAMES_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PortA = 0,
PortB = 1,
PortC = 2,
PortD = 3,
PortE = 4,
PortF = 5,
PortG = 6,
PortH = 7
} PortName;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,24 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBED_DEVICE_H
#define MBED_DEVICE_H
#define DEVICE_ID_LENGTH 24
#include "objects.h"
#endif

View File

@ -0,0 +1,72 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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.
*/
#include "analogin_api.h"
void mbed_sdk_init(void)
{
// NOTE: Support singleton semantics to be called from other init functions
static int inited = 0;
if (inited) {
return;
}
inited = 1;
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Unlock protected registers */
SYS_UnlockReg();
/* Enable HIRC clock (Internal RC 22.1184MHz) */
CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);
/* Enable HXT clock (external XTAL 12MHz) */
CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk);
/* Enable LIRC for lp_ticker */
CLK_EnableXtalRC(CLK_PWRCTL_LIRCEN_Msk);
/* Enable LXT for RTC */
CLK_EnableXtalRC(CLK_PWRCTL_LXTEN_Msk);
/* Wait for HIRC clock ready */
CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
/* Wait for HXT clock ready */
CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);
/* Wait for LIRC clock ready */
CLK_WaitClockReady(CLK_STATUS_LIRCSTB_Msk);
/* Wait for LXT clock ready */
CLK_WaitClockReady(CLK_STATUS_LXTSTB_Msk);
/* Select HCLK clock source as HIRC and HCLK clock divider as 1 */
CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));
/* Set core clock as 192000000 from PLL */
CLK_SetCoreClock(192000000);
/* Set PCLK0/PCLK1 to HCLK/2 */
CLK->PCLKDIV = (CLK_PCLKDIV_PCLK0DIV2 | CLK_PCLKDIV_PCLK1DIV2); // PCLK divider set 2
#if DEVICE_ANALOGIN
/* Vref connect to internal */
SYS->VREFCTL = (SYS->VREFCTL & ~SYS_VREFCTL_VREFCTL_Msk) | SYS_VREFCTL_VREF_3_0V;
#endif
/* Update System Core Clock */
/* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
SystemCoreClockUpdate();
/* Lock protected registers */
SYS_LockReg();
}

View File

@ -0,0 +1,139 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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 MBED_OBJECTS_H
#define MBED_OBJECTS_H
#include "cmsis.h"
#include "PortNames.h"
#include "PeripheralNames.h"
#include "PinNames.h"
#include "dma_api.h"
#ifdef __cplusplus
extern "C" {
#endif
struct gpio_irq_s {
//IRQn_Type irq_n;
//uint32_t irq_index;
//uint32_t event;
PinName pin;
uint32_t irq_handler;
uint32_t irq_id;
};
struct port_s {
PortName port;
uint32_t mask;
PinDirection direction;
};
struct analogin_s {
ADCName adc;
//PinName pin;
};
struct serial_s {
UARTName uart;
PinName pin_tx;
PinName pin_rx;
uint32_t baudrate;
uint32_t databits;
uint32_t parity;
uint32_t stopbits;
void (*vec)(void);
uint32_t irq_handler;
uint32_t irq_id;
uint32_t irq_en;
uint32_t inten_msk;
// Async transfer related fields
DMAUsage dma_usage_tx;
DMAUsage dma_usage_rx;
int dma_chn_id_tx;
int dma_chn_id_rx;
uint32_t event;
void (*irq_handler_tx_async)(void);
void (*irq_handler_rx_async)(void);
};
struct spi_s {
SPIName spi;
PinName pin_miso;
PinName pin_mosi;
PinName pin_sclk;
PinName pin_ssel;
//void (*vec)(void);
// Async transfer related fields
DMAUsage dma_usage;
int dma_chn_id_tx;
int dma_chn_id_rx;
uint32_t event;
//void (*irq_handler_tx_async)(void);
//void (*irq_handler_rx_async)(void);
};
struct i2c_s {
I2CName i2c;
//void (*vec)(void);
int slaveaddr_state;
uint32_t tran_ctrl;
char * tran_beg;
char * tran_pos;
char * tran_end;
int inten;
// Async transfer related fields
DMAUsage dma_usage;
uint32_t event;
int stop;
uint32_t address;
};
struct pwmout_s {
PWMName pwm;
//PinName pin;
uint32_t period_us;
uint32_t pulsewidth_us;
};
struct sleep_s {
int powerdown;
};
struct trng_s {
uint8_t dummy;
};
struct can_s {
CANName can;
int index;
};
#ifdef __cplusplus
}
#endif
#include "gpio_object.h"
#endif

View File

@ -0,0 +1,105 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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.
*/
#include "analogin_api.h"
#if DEVICE_ANALOGIN
#include "cmsis.h"
#include "pinmap.h"
#include "PeripheralPins.h"
#include "nu_modutil.h"
static uint32_t eadc_modinit_mask = 0;
static const struct nu_modinit_s adc_modinit_tab[] = {
{ADC_0_0, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_1, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_2, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_3, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_4, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_5, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_6, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_7, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_8, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_9, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_10, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_11, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_12, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_13, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_14, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
{ADC_0_15, EADC_MODULE, 0, CLK_CLKDIV0_EADC(8), EADC_RST, ADC0_IRQn, NULL},
};
void analogin_init(analogin_t *obj, PinName pin)
{
obj->adc = (ADCName) pinmap_peripheral(pin, PinMap_ADC);
MBED_ASSERT(obj->adc != (ADCName) NC);
const struct nu_modinit_s *modinit = get_modinit(obj->adc, adc_modinit_tab);
MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == (int) obj->adc);
EADC_T *eadc_base = (EADC_T *) NU_MODBASE(obj->adc);
// NOTE: All channels (identified by ADCName) share a ADC module. This reset will also affect other channels of the same ADC module.
if (! eadc_modinit_mask) {
// Reset this module if no channel enabled
SYS_ResetModule(modinit->rsetidx);
// Select clock source of paired channels
CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
// Enable clock of paired channels
CLK_EnableModuleClock(modinit->clkidx);
// Set the ADC internal sampling time, input mode as single-end and enable the A/D converter
EADC_Open(eadc_base, EADC_CTL_DIFFEN_SINGLE_END);
}
uint32_t chn = NU_MODSUBINDEX(obj->adc);
// Wire pinout
pinmap_pinout(pin, PinMap_ADC);
// Configure the sample module Nmod for analog input channel Nch and software trigger source
EADC_ConfigSampleModule(eadc_base, chn, EADC_SOFTWARE_TRIGGER, chn);
eadc_modinit_mask |= 1 << chn;
}
uint16_t analogin_read_u16(analogin_t *obj)
{
EADC_T *eadc_base = (EADC_T *) NU_MODBASE(obj->adc);
uint32_t chn = NU_MODSUBINDEX(obj->adc);
EADC_START_CONV(eadc_base, 1 << chn);
while (EADC_GET_DATA_VALID_FLAG(eadc_base, 1 << chn) != ((uint32_t) (1 << chn)));
uint16_t conv_res_12 = EADC_GET_CONV_DATA(eadc_base, chn);
// Just 12 bits are effective. Convert to 16 bits.
// conv_res_12: 0000 b11b10b9b8 b7b6b5b4 b3b2b1b0
// conv_res_16: b11b10b9b8 b7b6b5b4 b3b2b1b0 b11b10b9b8
uint16_t conv_res_16 = (conv_res_12 << 4) | (conv_res_12 >> 8);
return conv_res_16;
}
float analogin_read(analogin_t *obj)
{
uint16_t value = analogin_read_u16(obj);
return (float) value * (1.0f / (float) 0xFFFF);
}
#endif

View File

@ -0,0 +1,355 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed 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.
*/
#include "can_api.h"
#include "m480_gpio.h"
#include "m480_can.h"
#if DEVICE_CAN
#include <string.h>
#include "cmsis.h"
#include "pinmap.h"
#include "PeripheralPins.h"
#include "nu_modutil.h"
#include "nu_miscutil.h"
#include "nu_bitutil.h"
#include "mbed_critical.h"
#define NU_CAN_DEBUG 0
#define CAN_NUM 2
static uint32_t can_irq_ids[CAN_NUM] = {0};
static can_irq_handler can0_irq_handler;
static can_irq_handler can1_irq_handler;
extern uint32_t CAN_GetCANBitRate(CAN_T *tCAN);
extern void CAN_EnterInitMode(CAN_T *tCAN, uint8_t u8Mask);
extern void CAN_LeaveInitMode(CAN_T *tCAN);
extern void CAN_LeaveTestMode(CAN_T *tCAN);
extern void CAN_EnterTestMode(CAN_T *tCAN, uint8_t u8TestMask);
static const struct nu_modinit_s can_modinit_tab[] = {
{CAN_0, CAN0_MODULE, 0, 0, CAN0_RST, CAN0_IRQn, NULL},
{CAN_1, CAN1_MODULE, 0, 0, CAN1_RST, CAN1_IRQn, NULL},
{NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
};
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz)
{
uint32_t can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
uint32_t can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
obj->can = (CANName)pinmap_merge(can_td, can_rd);
MBED_ASSERT((int)obj->can != NC);
const struct nu_modinit_s *modinit = get_modinit(obj->can, can_modinit_tab);
MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == (int) obj->can);
// Reset this module
SYS_ResetModule(modinit->rsetidx);
NVIC_DisableIRQ(CAN0_IRQn);
NVIC_DisableIRQ(CAN1_IRQn);
// Enable IP clock
CLK_EnableModuleClock(modinit->clkidx);
if(obj->can == CAN_1) {
obj->index = 1;
} else
obj->index = 0;
pinmap_pinout(td, PinMap_CAN_TD);
pinmap_pinout(rd, PinMap_CAN_RD);
#if 0
/* TBD: For M487 mbed Board Transmitter Setting (RS Pin) */
GPIO_SetMode(PA, BIT2| BIT3, GPIO_MODE_OUTPUT);
PA2 = 0x00;
PA3 = 0x00;
#endif
CAN_Open((CAN_T *)NU_MODBASE(obj->can), hz, CAN_NORMAL_MODE);
can_filter(obj, 0, 0, CANStandard, 0);
}
void can_init(can_t *obj, PinName rd, PinName td)
{
can_init_freq(obj, rd, td, 500000);
}
void can_free(can_t *obj)
{
const struct nu_modinit_s *modinit = get_modinit(obj->can, can_modinit_tab);
MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == (int) obj->can);
// Reset this module
SYS_ResetModule(modinit->rsetidx);
CLK_DisableModuleClock(modinit->clkidx);
}
int can_frequency(can_t *obj, int hz)
{
CAN_SetBaudRate((CAN_T *)NU_MODBASE(obj->can), hz);
return CAN_GetCANBitRate((CAN_T *)NU_MODBASE(obj->can));
}
static void can_irq(CANName name, int id)
{
CAN_T *can = (CAN_T *)NU_MODBASE(name);
uint32_t u8IIDRstatus;
u8IIDRstatus = can->IIDR;
if(u8IIDRstatus == 0x00008000) { /* Check Status Interrupt Flag (Error status Int and Status change Int) */
/**************************/
/* Status Change interrupt*/
/**************************/
if(can->STATUS & CAN_STATUS_RXOK_Msk) {
can->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/
if(id)
can1_irq_handler(can_irq_ids[id], IRQ_RX);
else
can0_irq_handler(can_irq_ids[id], IRQ_RX);
}
if(can->STATUS & CAN_STATUS_TXOK_Msk) {
can->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/
if(id)
can1_irq_handler(can_irq_ids[id], IRQ_TX);
else
can0_irq_handler(can_irq_ids[id], IRQ_TX);
}
/**************************/
/* Error Status interrupt */
/**************************/
if(can->STATUS & CAN_STATUS_EWARN_Msk) {
if(id)
can1_irq_handler(can_irq_ids[id], IRQ_ERROR);
else
can0_irq_handler(can_irq_ids[id], IRQ_ERROR);
}
if(can->STATUS & CAN_STATUS_BOFF_Msk) {
if(id)
can1_irq_handler(can_irq_ids[id], IRQ_BUS);
else
can0_irq_handler(can_irq_ids[id], IRQ_BUS);
}
} else if (u8IIDRstatus!=0) {
if(id)
can1_irq_handler(can_irq_ids[id], IRQ_OVERRUN);
else
can0_irq_handler(can_irq_ids[id], IRQ_OVERRUN);
CAN_CLR_INT_PENDING_BIT(can, ((can->IIDR) -1)); /* Clear Interrupt Pending */
} else if(can->WU_STATUS == 1) {
can->WU_STATUS = 0; /* Write '0' to clear */
if(id)
can1_irq_handler(can_irq_ids[id], IRQ_WAKEUP);
else
can0_irq_handler(can_irq_ids[id], IRQ_WAKEUP);
}
}
void CAN0_IRQHandler(void)
{
can_irq(CAN_0, 0);
}
void CAN1_IRQHandler(void)
{
can_irq(CAN_1, 1);
}
void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id)
{
if(obj->index)
can1_irq_handler = handler;
else
can0_irq_handler = handler;
can_irq_ids[obj->index] = id;
}
void can_irq_free(can_t *obj)
{
CAN_DisableInt((CAN_T *)NU_MODBASE(obj->can), (CAN_CON_IE_Msk|CAN_CON_SIE_Msk|CAN_CON_EIE_Msk));
can_irq_ids[obj->index] = 0;
if(!obj->index)
NVIC_DisableIRQ(CAN0_IRQn);
else
NVIC_DisableIRQ(CAN1_IRQn);
}
void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable)
{
uint8_t u8Mask;
u8Mask = ((enable != 0 )? CAN_CON_IE_Msk :0);
switch (irq) {
case IRQ_ERROR:
case IRQ_BUS:
case IRQ_PASSIVE:
u8Mask = u8Mask | CAN_CON_EIE_Msk | CAN_CON_SIE_Msk;
break;
case IRQ_RX:
case IRQ_TX:
case IRQ_OVERRUN:
case IRQ_WAKEUP:
u8Mask = u8Mask | CAN_CON_SIE_Msk;
break;
default:
break;
}
CAN_EnterInitMode((CAN_T*)NU_MODBASE(obj->can), u8Mask);
CAN_LeaveInitMode((CAN_T*)NU_MODBASE(obj->can));
if(!obj->index) {
NVIC_SetVector(CAN0_IRQn, (uint32_t)&CAN0_IRQHandler);
NVIC_EnableIRQ(CAN0_IRQn);
} else {
NVIC_SetVector(CAN1_IRQn, (uint32_t)&CAN1_IRQHandler);
NVIC_EnableIRQ(CAN1_IRQn);
}
}
int can_write(can_t *obj, CAN_Message msg, int cc)
{
STR_CANMSG_T CMsg;
CMsg.IdType = (uint32_t)msg.format;
CMsg.FrameType = (uint32_t)!msg.type;
CMsg.Id = msg.id;
CMsg.DLC = msg.len;
memcpy((void *)&CMsg.Data[0],(const void *)&msg.data[0], (unsigned int)8);
return CAN_Transmit((CAN_T *)(NU_MODBASE(obj->can)), cc, &CMsg);
}
int can_read(can_t *obj, CAN_Message *msg, int handle)
{
STR_CANMSG_T CMsg;
if(!CAN_Receive((CAN_T *)(NU_MODBASE(obj->can)), handle, &CMsg))
return 0;
msg->format = (CANFormat)CMsg.IdType;
msg->type = (CANType)!CMsg.FrameType;
msg->id = CMsg.Id;
msg->len = CMsg.DLC;
memcpy(&msg->data[0], &CMsg.Data[0], 8);
return 1;
}
int can_mode(can_t *obj, CanMode mode)
{
int success = 0;
switch (mode) {
case MODE_RESET:
CAN_LeaveTestMode((CAN_T*)NU_MODBASE(obj->can));
success = 1;
break;
case MODE_NORMAL:
CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_BASIC_Msk);
success = 1;
break;
case MODE_SILENT:
CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_SILENT_Msk);
success = 1;
break;
case MODE_TEST_LOCAL:
case MODE_TEST_GLOBAL:
CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_LBACK_Msk);
success = 1;
break;
case MODE_TEST_SILENT:
CAN_EnterTestMode((CAN_T*)NU_MODBASE(obj->can), CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk);
success = 1;
break;
default:
success = 0;
break;
}
return success;
}
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle)
{
return CAN_SetRxMsg((CAN_T *)NU_MODBASE(obj->can), handle, (uint32_t)format, id);
}
void can_reset(can_t *obj)
{
const struct nu_modinit_s *modinit = get_modinit(obj->can, can_modinit_tab);
MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == (int) obj->can);
// Reset this module
SYS_ResetModule(modinit->rsetidx);
}
unsigned char can_rderror(can_t *obj)
{
CAN_T *can = (CAN_T *)NU_MODBASE(obj->can);
return ((can->ERR>>8)&0xFF);
}
unsigned char can_tderror(can_t *obj)
{
CAN_T *can = (CAN_T *)NU_MODBASE(obj->can);
return ((can->ERR)&0xFF);
}
void can_monitor(can_t *obj, int silent)
{
CAN_EnterTestMode((CAN_T *)NU_MODBASE(obj->can), CAN_TEST_SILENT_Msk);
}
#endif // DEVICE_CAN

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
/**************************************************************************//**
* @file acmp.c
* @version V1.00
* @brief M480 series Analog Comparator(ACMP) driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_ACMP_Driver ACMP Driver
@{
*/
/** @addtogroup M480_ACMP_EXPORTED_FUNCTIONS ACMP Exported Functions
@{
*/
/**
* @brief Configure the specified ACMP module
*
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum Comparator number.
* @param[in] u32NegSrc Comparator negative input selection. Including:
* - \ref ACMP_CTL_NEGSEL_PIN
* - \ref ACMP_CTL_NEGSEL_CRV
* - \ref ACMP_CTL_NEGSEL_VBG
* - \ref ACMP_CTL_NEGSEL_DAC
* @param[in] u32HysSel The hysteresis function option. Including:
* - \ref ACMP_CTL_HYSTERESIS_30MV
* - \ref ACMP_CTL_HYSTERESIS_20MV
* - \ref ACMP_CTL_HYSTERESIS_10MV
* - \ref ACMP_CTL_HYSTERESIS_DISABLE
*
* @return None
*
* @details Configure hysteresis function, select the source of negative input and enable analog comparator.
*/
void ACMP_Open(ACMP_T *acmp, uint32_t u32ChNum, uint32_t u32NegSrc, uint32_t u32HysSel)
{
acmp->CTL[u32ChNum] = (acmp->CTL[u32ChNum] & (~(ACMP_CTL_NEGSEL_Msk | ACMP_CTL_HYSSEL_Msk))) | (u32NegSrc | u32HysSel | ACMP_CTL_ACMPEN_Msk);
}
/**
* @brief Close analog comparator
*
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum Comparator number.
*
* @return None
*
* @details This function will clear ACMPEN bit of ACMP_CTL register to disable analog comparator.
*/
void ACMP_Close(ACMP_T *acmp, uint32_t u32ChNum)
{
acmp->CTL[u32ChNum] &= (~ACMP_CTL_ACMPEN_Msk);
}
/*@}*/ /* end of group M480_ACMP_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_ACMP_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,414 @@
/**************************************************************************//**
* @file ACMP.h
* @version V1.00
* @brief M480 Series ACMP Driver Header File
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#ifndef __ACMP_H__
#define __ACMP_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_ACMP_Driver ACMP Driver
@{
*/
/** @addtogroup M480_ACMP_EXPORTED_CONSTANTS ACMP Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* ACMP_CTL constant definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define ACMP_CTL_FILTSEL_OFF (0UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for filter function disabled. \hideinitializer */
#define ACMP_CTL_FILTSEL_1PCLK (1UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 1 PCLK filter count. \hideinitializer */
#define ACMP_CTL_FILTSEL_2PCLK (2UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 2 PCLK filter count. \hideinitializer */
#define ACMP_CTL_FILTSEL_4PCLK (3UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 4 PCLK filter count. \hideinitializer */
#define ACMP_CTL_FILTSEL_8PCLK (4UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 8 PCLK filter count. \hideinitializer */
#define ACMP_CTL_FILTSEL_16PCLK (5UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 16 PCLK filter count. \hideinitializer */
#define ACMP_CTL_FILTSEL_32PCLK (6UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 32 PCLK filter count. \hideinitializer */
#define ACMP_CTL_FILTSEL_64PCLK (7UL << ACMP_CTL_FILTSEL_Pos) /*!< ACMP_CTL setting for 64 PCLK filter count. \hideinitializer */
#define ACMP_CTL_INTPOL_RF (0UL << ACMP_CTL_INTPOL_Pos) /*!< ACMP_CTL setting for selecting rising edge and falling edge as interrupt condition. \hideinitializer */
#define ACMP_CTL_INTPOL_R (1UL << ACMP_CTL_INTPOL_Pos) /*!< ACMP_CTL setting for selecting rising edge as interrupt condition. \hideinitializer */
#define ACMP_CTL_INTPOL_F (2UL << ACMP_CTL_INTPOL_Pos) /*!< ACMP_CTL setting for selecting falling edge as interrupt condition. \hideinitializer */
#define ACMP_CTL_POSSEL_P0 (0UL << ACMP_CTL_POSSEL_Pos) /*!< ACMP_CTL setting for selecting ACMPx_P0 pin as the source of ACMP V+. \hideinitializer */
#define ACMP_CTL_POSSEL_P1 (1UL << ACMP_CTL_POSSEL_Pos) /*!< ACMP_CTL setting for selecting ACMPx_P1 pin as the source of ACMP V+. \hideinitializer */
#define ACMP_CTL_POSSEL_P2 (2UL << ACMP_CTL_POSSEL_Pos) /*!< ACMP_CTL setting for selecting ACMPx_P2 pin as the source of ACMP V+. \hideinitializer */
#define ACMP_CTL_POSSEL_P3 (3UL << ACMP_CTL_POSSEL_Pos) /*!< ACMP_CTL setting for selecting ACMPx_P3 pin as the source of ACMP V+. \hideinitializer */
#define ACMP_CTL_NEGSEL_PIN (0UL << ACMP_CTL_NEGSEL_Pos) /*!< ACMP_CTL setting for selecting the voltage of ACMP negative input pin as the source of ACMP V-. \hideinitializer */
#define ACMP_CTL_NEGSEL_CRV (1UL << ACMP_CTL_NEGSEL_Pos) /*!< ACMP_CTL setting for selecting internal comparator reference voltage as the source of ACMP V-. \hideinitializer */
#define ACMP_CTL_NEGSEL_VBG (2UL << ACMP_CTL_NEGSEL_Pos) /*!< ACMP_CTL setting for selecting internal Band-gap voltage as the source of ACMP V-. \hideinitializer */
#define ACMP_CTL_NEGSEL_DAC (3UL << ACMP_CTL_NEGSEL_Pos) /*!< ACMP_CTL setting for selecting DAC output voltage as the source of ACMP V-. \hideinitializer */
#define ACMP_CTL_HYSTERESIS_30MV (3UL << ACMP_CTL_HYSSEL_Pos) /*!< ACMP_CTL setting for enabling the hysteresis function at 30mV. \hideinitializer */
#define ACMP_CTL_HYSTERESIS_20MV (2UL << ACMP_CTL_HYSSEL_Pos) /*!< ACMP_CTL setting for enabling the hysteresis function at 20mV. \hideinitializer */
#define ACMP_CTL_HYSTERESIS_10MV (1UL << ACMP_CTL_HYSSEL_Pos) /*!< ACMP_CTL setting for enabling the hysteresis function at 10mV. \hideinitializer */
#define ACMP_CTL_HYSTERESIS_DISABLE (0UL << ACMP_CTL_HYSSEL_Pos) /*!< ACMP_CTL setting for disabling the hysteresis function. \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* ACMP_VREF constant definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define ACMP_VREF_CRVSSEL_VDDA (0UL << ACMP_VREF_CRVSSEL_Pos) /*!< ACMP_VREF setting for selecting analog supply voltage VDDA as the CRV source voltage \hideinitializer */
#define ACMP_VREF_CRVSSEL_INTVREF (1UL << ACMP_VREF_CRVSSEL_Pos) /*!< ACMP_VREF setting for selecting internal reference voltage as the CRV source voltage \hideinitializer */
/*@}*/ /* end of group M480_ACMP_EXPORTED_CONSTANTS */
/** @addtogroup M480_ACMP_EXPORTED_FUNCTIONS ACMP Exported Functions
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* Define Macros and functions */
/*---------------------------------------------------------------------------------------------------------*/
/**
* @brief This macro is used to enable output inverse function
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will set ACMPOINV bit of ACMP_CTL register to enable output inverse function.
* \hideinitializer
*/
#define ACMP_ENABLE_OUTPUT_INVERSE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_ACMPOINV_Msk)
/**
* @brief This macro is used to disable output inverse function
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will clear ACMPOINV bit of ACMP_CTL register to disable output inverse function.
* \hideinitializer
*/
#define ACMP_DISABLE_OUTPUT_INVERSE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_ACMPOINV_Msk)
/**
* @brief This macro is used to select ACMP negative input source
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @param[in] u32Src is comparator negative input selection. Including:
* - \ref ACMP_CTL_NEGSEL_PIN
* - \ref ACMP_CTL_NEGSEL_CRV
* - \ref ACMP_CTL_NEGSEL_VBG
* - \ref ACMP_CTL_NEGSEL_DAC
* @return None
* @details This macro will set NEGSEL (ACMP_CTL[5:4]) to determine the source of negative input.
* \hideinitializer
*/
#define ACMP_SET_NEG_SRC(acmp, u32ChNum, u32Src) ((acmp)->CTL[(u32ChNum)] = ((acmp)->CTL[(u32ChNum)] & ~ACMP_CTL_NEGSEL_Msk) | (u32Src))
/**
* @brief This macro is used to enable hysteresis function and set hysteresis to 30mV
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* \hideinitializer
*/
#define ACMP_ENABLE_HYSTERESIS(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_HYSTERESIS_30MV)
/**
* @brief This macro is used to disable hysteresis function
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will clear HYSEL bits of ACMP_CTL register to disable hysteresis function.
* \hideinitializer
*/
#define ACMP_DISABLE_HYSTERESIS(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_HYSSEL_Msk)
/**
* @brief This macro is used to select hysteresis level
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @param[in] u32HysSel The hysteresis function option. Including:
* - \ref ACMP_CTL_HYSTERESIS_30MV
* - \ref ACMP_CTL_HYSTERESIS_20MV
* - \ref ACMP_CTL_HYSTERESIS_10MV
* - \ref ACMP_CTL_HYSTERESIS_DISABLE
* \hideinitializer
* @return None
*/
#define ACMP_CONFIG_HYSTERESIS(acmp, u32ChNum, u32HysSel) ((acmp)->CTL[(u32ChNum)] = ((acmp)->CTL[(u32ChNum)] & ~ACMP_CTL_HYSSEL_Msk) | (u32HysSel))
/**
* @brief This macro is used to enable interrupt
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will set ACMPIE bit of ACMP_CTL register to enable interrupt function.
* If wake-up function is enabled, the wake-up interrupt will be enabled as well.
* \hideinitializer
*/
#define ACMP_ENABLE_INT(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_ACMPIE_Msk)
/**
* @brief This macro is used to disable interrupt
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will clear ACMPIE bit of ACMP_CTL register to disable interrupt function.
* \hideinitializer
*/
#define ACMP_DISABLE_INT(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_ACMPIE_Msk)
/**
* @brief This macro is used to enable ACMP
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will set ACMPEN bit of ACMP_CTL register to enable analog comparator.
* \hideinitializer
*/
#define ACMP_ENABLE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_ACMPEN_Msk)
/**
* @brief This macro is used to disable ACMP
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will clear ACMPEN bit of ACMP_CTL register to disable analog comparator.
* \hideinitializer
*/
#define ACMP_DISABLE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_ACMPEN_Msk)
/**
* @brief This macro is used to get ACMP output value
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return ACMP output value
* @details This macro will return the ACMP output value.
* \hideinitializer
*/
#define ACMP_GET_OUTPUT(acmp, u32ChNum) (((acmp)->STATUS & (ACMP_STATUS_ACMPO0_Msk<<((u32ChNum))))?1:0)
/**
* @brief This macro is used to get ACMP interrupt flag
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return ACMP interrupt occurred (1) or not (0)
* @details This macro will return the ACMP interrupt flag.
* \hideinitializer
*/
#define ACMP_GET_INT_FLAG(acmp, u32ChNum) (((acmp)->STATUS & (ACMP_STATUS_ACMPIF0_Msk<<((u32ChNum))))?1:0)
/**
* @brief This macro is used to clear ACMP interrupt flag
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will write 1 to ACMPIFn bit of ACMP_STATUS register to clear interrupt flag.
* \hideinitializer
*/
#define ACMP_CLR_INT_FLAG(acmp, u32ChNum) ((acmp)->STATUS = (ACMP_STATUS_ACMPIF0_Msk<<((u32ChNum))))
/**
* @brief This macro is used to clear ACMP wake-up interrupt flag
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will write 1 to WKIFn bit of ACMP_STATUS register to clear interrupt flag.
* \hideinitializer
*/
#define ACMP_CLR_WAKEUP_INT_FLAG(acmp, u32ChNum) ((acmp)->STATUS = (ACMP_STATUS_WKIF0_Msk<<((u32ChNum))))
/**
* @brief This macro is used to enable ACMP wake-up function
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will set WKEN (ACMP_CTL[16]) to enable ACMP wake-up function.
* \hideinitializer
*/
#define ACMP_ENABLE_WAKEUP(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_WKEN_Msk)
/**
* @brief This macro is used to disable ACMP wake-up function
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will clear WKEN (ACMP_CTL[16]) to disable ACMP wake-up function.
* \hideinitializer
*/
#define ACMP_DISABLE_WAKEUP(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_WKEN_Msk)
/**
* @brief This macro is used to select ACMP positive input pin
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @param[in] u32Pin Comparator positive pin selection. Including:
* - \ref ACMP_CTL_POSSEL_P0
* - \ref ACMP_CTL_POSSEL_P1
* - \ref ACMP_CTL_POSSEL_P2
* - \ref ACMP_CTL_POSSEL_P3
* @return None
* @details This macro will set POSSEL (ACMP_CTL[7:6]) to determine the comparator positive input pin.
* \hideinitializer
*/
#define ACMP_SELECT_P(acmp, u32ChNum, u32Pin) ((acmp)->CTL[(u32ChNum)] = ((acmp)->CTL[(u32ChNum)] & ~ACMP_CTL_POSSEL_Msk) | (u32Pin))
/**
* @brief This macro is used to enable ACMP filter function
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will set OUTSEL (ACMP_CTL[12]) to enable output filter function.
* \hideinitializer
*/
#define ACMP_ENABLE_FILTER(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_OUTSEL_Msk)
/**
* @brief This macro is used to disable ACMP filter function
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will clear OUTSEL (ACMP_CTL[12]) to disable output filter function.
* \hideinitializer
*/
#define ACMP_DISABLE_FILTER(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_OUTSEL_Msk)
/**
* @brief This macro is used to set ACMP filter function
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @param[in] u32Cnt is comparator filter count setting.
* - \ref ACMP_CTL_FILTSEL_OFF
* - \ref ACMP_CTL_FILTSEL_1PCLK
* - \ref ACMP_CTL_FILTSEL_2PCLK
* - \ref ACMP_CTL_FILTSEL_4PCLK
* - \ref ACMP_CTL_FILTSEL_8PCLK
* - \ref ACMP_CTL_FILTSEL_16PCLK
* - \ref ACMP_CTL_FILTSEL_32PCLK
* - \ref ACMP_CTL_FILTSEL_64PCLK
* @return None
* @details When ACMP output filter function is enabled, the output sampling count is determined by FILTSEL (ACMP_CTL[15:13]).
* \hideinitializer
*/
#define ACMP_SET_FILTER(acmp, u32ChNum, u32Cnt) ((acmp)->CTL[(u32ChNum)] = ((acmp)->CTL[(u32ChNum)] & ~ACMP_CTL_FILTSEL_Msk) | (u32Cnt))
/**
* @brief This macro is used to select comparator reference voltage
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32Level The comparator reference voltage setting.
* The formula is:
* comparator reference voltage = CRV source voltage x (1/6 + u32Level/24)
* The range of u32Level is 0 ~ 15.
* @return None
* @details When CRV is selected as ACMP negative input source, the CRV level is determined by CRVCTL (ACMP_VREF[3:0]).
* \hideinitializer
*/
#define ACMP_CRV_SEL(acmp, u32Level) ((acmp)->VREF = ((acmp)->VREF & ~ACMP_VREF_CRVCTL_Msk) | ((u32Level)<<ACMP_VREF_CRVCTL_Pos))
/**
* @brief This macro is used to select the source of CRV
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32Src is the source of CRV. Including:
* - \ref ACMP_VREF_CRVSSEL_VDDA
* - \ref ACMP_VREF_CRVSSEL_INTVREF
* @return None
* @details The source of CRV can be VDDA or internal reference voltage. The internal reference voltage level is determined by SYS_VREFCTL register.
* \hideinitializer
*/
#define ACMP_SELECT_CRV_SRC(acmp, u32Src) ((acmp)->VREF = ((acmp)->VREF & ~ACMP_VREF_CRVSSEL_Msk) | (u32Src))
/**
* @brief This macro is used to select ACMP interrupt condition
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @param[in] u32Cond Comparator interrupt condition selection. Including:
* - \ref ACMP_CTL_INTPOL_RF
* - \ref ACMP_CTL_INTPOL_R
* - \ref ACMP_CTL_INTPOL_F
* @return None
* @details The ACMP output interrupt condition can be rising edge, falling edge or any edge.
* \hideinitializer
*/
#define ACMP_SELECT_INT_COND(acmp, u32ChNum, u32Cond) ((acmp)->CTL[(u32ChNum)] = ((acmp)->CTL[(u32ChNum)] & ~ACMP_CTL_INTPOL_Msk) | (u32Cond))
/**
* @brief This macro is used to enable ACMP window latch mode
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will set WLATEN (ACMP_CTL[17]) to enable ACMP window latch mode.
* When ACMP0/1_WLAT pin is at high level, ACMPO0/1 passes through window latch
* block; when ACMP0/1_WLAT pin is at low level, the output of window latch block,
* WLATOUT, is frozen.
* \hideinitializer
*/
#define ACMP_ENABLE_WINDOW_LATCH(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_WLATEN_Msk)
/**
* @brief This macro is used to disable ACMP window latch mode
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will clear WLATEN (ACMP_CTL[17]) to disable ACMP window latch mode.
* \hideinitializer
*/
#define ACMP_DISABLE_WINDOW_LATCH(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_WLATEN_Msk)
/**
* @brief This macro is used to enable ACMP window compare mode
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will set WCMPSEL (ACMP_CTL[18]) to enable ACMP window compare mode.
* When window compare mode is enabled, user can connect the specific analog voltage
* source to either the positive inputs of both comparators or the negative inputs of
* both comparators. The upper bound and lower bound of the designated range are
* determined by the voltages applied to the other inputs of both comparators. If the
* output of a comparator is low and the other comparator outputs high, which means two
* comparators implies the upper and lower bound. User can directly monitor a specific
* analog voltage source via ACMPWO (ACMP_STATUS[16]).
* \hideinitializer
*/
#define ACMP_ENABLE_WINDOW_COMPARE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] |= ACMP_CTL_WCMPSEL_Msk)
/**
* @brief This macro is used to disable ACMP window compare mode
* @param[in] acmp The pointer of the specified ACMP module
* @param[in] u32ChNum The ACMP number
* @return None
* @details This macro will clear WCMPSEL (ACMP_CTL[18]) to disable ACMP window compare mode.
* \hideinitializer
*/
#define ACMP_DISABLE_WINDOW_COMPARE(acmp, u32ChNum) ((acmp)->CTL[(u32ChNum)] &= ~ACMP_CTL_WCMPSEL_Msk)
/* Function prototype declaration */
void ACMP_Open(ACMP_T *acmp, uint32_t u32ChNum, uint32_t u32NegSrc, uint32_t u32HysSel);
void ACMP_Close(ACMP_T *acmp, uint32_t u32ChNum);
/*@}*/ /* end of group M480_ACMP_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_ACMP_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __ACMP_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,703 @@
/**************************************************************************//**
* @file bpwm.c
* @version V1.00
* @brief M480 series BPWM driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_BPWM_Driver BPWM Driver
@{
*/
/** @addtogroup M480_BPWM_EXPORTED_FUNCTIONS BPWM Exported Functions
@{
*/
/**
* @brief Configure BPWM capture and get the nearest unit time.
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @param[in] u32UnitTimeNsec The unit time of counter
* @param[in] u32CaptureEdge The condition to latch the counter. This parameter is not used
* @return The nearest unit time in nano second.
* @details This function is used to Configure BPWM capture and get the nearest unit time.
*/
uint32_t BPWM_ConfigCaptureChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32UnitTimeNsec, uint32_t u32CaptureEdge)
{
uint32_t u32Src;
uint32_t u32PWMClockSrc;
uint32_t u32NearestUnitTimeNsec;
uint16_t u16Prescale = 1U, u16CNR = 0xFFFFU;
if(bpwm == BPWM0) {
u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM0SEL_Msk;
} else { /* (bpwm == BPWM1) */
u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM1SEL_Msk;
}
if(u32Src == 0U) {
/* clock source is from PLL clock */
u32PWMClockSrc = CLK_GetPLLClockFreq();
} else {
/* clock source is from PCLK */
SystemCoreClockUpdate();
if(bpwm == BPWM0) {
u32PWMClockSrc = CLK_GetPCLK0Freq();
} else {/* (bpwm == BPWM1) */
u32PWMClockSrc = CLK_GetPCLK1Freq();
}
}
u32PWMClockSrc /= 1000UL;
for(u16Prescale = 1U; u16Prescale <= 0x1000U; u16Prescale++) {
uint32_t u32Exit = 0U;
u32NearestUnitTimeNsec = (1000000UL * u16Prescale) / u32PWMClockSrc;
if(u32NearestUnitTimeNsec < u32UnitTimeNsec) {
if (u16Prescale == 0x1000U) { /* limit to the maximum unit time(nano second) */
u32Exit = 1U;
} else {
u32Exit = 0U;
}
if (!(1000000UL * (u16Prescale + 1UL) > (u32NearestUnitTimeNsec * u32PWMClockSrc))) {
u32Exit = 1U;
} else {
u32Exit = 0U;
}
} else {
u32Exit = 1U;
}
if (u32Exit == 1U) {
break;
} else {}
}
/* convert to real register value */
/* all channels share a prescaler */
u16Prescale -= 1U;
BPWM_SET_PRESCALER(bpwm, u32ChannelNum, u16Prescale);
/* set BPWM to down count type(edge aligned) */
(bpwm)->CTL1 = (1UL);
BPWM_SET_CNR(bpwm, u32ChannelNum, u16CNR);
return (u32NearestUnitTimeNsec);
}
/**
* @brief This function Configure BPWM generator and get the nearest frequency in edge aligned auto-reload mode
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @param[in] u32Frequency Target generator frequency
* @param[in] u32DutyCycle Target generator duty cycle percentage. Valid range are between 0 ~ 100. 10 means 10%, 20 means 20%...
* @return Nearest frequency clock in nano second
* @note Since all channels shares a prescaler. Call this API to configure BPWM frequency may affect
* existing frequency of other channel.
*/
uint32_t BPWM_ConfigOutputChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Frequency, uint32_t u32DutyCycle)
{
uint32_t u32Src;
uint32_t u32PWMClockSrc;
uint32_t i;
uint32_t u32Prescale = 1U, u32CNR = 0xFFFFU;
if(bpwm == BPWM0) {
u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM0SEL_Msk;
} else { /* (bpwm == BPWM1) */
u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM1SEL_Msk;
}
if(u32Src == 0U) {
/* clock source is from PLL clock */
u32PWMClockSrc = CLK_GetPLLClockFreq();
} else {
/* clock source is from PCLK */
SystemCoreClockUpdate();
if(bpwm == BPWM0) {
u32PWMClockSrc = CLK_GetPCLK0Freq();
} else { /* (bpwm == BPWM1) */
u32PWMClockSrc = CLK_GetPCLK1Freq();
}
}
for(u32Prescale = 1U; u32Prescale < 0xFFFU; u32Prescale++) { /* prescale could be 0~0xFFF */
i = (u32PWMClockSrc / u32Frequency) / u32Prescale;
/* If target value is larger than CNR, need to use a larger prescaler */
if(i < (0x10000U)) {
u32CNR = i;
break;
}
}
/* Store return value here 'cos we're gonna change u16Prescale & u16CNR to the real value to fill into register */
i = u32PWMClockSrc / (u32Prescale * u32CNR);
/* convert to real register value */
/* all channels share a prescaler */
u32Prescale -= 1U;
BPWM_SET_PRESCALER(bpwm, u32ChannelNum, u32Prescale);
/* set BPWM to down count type(edge aligned) */
(bpwm)->CTL1 = (1UL);
u32CNR -= 1U;
BPWM_SET_CNR(bpwm, u32ChannelNum, u32CNR);
if(u32DutyCycle) {
BPWM_SET_CMR(bpwm, u32ChannelNum, u32DutyCycle * (u32CNR + 1UL) / 100UL - 1UL);
(bpwm)->WGCTL0 &= ~((BPWM_WGCTL0_PRDPCTLn_Msk | BPWM_WGCTL0_ZPCTLn_Msk) << (u32ChannelNum * 2U));
(bpwm)->WGCTL0 |= (BPWM_OUTPUT_LOW << ((u32ChannelNum * (2U)) + (uint32_t)BPWM_WGCTL0_PRDPCTLn_Pos));
(bpwm)->WGCTL1 &= ~((BPWM_WGCTL1_CMPDCTLn_Msk | BPWM_WGCTL1_CMPUCTLn_Msk) << (u32ChannelNum * 2U));
(bpwm)->WGCTL1 |= (BPWM_OUTPUT_HIGH << (u32ChannelNum * (2U) + (uint32_t)BPWM_WGCTL1_CMPDCTLn_Pos));
} else {
BPWM_SET_CMR(bpwm, u32ChannelNum, 0U);
(bpwm)->WGCTL0 &= ~((BPWM_WGCTL0_PRDPCTLn_Msk | BPWM_WGCTL0_ZPCTLn_Msk) << (u32ChannelNum * 2U));
(bpwm)->WGCTL0 |= (BPWM_OUTPUT_LOW << (u32ChannelNum * 2U + (uint32_t)BPWM_WGCTL0_ZPCTLn_Pos));
(bpwm)->WGCTL1 &= ~((BPWM_WGCTL1_CMPDCTLn_Msk | BPWM_WGCTL1_CMPUCTLn_Msk) << (u32ChannelNum * 2U));
(bpwm)->WGCTL1 |= (BPWM_OUTPUT_HIGH << (u32ChannelNum * 2U + (uint32_t)BPWM_WGCTL1_CMPDCTLn_Pos));
}
return(i);
}
/**
* @brief Start BPWM module
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used.
* @return None
* @details This function is used to start BPWM module.
* @note All channels share one counter.
*/
void BPWM_Start(BPWM_T *bpwm, uint32_t u32ChannelMask)
{
(bpwm)->CNTEN = BPWM_CNTEN_CNTEN0_Msk;
}
/**
* @brief Stop BPWM module
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used.
* @return None
* @details This function is used to stop BPWM module.
* @note All channels share one period.
*/
void BPWM_Stop(BPWM_T *bpwm, uint32_t u32ChannelMask)
{
(bpwm)->PERIOD = 0U;
}
/**
* @brief Stop BPWM generation immediately by clear channel enable bit
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used.
* @return None
* @details This function is used to stop BPWM generation immediately by clear channel enable bit.
* @note All channels share one counter.
*/
void BPWM_ForceStop(BPWM_T *bpwm, uint32_t u32ChannelMask)
{
(bpwm)->CNTEN &= ~BPWM_CNTEN_CNTEN0_Msk;
}
/**
* @brief Enable selected channel to trigger EADC
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @param[in] u32Condition The condition to trigger EADC. Combination of following conditions:
* - \ref BPWM_TRIGGER_EADC_EVEN_ZERO_POINT
* - \ref BPWM_TRIGGER_EADC_EVEN_PERIOD_POINT
* - \ref BPWM_TRIGGER_EADC_EVEN_ZERO_OR_PERIOD_POINT
* - \ref BPWM_TRIGGER_EADC_EVEN_CMP_UP_COUNT_POINT
* - \ref BPWM_TRIGGER_EADC_EVEN_CMP_DOWN_COUNT_POINT
* - \ref BPWM_TRIGGER_EADC_ODD_CMP_UP_COUNT_POINT
* - \ref BPWM_TRIGGER_EADC_ODD_CMP_DOWN_COUNT_POINT
* @return None
* @details This function is used to enable selected channel to trigger EADC
*/
void BPWM_EnableEADCTrigger(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Condition)
{
if(u32ChannelNum < 4U) {
(bpwm)->EADCTS0 &= ~((BPWM_EADCTS0_TRGSEL0_Msk) << (u32ChannelNum * 8U));
(bpwm)->EADCTS0 |= ((BPWM_EADCTS0_TRGEN0_Msk | u32Condition) << (u32ChannelNum * 8U));
} else {
(bpwm)->EADCTS1 &= ~((BPWM_EADCTS1_TRGSEL4_Msk) << ((u32ChannelNum - 4U) * 8U));
(bpwm)->EADCTS1 |= ((BPWM_EADCTS1_TRGEN4_Msk | u32Condition) << ((u32ChannelNum - 4U) * 8U));
}
}
/**
* @brief Disable selected channel to trigger EADC
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~3
* @return None
* @details This function is used to disable selected channel to trigger EADC
*/
void BPWM_DisableEADCTrigger(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
if(u32ChannelNum < 4U) {
(bpwm)->EADCTS0 &= ~(BPWM_EADCTS0_TRGEN0_Msk << (u32ChannelNum * 8U));
} else {
(bpwm)->EADCTS1 &= ~(BPWM_EADCTS1_TRGEN4_Msk << ((u32ChannelNum - 4U) * 8U));
}
}
/**
* @brief Clear selected channel trigger EADC flag
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @param[in] u32Condition This parameter is not used
* @return None
* @details This function is used to clear selected channel trigger EADC flag
*/
void BPWM_ClearEADCTriggerFlag(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Condition)
{
(bpwm)->STATUS = (BPWM_STATUS_EADCTRGn_Msk << u32ChannelNum);
}
/**
* @brief Get selected channel trigger EADC flag
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @retval 0 The specified channel trigger EADC to start of conversion flag is not set
* @retval 1 The specified channel trigger EADC to start of conversion flag is set
* @details This function is used to get BPWM trigger EADC to start of conversion flag for specified channel
*/
uint32_t BPWM_GetEADCTriggerFlag(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
return (((bpwm)->STATUS & (BPWM_STATUS_EADCTRGn_Msk << u32ChannelNum)) ? 1UL : 0UL);
}
/**
* @brief Enable capture of selected channel(s)
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
* Bit 0 is channel 0, bit 1 is channel 1...
* @return None
* @details This function is used to enable capture of selected channel(s)
*/
void BPWM_EnableCapture(BPWM_T *bpwm, uint32_t u32ChannelMask)
{
(bpwm)->CAPINEN |= u32ChannelMask;
(bpwm)->CAPCTL |= u32ChannelMask;
}
/**
* @brief Disable capture of selected channel(s)
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
* Bit 0 is channel 0, bit 1 is channel 1...
* @return None
* @details This function is used to disable capture of selected channel(s)
*/
void BPWM_DisableCapture(BPWM_T *bpwm, uint32_t u32ChannelMask)
{
(bpwm)->CAPINEN &= ~u32ChannelMask;
(bpwm)->CAPCTL &= ~u32ChannelMask;
}
/**
* @brief Enables BPWM output generation of selected channel(s)
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
* Set bit 0 to 1 enables channel 0 output, set bit 1 to 1 enables channel 1 output...
* @return None
* @details This function is used to enables BPWM output generation of selected channel(s)
*/
void BPWM_EnableOutput(BPWM_T *bpwm, uint32_t u32ChannelMask)
{
(bpwm)->POEN |= u32ChannelMask;
}
/**
* @brief Disables BPWM output generation of selected channel(s)
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Set bit 0 to 1 disables channel 0 output, set bit 1 to 1 disables channel 1 output...
* @return None
* @details This function is used to disables BPWM output generation of selected channel(s)
*/
void BPWM_DisableOutput(BPWM_T *bpwm, uint32_t u32ChannelMask)
{
(bpwm)->POEN &= ~u32ChannelMask;
}
/**
* @brief Enable capture interrupt of selected channel.
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @param[in] u32Edge Rising or falling edge to latch counter.
* - \ref BPWM_CAPTURE_INT_RISING_LATCH
* - \ref BPWM_CAPTURE_INT_FALLING_LATCH
* @return None
* @details This function is used to enable capture interrupt of selected channel.
*/
void BPWM_EnableCaptureInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge)
{
(bpwm)->CAPIEN |= (u32Edge << u32ChannelNum);
}
/**
* @brief Disable capture interrupt of selected channel.
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @param[in] u32Edge Rising or falling edge to latch counter.
* - \ref BPWM_CAPTURE_INT_RISING_LATCH
* - \ref BPWM_CAPTURE_INT_FALLING_LATCH
* @return None
* @details This function is used to disable capture interrupt of selected channel.
*/
void BPWM_DisableCaptureInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge)
{
(bpwm)->CAPIEN &= ~(u32Edge << u32ChannelNum);
}
/**
* @brief Clear capture interrupt of selected channel.
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @param[in] u32Edge Rising or falling edge to latch counter.
* - \ref BPWM_CAPTURE_INT_RISING_LATCH
* - \ref BPWM_CAPTURE_INT_FALLING_LATCH
* @return None
* @details This function is used to clear capture interrupt of selected channel.
*/
void BPWM_ClearCaptureIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge)
{
(bpwm)->CAPIF = (u32Edge << u32ChannelNum);
}
/**
* @brief Get capture interrupt of selected channel.
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @retval 0 No capture interrupt
* @retval 1 Rising edge latch interrupt
* @retval 2 Falling edge latch interrupt
* @retval 3 Rising and falling latch interrupt
* @details This function is used to get capture interrupt of selected channel.
*/
uint32_t BPWM_GetCaptureIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
return (((((bpwm)->CAPIF & (BPWM_CAPIF_CAPFIFn_Msk << u32ChannelNum)) ? 1UL : 0UL) << 1) | \
(((bpwm)->CAPIF & (BPWM_CAPIF_CAPRIFn_Msk << u32ChannelNum)) ? 1UL : 0UL));
}
/**
* @brief Enable duty interrupt of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @param[in] u32IntDutyType Duty interrupt type, could be either
* - \ref BPWM_DUTY_INT_DOWN_COUNT_MATCH_CMP
* - \ref BPWM_DUTY_INT_UP_COUNT_MATCH_CMP
* @return None
* @details This function is used to enable duty interrupt of selected channel.
*/
void BPWM_EnableDutyInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType)
{
(bpwm)->INTEN |= (u32IntDutyType << u32ChannelNum);
}
/**
* @brief Disable duty interrupt of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @return None
* @details This function is used to disable duty interrupt of selected channel
*/
void BPWM_DisableDutyInt(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
(bpwm)->INTEN &= ~((uint32_t)(BPWM_DUTY_INT_DOWN_COUNT_MATCH_CMP | BPWM_DUTY_INT_UP_COUNT_MATCH_CMP) << u32ChannelNum);
}
/**
* @brief Clear duty interrupt flag of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @return None
* @details This function is used to clear duty interrupt flag of selected channel
*/
void BPWM_ClearDutyIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
(bpwm)->INTSTS = (BPWM_INTSTS_CMPUIFn_Msk | BPWM_INTSTS_CMPDIFn_Msk) << u32ChannelNum;
}
/**
* @brief Get duty interrupt flag of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @return Duty interrupt flag of specified channel
* @retval 0 Duty interrupt did not occur
* @retval 1 Duty interrupt occurred
* @details This function is used to get duty interrupt flag of selected channel
*/
uint32_t BPWM_GetDutyIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
return ((((bpwm)->INTSTS & ((BPWM_INTSTS_CMPDIFn_Msk | BPWM_INTSTS_CMPUIFn_Msk) << u32ChannelNum))) ? 1UL : 0UL);
}
/**
* @brief Enable period interrupt of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @param[in] u32IntPeriodType Period interrupt type. This parameter is not used.
* @return None
* @details This function is used to enable period interrupt of selected channel.
* @note All channels share channel 0's setting.
*/
void BPWM_EnablePeriodInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType)
{
(bpwm)->INTEN |= BPWM_INTEN_PIEN0_Msk;
}
/**
* @brief Disable period interrupt of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @return None
* @details This function is used to disable period interrupt of selected channel.
* @note All channels share channel 0's setting.
*/
void BPWM_DisablePeriodInt(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
(bpwm)->INTEN &= ~BPWM_INTEN_PIEN0_Msk;
}
/**
* @brief Clear period interrupt of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @return None
* @details This function is used to clear period interrupt of selected channel
* @note All channels share channel 0's setting.
*/
void BPWM_ClearPeriodIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
(bpwm)->INTSTS = BPWM_INTSTS_PIF0_Msk;
}
/**
* @brief Get period interrupt of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @return Period interrupt flag of specified channel
* @retval 0 Period interrupt did not occur
* @retval 1 Period interrupt occurred
* @details This function is used to get period interrupt of selected channel
* @note All channels share channel 0's setting.
*/
uint32_t BPWM_GetPeriodIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
return (((bpwm)->INTSTS & BPWM_INTSTS_PIF0_Msk) ? 1UL : 0UL);
}
/**
* @brief Enable zero interrupt of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @return None
* @details This function is used to enable zero interrupt of selected channel.
* @note All channels share channel 0's setting.
*/
void BPWM_EnableZeroInt(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
(bpwm)->INTEN |= BPWM_INTEN_ZIEN0_Msk;
}
/**
* @brief Disable zero interrupt of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @return None
* @details This function is used to disable zero interrupt of selected channel.
* @note All channels share channel 0's setting.
*/
void BPWM_DisableZeroInt(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
(bpwm)->INTEN &= ~BPWM_INTEN_ZIEN0_Msk;
}
/**
* @brief Clear zero interrupt of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @return None
* @details This function is used to clear zero interrupt of selected channel.
* @note All channels share channel 0's setting.
*/
void BPWM_ClearZeroIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
(bpwm)->INTSTS = BPWM_INTSTS_ZIF0_Msk;
}
/**
* @brief Get zero interrupt of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @return zero interrupt flag of specified channel
* @retval 0 zero interrupt did not occur
* @retval 1 zero interrupt occurred
* @details This function is used to get zero interrupt of selected channel.
* @note All channels share channel 0's setting.
*/
uint32_t BPWM_GetZeroIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
return (((bpwm)->INTSTS & BPWM_INTSTS_ZIF0_Msk) ? 1UL : 0UL);
}
/**
* @brief Enable load mode of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @param[in] u32LoadMode BPWM counter loading mode.
* - \ref BPWM_LOAD_MODE_IMMEDIATE
* - \ref BPWM_LOAD_MODE_CENTER
* @return None
* @details This function is used to enable load mode of selected channel.
*/
void BPWM_EnableLoadMode(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32LoadMode)
{
(bpwm)->CTL0 |= (u32LoadMode << u32ChannelNum);
}
/**
* @brief Disable load mode of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @param[in] u32LoadMode PWM counter loading mode.
* - \ref BPWM_LOAD_MODE_IMMEDIATE
* - \ref BPWM_LOAD_MODE_CENTER
* @return None
* @details This function is used to disable load mode of selected channel.
*/
void BPWM_DisableLoadMode(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32LoadMode)
{
(bpwm)->CTL0 &= ~(u32LoadMode << u32ChannelNum);
}
/**
* @brief Enable BPWM SYNC input pin inverse function
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @param[in] u32ClkSrcSel BPWM external clock source.
* - \ref BPWM_CLKSRC_BPWM_CLK
* - \ref BPWM_CLKSRC_TIMER0
* - \ref BPWM_CLKSRC_TIMER1
* - \ref BPWM_CLKSRC_TIMER2
* - \ref BPWM_CLKSRC_TIMER3
* @return None
* @details This function is used to enable BPWM SYNC input pin inverse function.
* @note All channels share channel 0's setting.
*/
void BPWM_SetClockSource(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32ClkSrcSel)
{
(bpwm)->CLKSRC = (u32ClkSrcSel);
}
/**
* @brief Get the time-base counter reached its maximum value flag of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @return Count to max interrupt flag of specified channel
* @retval 0 Count to max interrupt did not occur
* @retval 1 Count to max interrupt occurred
* @details This function is used to get the time-base counter reached its maximum value flag of selected channel.
* @note All channels share channel 0's setting.
*/
uint32_t BPWM_GetWrapAroundFlag(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
return (((bpwm)->STATUS & BPWM_STATUS_CNTMAX0_Msk) ? 1UL : 0UL);
}
/**
* @brief Clear the time-base counter reached its maximum value flag of selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* - BPWM0 : BPWM Group 0
* - BPWM1 : BPWM Group 1
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @return None
* @details This function is used to clear the time-base counter reached its maximum value flag of selected channel.
* @note All channels share channel 0's setting.
*/
void BPWM_ClearWrapAroundFlag(BPWM_T *bpwm, uint32_t u32ChannelNum)
{
(bpwm)->STATUS = BPWM_STATUS_CNTMAX0_Msk;
}
/*@}*/ /* end of group M480_BPWM_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_BPWM_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,319 @@
/**************************************************************************//**
* @file bpwm.h
* @version V1.00
* @brief M480 series PWM driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __BPWM_H__
#define __BPWM_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_BPWM_Driver BPWM Driver
@{
*/
/** @addtogroup M480_BPWM_EXPORTED_CONSTANTS BPWM Exported Constants
@{
*/
#define BPWM_CHANNEL_NUM (6) /*!< BPWM channel number \hideinitializer */
#define BPWM_CH_0_MASK (0x1UL) /*!< BPWM channel 0 mask \hideinitializer */
#define BPWM_CH_1_MASK (0x2UL) /*!< BPWM channel 1 mask \hideinitializer */
#define BPWM_CH_2_MASK (0x4UL) /*!< BPWM channel 2 mask \hideinitializer */
#define BPWM_CH_3_MASK (0x8UL) /*!< BPWM channel 3 mask \hideinitializer */
#define BPWM_CH_4_MASK (0x10UL) /*!< BPWM channel 4 mask \hideinitializer */
#define BPWM_CH_5_MASK (0x20UL) /*!< BPWM channel 5 mask \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Counter Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define BPWM_UP_COUNTER (0UL) /*!< Up counter type \hideinitializer */
#define BPWM_DOWN_COUNTER (1UL) /*!< Down counter type \hideinitializer */
#define BPWM_UP_DOWN_COUNTER (2UL) /*!< Up-Down counter type \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Aligned Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define BPWM_EDGE_ALIGNED (1UL) /*!< BPWM working in edge aligned type(down count) \hideinitializer */
#define BPWM_CENTER_ALIGNED (2UL) /*!< BPWM working in center aligned type \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Output Level Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define BPWM_OUTPUT_NOTHING (0UL) /*!< BPWM output nothing \hideinitializer */
#define BPWM_OUTPUT_LOW (1UL) /*!< BPWM output low \hideinitializer */
#define BPWM_OUTPUT_HIGH (2UL) /*!< BPWM output high \hideinitializer */
#define BPWM_OUTPUT_TOGGLE (3UL) /*!< BPWM output toggle \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Trigger Source Select Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define BPWM_TRIGGER_EADC_EVEN_ZERO_POINT (0UL) /*!< BPWM trigger EADC while counter of even channel matches zero point \hideinitializer */
#define BPWM_TRIGGER_EADC_EVEN_PERIOD_POINT (1UL) /*!< BPWM trigger EADC while counter of even channel matches period point \hideinitializer */
#define BPWM_TRIGGER_EADC_EVEN_ZERO_OR_PERIOD_POINT (2UL) /*!< BPWM trigger EADC while counter of even channel matches zero or period point \hideinitializer */
#define BPWM_TRIGGER_EADC_EVEN_CMP_UP_COUNT_POINT (3UL) /*!< BPWM trigger EADC while counter of even channel matches up count to comparator point \hideinitializer */
#define BPWM_TRIGGER_EADC_EVEN_CMP_DOWN_COUNT_POINT (4UL) /*!< BPWM trigger EADC while counter of even channel matches down count to comparator point \hideinitializer */
#define BPWM_TRIGGER_EADC_ODD_CMP_UP_COUNT_POINT (8UL) /*!< BPWM trigger EADC while counter of odd channel matches up count to comparator point \hideinitializer */
#define BPWM_TRIGGER_EADC_ODD_CMP_DOWN_COUNT_POINT (9UL) /*!< BPWM trigger EADC while counter of odd channel matches down count to comparator point \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Capture Control Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define BPWM_CAPTURE_INT_RISING_LATCH (1UL) /*!< BPWM capture interrupt if channel has rising transition \hideinitializer */
#define BPWM_CAPTURE_INT_FALLING_LATCH (0x100UL) /*!< BPWM capture interrupt if channel has falling transition \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Duty Interrupt Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define BPWM_DUTY_INT_DOWN_COUNT_MATCH_CMP (1 << BPWM_INTEN_CMPDIENn_Pos) /*!< BPWM duty interrupt triggered if down count match comparator \hideinitializer */
#define BPWM_DUTY_INT_UP_COUNT_MATCH_CMP (1 << BPWM_INTEN_CMPUIENn_Pos) /*!< BPWM duty interrupt triggered if up down match comparator \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Load Mode Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define BPWM_LOAD_MODE_IMMEDIATE (1 << BPWM_CTL0_IMMLDENn_Pos) /*!< BPWM immediately load mode \hideinitializer */
#define BPWM_LOAD_MODE_CENTER (1 << BPWM_CTL0_CTRLDn_Pos) /*!< BPWM center load mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Clock Source Select Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define BPWM_CLKSRC_BPWM_CLK (0UL) /*!< BPWM Clock source selects to BPWM0_CLK or BPWM1_CLK \hideinitializer */
#define BPWM_CLKSRC_TIMER0 (1UL) /*!< BPWM Clock source selects to TIMER0 overflow \hideinitializer */
#define BPWM_CLKSRC_TIMER1 (2UL) /*!< BPWM Clock source selects to TIMER1 overflow \hideinitializer */
#define BPWM_CLKSRC_TIMER2 (3UL) /*!< BPWM Clock source selects to TIMER2 overflow \hideinitializer */
#define BPWM_CLKSRC_TIMER3 (4UL) /*!< BPWM Clock source selects to TIMER3 overflow \hideinitializer */
/*@}*/ /* end of group M480_BPWM_EXPORTED_CONSTANTS */
/** @addtogroup M480_BPWM_EXPORTED_FUNCTIONS BPWM Exported Functions
@{
*/
/**
* @brief Enable timer synchronous mode of specified channel(s)
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used.
* @return None
* @details This macro is used to enable timer synchronous mode of specified channel(s).
* @note All channels share channel 0's setting.
* \hideinitializer
*/
#define BPWM_ENABLE_TIMER_SYNC(bpwm, u32ChannelMask) ((bpwm)->SSCTL |= BPWM_SSCTL_SSEN0_Msk)
/**
* @brief Disable timer synchronous mode of specified channel(s)
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used.
* @return None
* @details This macro is used to disable timer synchronous mode of specified channel(s).
* @note All channels share channel 0's setting.
* \hideinitializer
*/
#define BPWM_DISABLE_TIMER_SYNC(bpwm, u32ChannelMask) ((bpwm)->SSCTL &= ~BPWM_SSCTL_SSEN0_Msk)
/**
* @brief This macro enable output inverter of specified channel(s)
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 1...
* @return None
* \hideinitializer
*/
#define BPWM_ENABLE_OUTPUT_INVERTER(bpwm, u32ChannelMask) ((bpwm)->POLCTL = (u32ChannelMask))
/**
* @brief This macro get captured rising data
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @return None
* \hideinitializer
*/
#define BPWM_GET_CAPTURE_RISING_DATA(bpwm, u32ChannelNum) (*(__IO uint32_t *) (&((bpwm)->RCAPDAT0) + 2 * (u32ChannelNum)))
/**
* @brief This macro get captured falling data
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @return None
* \hideinitializer
*/
#define BPWM_GET_CAPTURE_FALLING_DATA(bpwm, u32ChannelNum) (*(__IO uint32_t *) (&((bpwm)->FCAPDAT0) + 2 * (u32ChannelNum)))
/**
* @brief This macro mask output logic to high or low
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 1...
* @param[in] u32LevelMask Output logic to high or low
* @return None
* @details This macro is used to mask output logic to high or low of specified channel(s).
* @note If u32ChannelMask parameter is 0, then mask function will be disabled.
* \hideinitializer
*/
#define BPWM_MASK_OUTPUT(bpwm, u32ChannelMask, u32LevelMask) \
{ \
(bpwm)->MSKEN = (u32ChannelMask); \
(bpwm)->MSK = (u32LevelMask); \
}
/**
* @brief This macro set the prescaler of all channels
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @param[in] u32Prescaler Clock prescaler of specified channel. Valid values are between 1 ~ 0xFFF
* @return None
* \hideinitializer
*/
#define BPWM_SET_PRESCALER(bpwm, u32ChannelNum, u32Prescaler) ((bpwm)->CLKPSC = (u32Prescaler))
/**
* @brief This macro set the duty of the selected channel
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5
* @param[in] u32CMR Duty of specified channel. Valid values are between 0~0xFFFF
* @return None
* @note This new setting will take effect on next BPWM period
* \hideinitializer
*/
#define BPWM_SET_CMR(bpwm, u32ChannelNum, u32CMR) ((bpwm)->CMPDAT[(u32ChannelNum)] = (u32CMR))
/**
* @brief This macro set the period of all channels
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelNum BPWM channel number. This parameter is not used.
* @param[in] u32CNR Period of specified channel. Valid values are between 0~0xFFFF
* @return None
* @note This new setting will take effect on next BPWM period
* @note BPWM counter will stop if period length set to 0
* \hideinitializer
*/
#define BPWM_SET_CNR(bpwm, u32ChannelNum, u32CNR) ((bpwm)->PERIOD = (u32CNR))
/**
* @brief This macro set the BPWM aligned type
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used.
* @param[in] u32AlignedType BPWM aligned type, valid values are:
* - \ref BPWM_EDGE_ALIGNED
* - \ref BPWM_CENTER_ALIGNED
* @return None
* @note All channels share channel 0's setting.
* \hideinitializer
*/
#define BPWM_SET_ALIGNED_TYPE(bpwm, u32ChannelMask, u32AlignedType) ((bpwm)->CTL1 = (u32AlignedType))
/**
* @brief Clear counter of channel 0
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelMask Combination of enabled channels. This parameter is not used.
* @return None
* @details This macro is used to clear counter of channel 0
* \hideinitializer
*/
#define BPWM_CLR_COUNTER(bpwm, u32ChannelMask) ((bpwm)->CNTCLR = (BPWM_CNTCLR_CNTCLR0_Msk))
/**
* @brief Set output level at zero, compare up, period(center) and compare down of specified channel(s)
* @param[in] bpwm The pointer of the specified BPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 1...
* @param[in] u32ZeroLevel output level at zero point, valid values are:
* - \ref BPWM_OUTPUT_NOTHING
* - \ref BPWM_OUTPUT_LOW
* - \ref BPWM_OUTPUT_HIGH
* - \ref BPWM_OUTPUT_TOGGLE
* @param[in] u32CmpUpLevel output level at compare up point, valid values are:
* - \ref BPWM_OUTPUT_NOTHING
* - \ref BPWM_OUTPUT_LOW
* - \ref BPWM_OUTPUT_HIGH
* - \ref BPWM_OUTPUT_TOGGLE
* @param[in] u32PeriodLevel output level at period(center) point, valid values are:
* - \ref BPWM_OUTPUT_NOTHING
* - \ref BPWM_OUTPUT_LOW
* - \ref BPWM_OUTPUT_HIGH
* - \ref BPWM_OUTPUT_TOGGLE
* @param[in] u32CmpDownLevel output level at compare down point, valid values are:
* - \ref BPWM_OUTPUT_NOTHING
* - \ref BPWM_OUTPUT_LOW
* - \ref BPWM_OUTPUT_HIGH
* - \ref BPWM_OUTPUT_TOGGLE
* @return None
* @details This macro is used to Set output level at zero, compare up, period(center) and compare down of specified channel(s)
* \hideinitializer
*/
#define BPWM_SET_OUTPUT_LEVEL(bpwm, u32ChannelMask, u32ZeroLevel, u32CmpUpLevel, u32PeriodLevel, u32CmpDownLevel) \
do{ \
int i; \
for(i = 0; i < 6; i++) { \
if((u32ChannelMask) & (1 << i)) { \
(bpwm)->WGCTL0 = (((bpwm)->WGCTL0 & ~(3UL << (2 * i))) | ((u32ZeroLevel) << (2 * i))); \
(bpwm)->WGCTL0 = (((bpwm)->WGCTL0 & ~(3UL << (BPWM_WGCTL0_PRDPCTLn_Pos + (2 * i)))) | ((u32PeriodLevel) << (BPWM_WGCTL0_PRDPCTLn_Pos + (2 * i)))); \
(bpwm)->WGCTL1 = (((bpwm)->WGCTL1 & ~(3UL << (2 * i))) | ((u32CmpUpLevel) << (2 * i))); \
(bpwm)->WGCTL1 = (((bpwm)->WGCTL1 & ~(3UL << (BPWM_WGCTL1_CMPDCTLn_Pos + (2 * i)))) | ((u32CmpDownLevel) << (BPWM_WGCTL1_CMPDCTLn_Pos + (2 * i)))); \
} \
} \
}while(0)
/*---------------------------------------------------------------------------------------------------------*/
/* Define BPWM functions prototype */
/*---------------------------------------------------------------------------------------------------------*/
uint32_t BPWM_ConfigCaptureChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32UnitTimeNsec, uint32_t u32CaptureEdge);
uint32_t BPWM_ConfigOutputChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Frequency, uint32_t u32DutyCycle);
void BPWM_Start(BPWM_T *bpwm, uint32_t u32ChannelMask);
void BPWM_Stop(BPWM_T *bpwm, uint32_t u32ChannelMask);
void BPWM_ForceStop(BPWM_T *bpwm, uint32_t u32ChannelMask);
void BPWM_EnableEADCTrigger(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Condition);
void BPWM_DisableEADCTrigger(BPWM_T *bpwm, uint32_t u32ChannelNum);
void BPWM_ClearEADCTriggerFlag(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Condition);
uint32_t BPWM_GetEADCTriggerFlag(BPWM_T *bpwm, uint32_t u32ChannelNum);
void BPWM_EnableCapture(BPWM_T *bpwm, uint32_t u32ChannelMask);
void BPWM_DisableCapture(BPWM_T *bpwm, uint32_t u32ChannelMask);
void BPWM_EnableOutput(BPWM_T *bpwm, uint32_t u32ChannelMask);
void BPWM_DisableOutput(BPWM_T *bpwm, uint32_t u32ChannelMask);
void BPWM_EnableCaptureInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge);
void BPWM_DisableCaptureInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge);
void BPWM_ClearCaptureIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Edge);
uint32_t BPWM_GetCaptureIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum);
void BPWM_EnableDutyInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType);
void BPWM_DisableDutyInt(BPWM_T *bpwm, uint32_t u32ChannelNum);
void BPWM_ClearDutyIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum);
uint32_t BPWM_GetDutyIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum);
void BPWM_EnablePeriodInt(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType);
void BPWM_DisablePeriodInt(BPWM_T *bpwm, uint32_t u32ChannelNum);
void BPWM_ClearPeriodIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum);
uint32_t BPWM_GetPeriodIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum);
void BPWM_EnableZeroInt(BPWM_T *bpwm, uint32_t u32ChannelNum);
void BPWM_DisableZeroInt(BPWM_T *bpwm, uint32_t u32ChannelNum);
void BPWM_ClearZeroIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum);
uint32_t BPWM_GetZeroIntFlag(BPWM_T *bpwm, uint32_t u32ChannelNum);
void BPWM_EnableLoadMode(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32LoadMode);
void BPWM_DisableLoadMode(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32LoadMode);
void BPWM_SetClockSource(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32ClkSrcSel);
uint32_t BPWM_GetWrapAroundFlag(BPWM_T *bpwm, uint32_t u32ChannelNum);
void BPWM_ClearWrapAroundFlag(BPWM_T *bpwm, uint32_t u32ChannelNum);
/*@}*/ /* end of group M480_BPWM_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_BPWM_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __BPWM_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,180 @@
/**************************************************************************//**
* @file can.h
* @version V2.00
* @brief M480 Series CAN Driver Header File
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#ifndef __CAN_H__
#define __CAN_H__
#include "M480.h"
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_CAN_Driver CAN Driver
@{
*/
/** @addtogroup M480_CAN_EXPORTED_CONSTANTS CAN Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* CAN Test Mode Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define CAN_NORMAL_MODE 0ul /*!< CAN select normal mode \hideinitializer */
#define CAN_BASIC_MODE 1ul /*!< CAN select basic mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Message ID Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define CAN_STD_ID 0ul /*!< CAN select standard ID \hideinitializer */
#define CAN_EXT_ID 1ul /*!< CAN select extended ID \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Message Frame Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define CAN_REMOTE_FRAME 0ul /*!< CAN frame select remote frame \hideinitializer */
#define CAN_DATA_FRAME 1ul /*!< CAN frame select data frame \hideinitializer */
/*@}*/ /* end of group M480_CAN_EXPORTED_CONSTANTS */
/** @addtogroup M480_CAN_EXPORTED_STRUCTS CAN Exported Structs
@{
*/
/**
* @details CAN message structure
*/
typedef struct {
uint32_t IdType; /*!< ID type */
uint32_t FrameType; /*!< Frame type */
uint32_t Id; /*!< Message ID */
uint8_t DLC; /*!< Data length */
uint8_t Data[8]; /*!< Data */
} STR_CANMSG_T;
/**
* @details CAN mask message structure
*/
typedef struct {
uint8_t u8Xtd; /*!< Extended ID */
uint8_t u8Dir; /*!< Direction */
uint32_t u32Id; /*!< Message ID */
uint8_t u8IdType; /*!< ID type*/
} STR_CANMASK_T;
/*@}*/ /* end of group M480_CAN_EXPORTED_STRUCTS */
/** @cond HIDDEN_SYMBOLS */
#define MSG(id) (id)
/** @endcond HIDDEN_SYMBOLS */
/** @addtogroup M480_CAN_EXPORTED_FUNCTIONS CAN Exported Functions
@{
*/
/**
* @brief Get interrupt status.
*
* @param[in] can The base address of can module.
*
* @return CAN module status register value.
*
* @details Status Interrupt is generated by bits BOff (CAN_STATUS[7]), EWarn (CAN_STATUS[6]),
* EPass (CAN_STATUS[5]), RxOk (CAN_STATUS[4]), TxOk (CAN_STATUS[3]), and LEC (CAN_STATUS[2:0]).
* \hideinitializer
*/
#define CAN_GET_INT_STATUS(can) ((can)->STATUS)
/**
* @brief Get specified interrupt pending status.
*
* @param[in] can The base address of can module.
*
* @return The source of the interrupt.
*
* @details If several interrupts are pending, the CAN Interrupt Register will point to the pending interrupt
* with the highest priority, disregarding their chronological order.
* \hideinitializer
*/
#define CAN_GET_INT_PENDING_STATUS(can) ((can)->IIDR)
/**
* @brief Disable wake-up function.
*
* @param[in] can The base address of can module.
*
* @return None
*
* @details The macro is used to disable wake-up function.
* \hideinitializer
*/
#define CAN_DISABLE_WAKEUP(can) ((can)->WU_EN = 0ul)
/**
* @brief Enable wake-up function.
*
* @param[in] can The base address of can module.
*
* @return None
*
* @details User can wake-up system when there is a falling edge in the CAN_Rx pin.
* \hideinitializer
*/
#define CAN_ENABLE_WAKEUP(can) ((can)->WU_EN = CAN_WU_EN_WAKUP_EN_Msk)
/**
* @brief Get specified Message Object new data into bit value.
*
* @param[in] can The base address of can module.
* @param[in] u32MsgNum Specified Message Object number, valid value are from 0 to 31.
*
* @return Specified Message Object new data into bit value.
*
* @details The NewDat bit (CAN_IFn_MCON[15]) of a specific Message Object can be set/reset by the software through the IFn Message Interface Registers
* or by the Message Handler after reception of a Data Frame or after a successful transmission.
* \hideinitializer
*/
#define CAN_GET_NEW_DATA_IN_BIT(can, u32MsgNum) ((u32MsgNum) < 16 ? (can)->NDAT1 & (1 << (u32MsgNum)) : (can)->NDAT2 & (1 << ((u32MsgNum)-16)))
/*---------------------------------------------------------------------------------------------------------*/
/* Define CAN functions prototype */
/*---------------------------------------------------------------------------------------------------------*/
uint32_t CAN_SetBaudRate(CAN_T *tCAN, uint32_t u32BaudRate);
uint32_t CAN_Open(CAN_T *tCAN, uint32_t u32BaudRate, uint32_t u32Mode);
void CAN_Close(CAN_T *tCAN);
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum);
void CAN_EnableInt(CAN_T *tCAN, uint32_t u32Mask);
void CAN_DisableInt(CAN_T *tCAN, uint32_t u32Mask);
int32_t CAN_Transmit(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg);
int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg);
int32_t CAN_SetMultiRxMsg(CAN_T *tCAN, uint32_t u32MsgNum , uint32_t u32MsgCount, uint32_t u32IDType, uint32_t u32ID);
int32_t CAN_SetRxMsg(CAN_T *tCAN, uint32_t u32MsgNum , uint32_t u32IDType, uint32_t u32ID);
int32_t CAN_SetRxMsgAndMsk(CAN_T *tCAN, uint32_t u32MsgNum , uint32_t u32IDType, uint32_t u32ID, uint32_t u32IDMask);
int32_t CAN_SetTxMsg(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg);
int32_t CAN_TriggerTxMsg(CAN_T *tCAN, uint32_t u32MsgNum);
/*@}*/ /* end of group M480_CAN_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_CAN_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /*__CAN_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,612 @@
/**************************************************************************//**
* @file CLK.h
* @version V1.0
* @brief M480 Series CLK Driver Header File
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#ifndef __CLK_H__
#define __CLK_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_CLK_Driver CLK Driver
@{
*/
/** @addtogroup M480_CLK_EXPORTED_CONSTANTS CLK Exported Constants
@{
*/
#define FREQ_25MHZ 25000000UL /*!< 25 MHz \hideinitializer */
#define FREQ_50MHZ 50000000UL /*!< 50 MHz \hideinitializer */
#define FREQ_72MHZ 72000000UL /*!< 72 MHz \hideinitializer */
#define FREQ_80MHZ 80000000UL /*!< 80 MHz \hideinitializer */
#define FREQ_100MHZ 100000000UL /*!< 100 MHz \hideinitializer */
#define FREQ_125MHZ 125000000UL /*!< 125 MHz \hideinitializer */
#define FREQ_160MHZ 160000000UL /*!< 160 MHz \hideinitializer */
#define FREQ_192MHZ 192000000UL /*!< 192 MHz \hideinitializer */
#define FREQ_200MHZ 200000000UL /*!< 200 MHz \hideinitializer */
#define FREQ_250MHZ 250000000UL /*!< 250 MHz \hideinitializer */
#define FREQ_500MHZ 500000000UL /*!< 500 MHz \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* CLKSEL0 constant definitions. (Write-protection) */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKSEL0_HCLKSEL_HXT (0x0UL << CLK_CLKSEL0_HCLKSEL_Pos) /*!< Select HCLK clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL0_HCLKSEL_LXT (0x1UL << CLK_CLKSEL0_HCLKSEL_Pos) /*!< Select HCLK clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL0_HCLKSEL_PLL (0x2UL << CLK_CLKSEL0_HCLKSEL_Pos) /*!< Select HCLK clock source from PLL \hideinitializer */
#define CLK_CLKSEL0_HCLKSEL_LIRC (0x3UL << CLK_CLKSEL0_HCLKSEL_Pos) /*!< Select HCLK clock source from low speed oscillator \hideinitializer */
#define CLK_CLKSEL0_HCLKSEL_HIRC (0x7UL << CLK_CLKSEL0_HCLKSEL_Pos) /*!< Select HCLK clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL0_STCLKSEL_HXT (0x0UL << CLK_CLKSEL0_STCLKSEL_Pos) /*!< Select SysTick clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL0_STCLKSEL_LXT (0x1UL << CLK_CLKSEL0_STCLKSEL_Pos) /*!< Select SysTick clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL0_STCLKSEL_HXT_DIV2 (0x2UL << CLK_CLKSEL0_STCLKSEL_Pos) /*!< Select SysTick clock source from HXT/2 \hideinitializer */
#define CLK_CLKSEL0_STCLKSEL_HCLK_DIV2 (0x3UL << CLK_CLKSEL0_STCLKSEL_Pos) /*!< Select SysTick clock source from HCLK/2 \hideinitializer */
#define CLK_CLKSEL0_STCLKSEL_HIRC_DIV2 (0x7UL << CLK_CLKSEL0_STCLKSEL_Pos) /*!< Select SysTick clock source from HIRC/2 \hideinitializer */
#define CLK_CLKSEL0_STCLKSEL_HCLK (0x01UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< Select SysTick clock source from HCLK \hideinitializer */
#if(0)
#define CLK_CLKSEL0_PCLK0DIV1 (0x0UL << CLK_CLKSEL0_PCLK0SEL_Pos) /*!< Select PCLK0 clock source from HCLK \hideinitializer */
#define CLK_CLKSEL0_PCLK0DIV2 (0x1UL << CLK_CLKSEL0_PCLK0SEL_Pos) /*!< Select PCLK0 clock source from 1/2 HCLK \hideinitializer */
#define CLK_CLKSEL0_PCLK1DIV1 (0x0UL << CLK_CLKSEL0_PCLK1SEL_Pos) /*!< Select PCLK1 clock source from HCLK \hideinitializer */
#define CLK_CLKSEL0_PCLK1DIV2 (0x1UL << CLK_CLKSEL0_PCLK1SEL_Pos) /*!< Select PCLK1 clock source from 1/2 HCLK \hideinitializer */
#endif
#define CLK_CLKSEL0_SDH0SEL_HXT (0x0UL << CLK_CLKSEL0_SDH0SEL_Pos) /*!< Select SDH0 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL0_SDH0SEL_PLL (0x1UL << CLK_CLKSEL0_SDH0SEL_Pos) /*!< Select SDH0 clock source from PLL \hideinitializer */
#define CLK_CLKSEL0_SDH0SEL_HIRC (0x3UL << CLK_CLKSEL0_SDH0SEL_Pos) /*!< Select SDH0 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL0_SDH0SEL_HCLK (0x2UL << CLK_CLKSEL0_SDH0SEL_Pos) /*!< Select SDH0 clock source from HCLK \hideinitializer */
#define CLK_CLKSEL0_SDH1SEL_HXT (0x0UL << CLK_CLKSEL0_SDH1SEL_Pos) /*!< Select SDH1 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL0_SDH1SEL_PLL (0x1UL << CLK_CLKSEL0_SDH1SEL_Pos) /*!< Select SDH1 clock source from PLL \hideinitializer */
#define CLK_CLKSEL0_SDH1SEL_HIRC (0x3UL << CLK_CLKSEL0_SDH1SEL_Pos) /*!< Select SDH1 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL0_SDH1SEL_HCLK (0x2UL << CLK_CLKSEL0_SDH1SEL_Pos) /*!< Select SDH1 clock source from HCLK \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* CLKSEL1 constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKSEL1_WDTSEL_LXT (0x1UL << CLK_CLKSEL1_WDTSEL_Pos) /*!< Select WDT clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL1_WDTSEL_LIRC (0x3UL << CLK_CLKSEL1_WDTSEL_Pos) /*!< Select WDT clock source from low speed oscillator \hideinitializer */
#define CLK_CLKSEL1_WDTSEL_HCLK_DIV2048 (0x2UL << CLK_CLKSEL1_WDTSEL_Pos) /*!< Select WDT clock source from HCLK/2048 \hideinitializer */
#define CLK_CLKSEL1_TMR0SEL_HXT (0x0UL << CLK_CLKSEL1_TMR0SEL_Pos) /*!< Select TMR0 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL1_TMR0SEL_LXT (0x1UL << CLK_CLKSEL1_TMR0SEL_Pos) /*!< Select TMR0 clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL1_TMR0SEL_LIRC (0x5UL << CLK_CLKSEL1_TMR0SEL_Pos) /*!< Select TMR0 clock source from low speed oscillator \hideinitializer */
#define CLK_CLKSEL1_TMR0SEL_HIRC (0x7UL << CLK_CLKSEL1_TMR0SEL_Pos) /*!< Select TMR0 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL1_TMR0SEL_PCLK0 (0x2UL << CLK_CLKSEL1_TMR0SEL_Pos) /*!< Select TMR0 clock source from PCLK0 \hideinitializer */
#define CLK_CLKSEL1_TMR0SEL_EXT (0x3UL << CLK_CLKSEL1_TMR0SEL_Pos) /*!< Select TMR0 clock source from external trigger \hideinitializer */
#define CLK_CLKSEL1_TMR1SEL_HXT (0x0UL << CLK_CLKSEL1_TMR1SEL_Pos) /*!< Select TMR1 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL1_TMR1SEL_LXT (0x1UL << CLK_CLKSEL1_TMR1SEL_Pos) /*!< Select TMR1 clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL1_TMR1SEL_LIRC (0x5UL << CLK_CLKSEL1_TMR1SEL_Pos) /*!< Select TMR1 clock source from low speed oscillator \hideinitializer */
#define CLK_CLKSEL1_TMR1SEL_HIRC (0x7UL << CLK_CLKSEL1_TMR1SEL_Pos) /*!< Select TMR1 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL1_TMR1SEL_PCLK0 (0x2UL << CLK_CLKSEL1_TMR1SEL_Pos) /*!< Select TMR1 clock source from PCLK0 \hideinitializer */
#define CLK_CLKSEL1_TMR1SEL_EXT (0x3UL << CLK_CLKSEL1_TMR1SEL_Pos) /*!< Select TMR1 clock source from external trigger \hideinitializer */
#define CLK_CLKSEL1_TMR2SEL_HXT (0x0UL << CLK_CLKSEL1_TMR2SEL_Pos) /*!< Select TMR2 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL1_TMR2SEL_LXT (0x1UL << CLK_CLKSEL1_TMR2SEL_Pos) /*!< Select TMR2 clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL1_TMR2SEL_LIRC (0x5UL << CLK_CLKSEL1_TMR2SEL_Pos) /*!< Select TMR2 clock source from low speed oscillator \hideinitializer */
#define CLK_CLKSEL1_TMR2SEL_HIRC (0x7UL << CLK_CLKSEL1_TMR2SEL_Pos) /*!< Select TMR2 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL1_TMR2SEL_PCLK1 (0x2UL << CLK_CLKSEL1_TMR2SEL_Pos) /*!< Select TMR2 clock source from PCLK1 \hideinitializer */
#define CLK_CLKSEL1_TMR2SEL_EXT (0x3UL << CLK_CLKSEL1_TMR2SEL_Pos) /*!< Select TMR2 clock source from external trigger \hideinitializer */
#define CLK_CLKSEL1_TMR3SEL_HXT (0x0UL << CLK_CLKSEL1_TMR3SEL_Pos) /*!< Select TMR3 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL1_TMR3SEL_LXT (0x1UL << CLK_CLKSEL1_TMR3SEL_Pos) /*!< Select TMR3 clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL1_TMR3SEL_LIRC (0x5UL << CLK_CLKSEL1_TMR3SEL_Pos) /*!< Select TMR3 clock source from low speed oscillator \hideinitializer */
#define CLK_CLKSEL1_TMR3SEL_HIRC (0x7UL << CLK_CLKSEL1_TMR3SEL_Pos) /*!< Select TMR3 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL1_TMR3SEL_PCLK1 (0x2UL << CLK_CLKSEL1_TMR3SEL_Pos) /*!< Select TMR3 clock source from PCLK1 \hideinitializer */
#define CLK_CLKSEL1_TMR3SEL_EXT (0x3UL << CLK_CLKSEL1_TMR3SEL_Pos) /*!< Select TMR3 clock source from external trigger \hideinitializer */
#define CLK_CLKSEL1_UART0SEL_HXT (0x0UL << CLK_CLKSEL1_UART0SEL_Pos) /*!< Select UART0 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL1_UART0SEL_LXT (0x2UL << CLK_CLKSEL1_UART0SEL_Pos) /*!< Select UART0 clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL1_UART0SEL_PLL (0x1UL << CLK_CLKSEL1_UART0SEL_Pos) /*!< Select UART0 clock source from PLL \hideinitializer */
#define CLK_CLKSEL1_UART0SEL_HIRC (0x3UL << CLK_CLKSEL1_UART0SEL_Pos) /*!< Select UART0 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL1_UART1SEL_HXT (0x0UL << CLK_CLKSEL1_UART1SEL_Pos) /*!< Select UART1 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL1_UART1SEL_LXT (0x2UL << CLK_CLKSEL1_UART1SEL_Pos) /*!< Select UART1 clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL1_UART1SEL_PLL (0x1UL << CLK_CLKSEL1_UART1SEL_Pos) /*!< Select UART1 clock source from PLL \hideinitializer */
#define CLK_CLKSEL1_UART1SEL_HIRC (0x3UL << CLK_CLKSEL1_UART1SEL_Pos) /*!< Select UART1 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL1_CLKOSEL_HXT (0x0UL << CLK_CLKSEL1_CLKOSEL_Pos) /*!< Select CLKO clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL1_CLKOSEL_LXT (0x1UL << CLK_CLKSEL1_CLKOSEL_Pos) /*!< Select CLKO clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL1_CLKOSEL_HIRC (0x3UL << CLK_CLKSEL1_CLKOSEL_Pos) /*!< Select CLKO clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL1_CLKOSEL_HCLK (0x2UL << CLK_CLKSEL1_CLKOSEL_Pos) /*!< Select CLKO clock source from HCLK \hideinitializer */
#define CLK_CLKSEL1_WWDTSEL_LIRC (0x3UL << CLK_CLKSEL1_WWDTSEL_Pos) /*!< Select WWDT clock source from low speed oscillator \hideinitializer */
#define CLK_CLKSEL1_WWDTSEL_HCLK_DIV2048 (0x2UL << CLK_CLKSEL1_WWDTSEL_Pos) /*!< Select WWDT clock source from HCLK/2048 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* CLKSEL2 constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKSEL2_SPI0SEL_HXT (0x0UL << CLK_CLKSEL2_SPI0SEL_Pos) /*!< Select SPI0 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL2_SPI0SEL_PLL (0x1UL << CLK_CLKSEL2_SPI0SEL_Pos) /*!< Select SPI0 clock source from PLL \hideinitializer */
#define CLK_CLKSEL2_SPI0SEL_HIRC (0x3UL << CLK_CLKSEL2_SPI0SEL_Pos) /*!< Select SPI0 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL2_SPI0SEL_PCLK0 (0x2UL << CLK_CLKSEL2_SPI0SEL_Pos) /*!< Select SPI0 clock source from PCLK0 \hideinitializer */
#define CLK_CLKSEL2_SPI1SEL_HXT (0x0UL << CLK_CLKSEL2_SPI1SEL_Pos) /*!< Select SPI1 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL2_SPI1SEL_PLL (0x1UL << CLK_CLKSEL2_SPI1SEL_Pos) /*!< Select SPI1 clock source from PLL \hideinitializer */
#define CLK_CLKSEL2_SPI1SEL_HIRC (0x3UL << CLK_CLKSEL2_SPI1SEL_Pos) /*!< Select SPI1 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL2_SPI1SEL_PCLK1 (0x2UL << CLK_CLKSEL2_SPI1SEL_Pos) /*!< Select SPI1 clock source from PCLK1 \hideinitializer */
#define CLK_CLKSEL2_SPI2SEL_HXT (0x0UL << CLK_CLKSEL2_SPI2SEL_Pos) /*!< Select SPI2 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL2_SPI2SEL_PLL (0x1UL << CLK_CLKSEL2_SPI2SEL_Pos) /*!< Select SPI2 clock source from PLL \hideinitializer */
#define CLK_CLKSEL2_SPI2SEL_HIRC (0x3UL << CLK_CLKSEL2_SPI2SEL_Pos) /*!< Select SPI2 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL2_SPI2SEL_PCLK0 (0x2UL << CLK_CLKSEL2_SPI2SEL_Pos) /*!< Select SPI2 clock source from PCLK0 \hideinitializer */
#define CLK_CLKSEL2_EPWM0SEL_PLL (0x0UL << CLK_CLKSEL2_EPWM0SEL_Pos) /*!< Select EPWM0 clock source from PLL \hideinitializer */
#define CLK_CLKSEL2_EPWM0SEL_PCLK0 (0x1UL << CLK_CLKSEL2_EPWM0SEL_Pos) /*!< Select EPWM0 clock source from PCLK0 \hideinitializer */
#define CLK_CLKSEL2_EPWM1SEL_PLL (0x0UL << CLK_CLKSEL2_EPWM1SEL_Pos) /*!< Select EPWM1 clock source from PLL \hideinitializer */
#define CLK_CLKSEL2_EPWM1SEL_PCLK1 (0x1UL << CLK_CLKSEL2_EPWM1SEL_Pos) /*!< Select EPWM1 clock source from PCLK1 \hideinitializer */
#define CLK_CLKSEL2_BPWM0SEL_PLL (0x0UL << CLK_CLKSEL2_BPWM0SEL_Pos) /*!< Select BPWM0 clock source from PLL \hideinitializer */
#define CLK_CLKSEL2_BPWM0SEL_PCLK0 (0x1UL << CLK_CLKSEL2_BPWM0SEL_Pos) /*!< Select BPWM0 clock source from PCLK0 \hideinitializer */
#define CLK_CLKSEL2_BPWM1SEL_PLL (0x0UL << CLK_CLKSEL2_BPWM1SEL_Pos) /*!< Select BPWM1 clock source from PLL \hideinitializer */
#define CLK_CLKSEL2_BPWM1SEL_PCLK1 (0x1UL << CLK_CLKSEL2_BPWM1SEL_Pos) /*!< Select BPWM1 clock source from PCLK1 \hideinitializer */
#define CLK_CLKSEL2_SPI3SEL_HXT (0x0UL << CLK_CLKSEL2_SPI3SEL_Pos) /*!< Select SPI3 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL2_SPI3SEL_PLL (0x1UL << CLK_CLKSEL2_SPI3SEL_Pos) /*!< Select SPI3 clock source from PLL \hideinitializer */
#define CLK_CLKSEL2_SPI3SEL_HIRC (0x3UL << CLK_CLKSEL2_SPI3SEL_Pos) /*!< Select SPI3 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL2_SPI3SEL_PCLK1 (0x2UL << CLK_CLKSEL2_SPI3SEL_Pos) /*!< Select SPI3 clock source from PCLK1 \hideinitializer */
#define CLK_CLKSEL2_SPI4SEL_HXT (0x0UL << CLK_CLKSEL2_SPI4SEL_Pos) /*!< Select SPI4 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL2_SPI4SEL_PLL (0x1UL << CLK_CLKSEL2_SPI4SEL_Pos) /*!< Select SPI4 clock source from PLL \hideinitializer */
#define CLK_CLKSEL2_SPI4SEL_HIRC (0x3UL << CLK_CLKSEL2_SPI4SEL_Pos) /*!< Select SPI4 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL2_SPI4SEL_PCLK0 (0x2UL << CLK_CLKSEL2_SPI4SEL_Pos) /*!< Select SPI4 clock source from PCLK0 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* CLKSEL3 constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKSEL3_SC0SEL_HXT (0x0UL << CLK_CLKSEL3_SC0SEL_Pos) /*!< Select SC0 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL3_SC0SEL_PLL (0x1UL << CLK_CLKSEL3_SC0SEL_Pos) /*!< Select SC0 clock source from PLL \hideinitializer */
#define CLK_CLKSEL3_SC0SEL_HIRC (0x3UL << CLK_CLKSEL3_SC0SEL_Pos) /*!< Select SC0 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL3_SC0SEL_PCLK0 (0x2UL << CLK_CLKSEL3_SC0SEL_Pos) /*!< Select SC0 clock source from PCLK0 \hideinitializer */
#define CLK_CLKSEL3_SC1SEL_HXT (0x0UL << CLK_CLKSEL3_SC1SEL_Pos) /*!< Select SC1 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL3_SC1SEL_PLL (0x1UL << CLK_CLKSEL3_SC1SEL_Pos) /*!< Select SC1 clock source from PLL \hideinitializer */
#define CLK_CLKSEL3_SC1SEL_HIRC (0x3UL << CLK_CLKSEL3_SC1SEL_Pos) /*!< Select SC1 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL3_SC1SEL_PCLK1 (0x2UL << CLK_CLKSEL3_SC1SEL_Pos) /*!< Select SC1 clock source from PCLK1 \hideinitializer */
#define CLK_CLKSEL3_SC2SEL_HXT (0x0UL << CLK_CLKSEL3_SC2SEL_Pos) /*!< Select SC2 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL3_SC2SEL_PLL (0x1UL << CLK_CLKSEL3_SC2SEL_Pos) /*!< Select SC2 clock source from PLL \hideinitializer */
#define CLK_CLKSEL3_SC2SEL_HIRC (0x3UL << CLK_CLKSEL3_SC2SEL_Pos) /*!< Select SC2 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL3_SC2SEL_PCLK0 (0x2UL << CLK_CLKSEL3_SC2SEL_Pos) /*!< Select SC2 clock source from PCLK0 \hideinitializer */
#define CLK_CLKSEL3_RTCSEL_LXT (0x0UL << CLK_CLKSEL3_RTCSEL_Pos) /*!< Select RTC clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL3_RTCSEL_LIRC (0x1UL << CLK_CLKSEL3_RTCSEL_Pos) /*!< Select RTC clock source from low speed oscillator \hideinitializer */
#define CLK_CLKSEL3_I2S0SEL_HXT (0x0UL << CLK_CLKSEL3_I2S0SEL_Pos) /*!< Select I2S0 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL3_I2S0SEL_PLL (0x1UL << CLK_CLKSEL3_I2S0SEL_Pos) /*!< Select I2S0 clock source from PLL \hideinitializer */
#define CLK_CLKSEL3_I2S0SEL_HIRC (0x3UL << CLK_CLKSEL3_I2S0SEL_Pos) /*!< Select I2S0 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL3_I2S0SEL_PCLK0 (0x2UL << CLK_CLKSEL3_I2S0SEL_Pos) /*!< Select I2S0 clock source from PCLK0 \hideinitializer */
#define CLK_CLKSEL3_UART2SEL_HXT (0x0UL << CLK_CLKSEL3_UART2SEL_Pos) /*!< Select UART2 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL3_UART2SEL_LXT (0x2UL << CLK_CLKSEL3_UART2SEL_Pos) /*!< Select UART2 clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL3_UART2SEL_PLL (0x1UL << CLK_CLKSEL3_UART2SEL_Pos) /*!< Select UART2 clock source from PLL \hideinitializer */
#define CLK_CLKSEL3_UART2SEL_HIRC (0x3UL << CLK_CLKSEL3_UART2SEL_Pos) /*!< Select UART2 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL3_UART3SEL_HXT (0x0UL << CLK_CLKSEL3_UART3SEL_Pos) /*!< Select UART3 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL3_UART3SEL_LXT (0x2UL << CLK_CLKSEL3_UART3SEL_Pos) /*!< Select UART3 clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL3_UART3SEL_PLL (0x1UL << CLK_CLKSEL3_UART3SEL_Pos) /*!< Select UART3 clock source from PLL \hideinitializer */
#define CLK_CLKSEL3_UART3SEL_HIRC (0x3UL << CLK_CLKSEL3_UART3SEL_Pos) /*!< Select UART3 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL3_UART4SEL_HXT (0x0UL << CLK_CLKSEL3_UART4SEL_Pos) /*!< Select UART4 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL3_UART4SEL_LXT (0x2UL << CLK_CLKSEL3_UART4SEL_Pos) /*!< Select UART4 clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL3_UART4SEL_PLL (0x1UL << CLK_CLKSEL3_UART4SEL_Pos) /*!< Select UART4 clock source from PLL \hideinitializer */
#define CLK_CLKSEL3_UART4SEL_HIRC (0x3UL << CLK_CLKSEL3_UART4SEL_Pos) /*!< Select UART4 clock source from high speed oscillator \hideinitializer */
#define CLK_CLKSEL3_UART5SEL_HXT (0x0UL << CLK_CLKSEL3_UART5SEL_Pos) /*!< Select UART5 clock source from high speed crystal \hideinitializer */
#define CLK_CLKSEL3_UART5SEL_LXT (0x2UL << CLK_CLKSEL3_UART5SEL_Pos) /*!< Select UART5 clock source from low speed crystal \hideinitializer */
#define CLK_CLKSEL3_UART5SEL_PLL (0x1UL << CLK_CLKSEL3_UART5SEL_Pos) /*!< Select UART5 clock source from PLL \hideinitializer */
#define CLK_CLKSEL3_UART5SEL_HIRC (0x3UL << CLK_CLKSEL3_UART5SEL_Pos) /*!< Select UART5 clock source from high speed oscillator \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* CLKDIV0 constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKDIV0_HCLK(x) (((x) - 1UL) << CLK_CLKDIV0_HCLKDIV_Pos) /*!< CLKDIV0 Setting for HCLK clock divider. It could be 1~16 \hideinitializer */
#define CLK_CLKDIV0_USB(x) (((x) - 1UL) << CLK_CLKDIV0_USBDIV_Pos) /*!< CLKDIV0 Setting for USB clock divider. It could be 1~16 \hideinitializer */
#define CLK_CLKDIV0_SDH0(x) (((x) - 1UL) << CLK_CLKDIV0_SDH0DIV_Pos) /*!< CLKDIV0 Setting for SDH0 clock divider. It could be 1~256 \hideinitializer */
#define CLK_CLKDIV0_UART0(x) (((x) - 1UL) << CLK_CLKDIV0_UART0DIV_Pos) /*!< CLKDIV0 Setting for UART0 clock divider. It could be 1~16 \hideinitializer */
#define CLK_CLKDIV0_UART1(x) (((x) - 1UL) << CLK_CLKDIV0_UART1DIV_Pos) /*!< CLKDIV0 Setting for UART1 clock divider. It could be 1~16 \hideinitializer */
#define CLK_CLKDIV0_EADC(x) (((x) - 1UL) << CLK_CLKDIV0_EADCDIV_Pos) /*!< CLKDIV0 Setting for EADC clock divider. It could be 1~256 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* CLKDIV1 constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKDIV1_SC0(x) (((x) - 1UL) << CLK_CLKDIV1_SC0DIV_Pos) /*!< CLKDIV1 Setting for SC0 clock divider. It could be 1~256 \hideinitializer */
#define CLK_CLKDIV1_SC1(x) (((x) - 1UL) << CLK_CLKDIV1_SC1DIV_Pos) /*!< CLKDIV1 Setting for SC1 clock divider. It could be 1~256 \hideinitializer */
#define CLK_CLKDIV1_SC2(x) (((x) - 1UL) << CLK_CLKDIV1_SC2DIV_Pos) /*!< CLKDIV1 Setting for SC2 clock divider. It could be 1~256 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* CLKDIV3 constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKDIV3_EMAC(x) (((x) - 1UL) << CLK_CLKDIV3_EMACDIV_Pos) /*!< CLKDIV3 Setting for EMAC clock divider. It could be 1~256 \hideinitializer */
#define CLK_CLKDIV3_SDH1(x) (((x) - 1UL) << CLK_CLKDIV3_SDH1DIV_Pos) /*!< CLKDIV3 Setting for SDH1 clock divider. It could be 1~256 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* CLKDIV4 constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_CLKDIV4_UART2(x) (((x) - 1UL) << CLK_CLKDIV4_UART2DIV_Pos) /*!< CLKDIV4 Setting for UART2 clock divider. It could be 1~16 \hideinitializer */
#define CLK_CLKDIV4_UART3(x) (((x) - 1UL) << CLK_CLKDIV4_UART3DIV_Pos) /*!< CLKDIV4 Setting for UART3 clock divider. It could be 1~16 \hideinitializer */
#define CLK_CLKDIV4_UART4(x) (((x) - 1UL) << CLK_CLKDIV4_UART4DIV_Pos) /*!< CLKDIV4 Setting for UART4 clock divider. It could be 1~16 \hideinitializer */
#define CLK_CLKDIV4_UART5(x) (((x) - 1UL) << CLK_CLKDIV4_UART5DIV_Pos) /*!< CLKDIV4 Setting for UART5 clock divider. It could be 1~16 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* PCLKDIV constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#if(1)
#define CLK_PCLKDIV_PCLK0DIV1 (0x0UL << CLK_PCLKDIV_APB0DIV_Pos) /*!< PCLKDIV Setting for PCLK0 = HCLK \hideinitializer */
#define CLK_PCLKDIV_PCLK0DIV2 (0x1UL << CLK_PCLKDIV_APB0DIV_Pos) /*!< PCLKDIV Setting for PCLK0 = 1/2 HCLK \hideinitializer */
#define CLK_PCLKDIV_PCLK0DIV4 (0x2UL << CLK_PCLKDIV_APB0DIV_Pos) /*!< PCLKDIV Setting for PCLK0 = 1/4 HCLK \hideinitializer */
#define CLK_PCLKDIV_PCLK0DIV8 (0x3UL << CLK_PCLKDIV_APB0DIV_Pos) /*!< PCLKDIV Setting for PCLK0 = 1/8 HCLK \hideinitializer */
#define CLK_PCLKDIV_PCLK0DIV16 (0x4UL << CLK_PCLKDIV_APB0DIV_Pos) /*!< PCLKDIV Setting for PCLK0 = 1/16 HCLK \hideinitializer */
#define CLK_PCLKDIV_PCLK1DIV1 (0x0UL << CLK_PCLKDIV_APB1DIV_Pos) /*!< PCLKDIV Setting for PCLK1 = HCLK \hideinitializer */
#define CLK_PCLKDIV_PCLK1DIV2 (0x1UL << CLK_PCLKDIV_APB1DIV_Pos) /*!< PCLKDIV Setting for PCLK1 = 1/2 HCLK \hideinitializer */
#define CLK_PCLKDIV_PCLK1DIV4 (0x2UL << CLK_PCLKDIV_APB1DIV_Pos) /*!< PCLKDIV Setting for PCLK1 = 1/4 HCLK \hideinitializer */
#define CLK_PCLKDIV_PCLK1DIV8 (0x3UL << CLK_PCLKDIV_APB1DIV_Pos) /*!< PCLKDIV Setting for PCLK1 = 1/8 HCLK \hideinitializer */
#define CLK_PCLKDIV_PCLK1DIV16 (0x4UL << CLK_PCLKDIV_APB1DIV_Pos) /*!< PCLKDIV Setting for PCLK1 = 1/16 HCLK \hideinitializer */
#endif
/*---------------------------------------------------------------------------------------------------------*/
/* PLLCTL constant definitions. PLL = FIN * 2 * NF / NR / NO */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_PLLCTL_PLLSRC_HXT 0x00000000UL /*!< For PLL clock source is HXT. 4MHz < FIN/NR < 8MHz \hideinitializer */
#define CLK_PLLCTL_PLLSRC_HIRC 0x00080000UL /*!< For PLL clock source is HIRC. 4MHz < FIN/NR < 8MHz \hideinitializer */
#define CLK_PLLCTL_NF(x) (((x)-2UL)) /*!< x must be constant and 2 <= x <= 513. 200MHz < FIN*2*NF/NR < 500MHz. \hideinitializer */
#define CLK_PLLCTL_NR(x) (((x)-1UL)<<9) /*!< x must be constant and 1 <= x <= 32. 4MHz < FIN/NR < 8MHz \hideinitializer */
#define CLK_PLLCTL_NO_1 0x0000UL /*!< For output divider is 1 \hideinitializer */
#define CLK_PLLCTL_NO_2 0x4000UL /*!< For output divider is 2 \hideinitializer */
#define CLK_PLLCTL_NO_4 0xC000UL /*!< For output divider is 4 \hideinitializer */
#define CLK_PLLCTL_72MHz_HXT (CLK_PLLCTL_PLLSRC_HXT | CLK_PLLCTL_NR(3UL) | CLK_PLLCTL_NF( 36UL) | CLK_PLLCTL_NO_4) /*!< Predefined PLLCTL setting for 72MHz PLL output with HXT(12MHz X'tal) \hideinitializer */
#define CLK_PLLCTL_80MHz_HXT (CLK_PLLCTL_PLLSRC_HXT | CLK_PLLCTL_NR(3UL) | CLK_PLLCTL_NF( 40UL) | CLK_PLLCTL_NO_4) /*!< Predefined PLLCTL setting for 80MHz PLL output with HXT(12MHz X'tal) \hideinitializer */
#define CLK_PLLCTL_144MHz_HXT (CLK_PLLCTL_PLLSRC_HXT | CLK_PLLCTL_NR(2UL) | CLK_PLLCTL_NF( 24UL) | CLK_PLLCTL_NO_2) /*!< Predefined PLLCTL setting for 144MHz PLL output with HXT(12MHz X'tal) \hideinitializer */
#define CLK_PLLCTL_160MHz_HXT (CLK_PLLCTL_PLLSRC_HXT | CLK_PLLCTL_NR(3UL) | CLK_PLLCTL_NF( 40UL) | CLK_PLLCTL_NO_2) /*!< Predefined PLLCTL setting for 160MHz PLL output with HXT(12MHz X'tal) \hideinitializer */
#define CLK_PLLCTL_192MHz_HXT (CLK_PLLCTL_PLLSRC_HXT | CLK_PLLCTL_NR(2UL) | CLK_PLLCTL_NF( 32UL) | CLK_PLLCTL_NO_2) /*!< Predefined PLLCTL setting for 192MHz PLL output with HXT(12MHz X'tal) \hideinitializer */
#define CLK_PLLCTL_72MHz_HIRC (CLK_PLLCTL_PLLSRC_HIRC | CLK_PLLCTL_NR(3UL) | CLK_PLLCTL_NF( 36UL) | CLK_PLLCTL_NO_4) /*!< Predefined PLLCTL setting for 72MHz PLL output with HIRC(12MHz IRC) \hideinitializer */
#define CLK_PLLCTL_80MHz_HIRC (CLK_PLLCTL_PLLSRC_HIRC | CLK_PLLCTL_NR(3UL) | CLK_PLLCTL_NF( 40UL) | CLK_PLLCTL_NO_4) /*!< Predefined PLLCTL setting for 80MHz PLL output with HIRC(12MHz IRC) \hideinitializer */
#define CLK_PLLCTL_144MHz_HIRC (CLK_PLLCTL_PLLSRC_HIRC | CLK_PLLCTL_NR(2UL) | CLK_PLLCTL_NF( 24UL) | CLK_PLLCTL_NO_2) /*!< Predefined PLLCTL setting for 144MHz PLL output with HIRC(12MHz IRC) \hideinitializer */
#define CLK_PLLCTL_160MHz_HIRC (CLK_PLLCTL_PLLSRC_HIRC | CLK_PLLCTL_NR(3UL) | CLK_PLLCTL_NF( 40UL) | CLK_PLLCTL_NO_2) /*!< Predefined PLLCTL setting for 160MHz PLL output with HIRC(12MHz IRC) \hideinitializer */
#define CLK_PLLCTL_192MHz_HIRC (CLK_PLLCTL_PLLSRC_HIRC | CLK_PLLCTL_NR(2UL) | CLK_PLLCTL_NF( 32UL) | CLK_PLLCTL_NO_2) /*!< Predefined PLLCTL setting for 192MHz PLL output with HIRC(12MHz IRC) \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* MODULE constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
/* APBCLK(31:30)|CLKSEL(29:28)|CLKSEL_Msk(27:25) |CLKSEL_Pos(24:20)|CLKDIV(19:18)|CLKDIV_Msk(17:10)|CLKDIV_Pos(9:5)|IP_EN_Pos(4:0) */
#define MODULE_APBCLK(x) (((x) >>30) & 0x3UL) /*!< Calculate AHBCLK/APBCLK offset on MODULE index, 0x0:AHBCLK, 0x1:APBCLK0, 0x2:APBCLK1 \hideinitializer */
#define MODULE_CLKSEL(x) (((x) >>28) & 0x3UL) /*!< Calculate CLKSEL offset on MODULE index, 0x0:CLKSEL0, 0x1:CLKSEL1, 0x2:CLKSEL2, 0x3:CLKSEL3 \hideinitializer */
#define MODULE_CLKSEL_Msk(x) (((x) >>25) & 0x7UL) /*!< Calculate CLKSEL mask offset on MODULE index \hideinitializer */
#define MODULE_CLKSEL_Pos(x) (((x) >>20) & 0x1fUL) /*!< Calculate CLKSEL position offset on MODULE index \hideinitializer */
#define MODULE_CLKDIV(x) (((x) >>18) & 0x3UL) /*!< Calculate APBCLK CLKDIV on MODULE index, 0x0:CLKDIV0, 0x1:CLKDIV1, 0x2:CLKDIV3, 0x3:CLKDIV4 \hideinitializer */
#define MODULE_CLKDIV_Msk(x) (((x) >>10) & 0xffUL) /*!< Calculate CLKDIV mask offset on MODULE index \hideinitializer */
#define MODULE_CLKDIV_Pos(x) (((x) >>5 ) & 0x1fUL) /*!< Calculate CLKDIV position offset on MODULE index \hideinitializer */
#define MODULE_IP_EN_Pos(x) (((x) >>0 ) & 0x1fUL) /*!< Calculate APBCLK offset on MODULE index \hideinitializer */
#define MODULE_NoMsk 0x0UL /*!< Not mask on MODULE index \hideinitializer */
#define NA MODULE_NoMsk /*!< Not Available \hideinitializer */
#define MODULE_APBCLK_ENC(x) (((x) & 0x03UL) << 30) /*!< MODULE index, 0x0:AHBCLK, 0x1:APBCLK0, 0x2:APBCLK1 \hideinitializer */
#define MODULE_CLKSEL_ENC(x) (((x) & 0x03UL) << 28) /*!< CLKSEL offset on MODULE index, 0x0:CLKSEL0, 0x1:CLKSEL1, 0x2:CLKSEL2, 0x3:CLKSEL3 \hideinitializer */
#define MODULE_CLKSEL_Msk_ENC(x) (((x) & 0x07UL) << 25) /*!< CLKSEL mask offset on MODULE index \hideinitializer */
#define MODULE_CLKSEL_Pos_ENC(x) (((x) & 0x1fUL) << 20) /*!< CLKSEL position offset on MODULE index \hideinitializer */
#define MODULE_CLKDIV_ENC(x) (((x) & 0x03UL) << 18) /*!< APBCLK CLKDIV on MODULE index, 0x0:CLKDIV0, 0x1:CLKDIV1, 0x2:CLKDIV3, 0x3:CLKDIV4 \hideinitializer */
#define MODULE_CLKDIV_Msk_ENC(x) (((x) & 0xffUL) << 10) /*!< CLKDIV mask offset on MODULE index \hideinitializer */
#define MODULE_CLKDIV_Pos_ENC(x) (((x) & 0x1fUL) << 5) /*!< CLKDIV position offset on MODULE index \hideinitializer */
#define MODULE_IP_EN_Pos_ENC(x) (((x) & 0x1fUL) << 0) /*!< AHBCLK/APBCLK offset on MODULE index \hideinitializer */
#define PDMA_MODULE ((0UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(1UL<<0)) /*!< PDMA Module \hideinitializer */
#define ISP_MODULE ((0UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(2UL<<0)) /*!< ISP Module \hideinitializer */
#define EBI_MODULE ((0UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(3UL<<0)) /*!< EBI Module \hideinitializer */
#define USBH_MODULE ((0UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(16UL<<0)) /*!< USBH Module \hideinitializer */
#define EMAC_MODULE ((0UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(2UL<<18) |(0xFFUL<<10) |(16UL<<5) |(5UL<<0)) /*!< EMAC Module \hideinitializer */
#define SDH0_MODULE ((0UL<<30)|(0UL<<28) |(0x3UL<<25) |(20UL<<20) |(0UL<<18) |(0xFFUL<<10) |(24UL<<5) |(6UL<<0)) /*!< SDH0 Module \hideinitializer */
#define CRC_MODULE ((0UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(7UL<<0)) /*!< CRC Module \hideinitializer */
#define HSUSBD_MODULE ((0UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(10UL<<0)) /*!< HSUSBD Module \hideinitializer */
#define CRPT_MODULE ((0UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(12UL<<0)) /*!< CRPT Module \hideinitializer */
#define SPIM_MODULE ((0UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(14UL<<0)) /*!< SPIM Module \hideinitializer */
#define SDH1_MODULE ((0UL<<30)|(0UL<<28) |(0x3UL<<25) |(22UL<<20) |(2UL<<18) |(0xFFUL<<10) |(24UL<<5) |(17UL<<0)) /*!< SDH1 Module \hideinitializer */
#define WDT_MODULE ((1UL<<30)|(1UL<<28) |(0x3UL<<25) |(0UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(0UL<<0)) /*!< WDT Module \hideinitializer */
#define RTC_MODULE ((1UL<<30)|(3UL<<28) |(0x1UL<<25) |(8UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(1UL<<0)) /*!< RTC Module \hideinitializer */
#define TMR0_MODULE ((1UL<<30)|(1UL<<28) |(0x7UL<<25) |(8UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(2UL<<0)) /*!< TMR0 Module \hideinitializer */
#define TMR1_MODULE ((1UL<<30)|(1UL<<28) |(0x7UL<<25) |(12UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(3UL<<0)) /*!< TMR1 Module \hideinitializer */
#define TMR2_MODULE ((1UL<<30)|(1UL<<28) |(0x7UL<<25) |(16UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(4UL<<0)) /*!< TMR2 Module \hideinitializer */
#define TMR3_MODULE ((1UL<<30)|(1UL<<28) |(0x7UL<<25) |(20UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(5UL<<0)) /*!< TMR3 Module \hideinitializer */
#define CLKO_MODULE ((1UL<<30)|(1UL<<28) |(0x3UL<<25) |(28UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(6UL<<0)) /*!< CLKO Module \hideinitializer */
#define WWDT_MODULE ((1UL<<30)|(1UL<<28) |(0x3UL<<25) |(30UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(0UL<<0)) /*!< WWDT Module \hideinitializer */
#define ACMP01_MODULE ((1UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(7UL<<0)) /*!< ACMP01 Module \hideinitializer */
#define I2C0_MODULE ((1UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(8UL<<0)) /*!< I2C0 Module \hideinitializer */
#define I2C1_MODULE ((1UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(9UL<<0)) /*!< I2C1 Module \hideinitializer */
#define I2C2_MODULE ((1UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(10UL<<0)) /*!< I2C2 Module \hideinitializer */
#define SPI0_MODULE ((1UL<<30)|(2UL<<28) |(0x3UL<<25) |(2UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(12UL<<0)) /*!< SPI0 Module \hideinitializer */
#define SPI1_MODULE ((1UL<<30)|(2UL<<28) |(0x3UL<<25) |(4UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(13UL<<0)) /*!< SPI1 Module \hideinitializer */
#define SPI2_MODULE ((1UL<<30)|(2UL<<28) |(0x3UL<<25) |(6UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(14UL<<0)) /*!< SPI2 Module \hideinitializer */
#define SPI3_MODULE ((1UL<<30)|(2UL<<28) |(0x3UL<<25) |(10UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(15UL<<0)) /*!< SPI3 Module \hideinitializer */
#define UART0_MODULE ((1UL<<30)|(1UL<<28) |(0x3UL<<25) |(24UL<<20) |(0UL<<18) |(0xFUL<<10) |(8UL<<5) |(16UL<<0)) /*!< UART0 Module \hideinitializer */
#define UART1_MODULE ((1UL<<30)|(1UL<<28) |(0x3UL<<25) |(26UL<<20) |(0UL<<18) |(0xFUL<<10) |(12UL<<5) |(17UL<<0)) /*!< UART1 Module \hideinitializer */
#define UART2_MODULE ((1UL<<30)|(3UL<<28) |(0x3UL<<25) |(24UL<<20) |(3UL<<18) |(0xFUL<<10) |(0UL<<5) |(18UL<<0)) /*!< UART2 Module \hideinitializer */
#define UART3_MODULE ((1UL<<30)|(3UL<<28) |(0x3UL<<25) |(26UL<<20) |(3UL<<18) |(0xFUL<<10) |(4UL<<5) |(19UL<<0)) /*!< UART3 Module \hideinitializer */
#define UART4_MODULE ((1UL<<30)|(3UL<<28) |(0x3UL<<25) |(28UL<<20) |(3UL<<18) |(0xFUL<<10) |(8UL<<5) |(20UL<<0)) /*!< UART4 Module \hideinitializer */
#define UART5_MODULE ((1UL<<30)|(3UL<<28) |(0x3UL<<25) |(30UL<<20) |(3UL<<18) |(0xFUL<<10) |(12UL<<5) |(21UL<<0)) /*!< UART5 Module \hideinitializer */
#define CAN0_MODULE ((1UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(24UL<<0)) /*!< CAN0 Module \hideinitializer */
#define CAN1_MODULE ((1UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(25UL<<0)) /*!< CAN1 Module \hideinitializer */
#define OTG_MODULE ((1UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(26UL<<0)) /*!< OTG Module \hideinitializer */
#define USBD_MODULE ((1UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(27UL<<0)) /*!< USBD Module \hideinitializer */
#define EADC_MODULE ((1UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(0UL<<18) |(0xFFUL<<10) |(16UL<<5) |(28UL<<0)) /*!< EADC Module \hideinitializer */
#define I2S0_MODULE ((1UL<<30)|(3UL<<28) |(0x3UL<<25) |(16UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(29UL<<0)) /*!< I2S0 Module \hideinitializer */
#define HSOTG_MODULE ((1UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(30UL<<0)) /*!< HSOTG Module \hideinitializer */
#define SC0_MODULE ((2UL<<30)|(3UL<<28) |(0x3UL<<25) |(0UL<<20) |(1UL<<18) |(0xFFUL<<10) |(0UL<<5) |(0UL<<0)) /*!< SC0 Module \hideinitializer */
#define SC1_MODULE ((2UL<<30)|(3UL<<28) |(0x3UL<<25) |(2UL<<20) |(1UL<<18) |(0xFFUL<<10) |(8UL<<5) |(1UL<<0)) /*!< SC1 Module \hideinitializer */
#define SC2_MODULE ((2UL<<30)|(3UL<<28) |(0x3UL<<25) |(4UL<<20) |(1UL<<18) |(0xFFUL<<10) |(16UL<<5) |(2UL<<0)) /*!< SC2 Module \hideinitializer */
#define SPI4_MODULE ((2UL<<30)|(2UL<<28) |(0x3UL<<25) |(12UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(6UL<<0)) /*!< SPI4 Module \hideinitializer */
#define USCI0_MODULE ((2UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(8UL<<0)) /*!< USCI0 Module \hideinitializer */
#define USCI1_MODULE ((2UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(9UL<<0)) /*!< USCI1 Module \hideinitializer */
#define DAC_MODULE ((2UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(12UL<<0)) /*!< DAC Module \hideinitializer */
#define EPWM0_MODULE ((2UL<<30)|(2UL<<28) |(0x1UL<<25) |(0UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(16UL<<0)) /*!< EPWM0 Module \hideinitializer */
#define EPWM1_MODULE ((2UL<<30)|(2UL<<28) |(0x1UL<<25) |(1UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(17UL<<0)) /*!< EPWM1 Module \hideinitializer */
#define BPWM0_MODULE ((2UL<<30)|(2UL<<28) |(0x1UL<<25) |(8UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(18UL<<0)) /*!< BPWM0 Module \hideinitializer */
#define BPWM1_MODULE ((2UL<<30)|(2UL<<28) |(0x1UL<<25) |(9UL<<20) |(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(19UL<<0)) /*!< BPWM1 Module \hideinitializer */
#define QEI0_MODULE ((2UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(22UL<<0)) /*!< QEI0 Module \hideinitializer */
#define QEI1_MODULE ((2UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(23UL<<0)) /*!< QEI1 Module \hideinitializer */
#define ECAP0_MODULE ((2UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(26UL<<0)) /*!< ECAP0 Module \hideinitializer */
#define ECAP1_MODULE ((2UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(27UL<<0)) /*!< ECAP1 Module \hideinitializer */
#define OPA_MODULE ((2UL<<30)|(MODULE_NoMsk<<28)|(MODULE_NoMsk<<25)|(MODULE_NoMsk<<20)|(MODULE_NoMsk<<18)|(MODULE_NoMsk<<10)|(MODULE_NoMsk<<5)|(30UL<<0)) /*!< OPA Module \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* PDMSEL constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_PMUCTL_PDMSEL_PD (0x0UL << CLK_PMUCTL_PDMSEL_Pos) /*!< Select power down mdoe is Power-down mode \hideinitializer */
#define CLK_PMUCTL_PDMSEL_LLPD (0x1UL << CLK_PMUCTL_PDMSEL_Pos) /*!< Select power down mdoe is Low leakage Power-down mode \hideinitializer */
#define CLK_PMUCTL_PDMSEL_FWPD (0x2UL << CLK_PMUCTL_PDMSEL_Pos) /*!< Select power down mdoe is Fast wake-up Power-down mode \hideinitializer */
#define CLK_PMUCTL_PDMSEL_SPD0 (0x4UL << CLK_PMUCTL_PDMSEL_Pos) /*!< Select power down mdoe is Standby Power-down mode 0 \hideinitializer */
#define CLK_PMUCTL_PDMSEL_SPD1 (0x5UL << CLK_PMUCTL_PDMSEL_Pos) /*!< Select power down mdoe is Standby Power-down mode 1 \hideinitializer */
#define CLK_PMUCTL_PDMSEL_DPD (0x6UL << CLK_PMUCTL_PDMSEL_Pos) /*!< Select power down mdoe is Deep Power-down mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* WKTMRIS constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_PMUCTL_WKTMRIS_128 (0x0UL << CLK_PMUCTL_WKTMRIS_Pos) /*!< Select Wake-up Timer Time-out Interval is 128 OSC10K clocks (12.8 ms) \hideinitializer */
#define CLK_PMUCTL_WKTMRIS_256 (0x1UL << CLK_PMUCTL_WKTMRIS_Pos) /*!< Select Wake-up Timer Time-out Interval is 256 OSC10K clocks (25.6 ms) \hideinitializer */
#define CLK_PMUCTL_WKTMRIS_512 (0x2UL << CLK_PMUCTL_WKTMRIS_Pos) /*!< Select Wake-up Timer Time-out Interval is 512 OSC10K clocks (51.2 ms) \hideinitializer */
#define CLK_PMUCTL_WKTMRIS_1024 (0x3UL << CLK_PMUCTL_WKTMRIS_Pos) /*!< Select Wake-up Timer Time-out Interval is 1024 OSC10K clocks (102.4ms) \hideinitializer */
#define CLK_PMUCTL_WKTMRIS_4096 (0x4UL << CLK_PMUCTL_WKTMRIS_Pos) /*!< Select Wake-up Timer Time-out Interval is 4096 OSC10K clocks (409.6ms) \hideinitializer */
#define CLK_PMUCTL_WKTMRIS_8192 (0x5UL << CLK_PMUCTL_WKTMRIS_Pos) /*!< Select Wake-up Timer Time-out Interval is 8192 OSC10K clocks (819.2ms) \hideinitializer */
#define CLK_PMUCTL_WKTMRIS_16384 (0x6UL << CLK_PMUCTL_WKTMRIS_Pos) /*!< Select Wake-up Timer Time-out Interval is 16384 OSC10K clocks (1638.4ms) \hideinitializer */
#define CLK_PMUCTL_WKTMRIS_65536 (0x7UL << CLK_PMUCTL_WKTMRIS_Pos) /*!< Select Wake-up Timer Time-out Interval is 65536 OSC10K clocks (6553.6ms) \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* SWKDBCLKSEL constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_SWKDBCTL_SWKDBCLKSEL_1 (0x0UL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 1 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_2 (0x1UL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 2 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_4 (0x2UL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 4 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_8 (0x3UL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 8 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_16 (0x4UL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 16 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_32 (0x5UL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 32 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_64 (0x6UL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 64 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_128 (0x7UL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 128 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_256 (0x8UL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 256 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_2x256 (0x9UL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 2x256 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_4x256 (0xaUL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 4x256 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_8x256 (0xbUL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 8x256 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_16x256 (0xcUL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 16x256 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_32x256 (0xdUL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 32x256 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_64x256 (0xeUL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 64x256 clocks \hideinitializer */
#define CLK_SWKDBCTL_SWKDBCLKSEL_128x256 (0xfUL << CLK_SWKDBCTL_SWKDBCLKSEL_Pos) /*!< Select Standby Power-down Pin De-bounce Sampling Cycle is 128x256 clocks \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* DPD Pin Rising/Falling Edge Wake-up Enable constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_DPDWKPIN_DISABLE (0x0UL << CLK_PMUCTL_WKPINEN_Pos) /*!< Disable Wake-up pin at Deep Power-down mode \hideinitializer */
#define CLK_DPDWKPIN_RISING (0x1UL << CLK_PMUCTL_WKPINEN_Pos) /*!< Enable Wake-up pin rising edge at Deep Power-down mode \hideinitializer */
#define CLK_DPDWKPIN_FALLING (0x2UL << CLK_PMUCTL_WKPINEN_Pos) /*!< Enable Wake-up pin falling edge at Deep Power-down mode \hideinitializer */
#define CLK_DPDWKPIN_BOTHEDGE (0x3UL << CLK_PMUCTL_WKPINEN_Pos) /*!< Enable Wake-up pin both edge at Deep Power-down mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* SPD Pin Rising/Falling Edge Wake-up Enable constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define CLK_SPDWKPIN_ENABLE (0x1UL << 0) /*!< Enable Standby Power-down Pin Wake-up \hideinitializer */
#define CLK_SPDWKPIN_RISING (0x1UL << 1) /*!< Standby Power-down Wake-up on Standby Power-down Pin rising edge \hideinitializer */
#define CLK_SPDWKPIN_FALLING (0x1UL << 2) /*!< Standby Power-down Wake-up on Standby Power-down Pin falling edge \hideinitializer */
#define CLK_SPDWKPIN_DEBOUNCEEN (0x1UL << 8) /*!< Enable Standby power-down pin De-bounce function \hideinitializer */
#define CLK_SPDWKPIN_DEBOUNCEDIS (0x0UL << 8) /*!< Disable Standby power-down pin De-bounce function \hideinitializer */
#define CLK_DISABLE_WKTMR(void) (CLK->PMUCTL &= ~CLK_PMUCTL_WKTMREN_Msk) /*!< Disable Wake-up timer at Standby or Deep Power-down mode \hideinitializer */
#define CLK_ENABLE_WKTMR(void) (CLK->PMUCTL |= CLK_PMUCTL_WKTMREN_Msk) /*!< Enable Wake-up timer at Standby or Deep Power-down mode \hideinitializer */
#define CLK_DISABLE_DPDWKPIN(void) (CLK->PMUCTL &= ~CLK_PMUCTL_WKPINEN_Msk) /*!< Disable Wake-up pin at Deep Power-down mode \hideinitializer */
#define CLK_DISABLE_SPDACMP(void) (CLK->PMUCTL &= ~CLK_PMUCTL_ACMPSPWK_Msk) /*!< Disable ACMP wake-up at Standby Power-down mode \hideinitializer */
#define CLK_ENABLE_SPDACMP(void) (CLK->PMUCTL |= CLK_PMUCTL_ACMPSPWK_Msk) /*!< Enable ACMP wake-up at Standby Power-down mode \hideinitializer */
#define CLK_DISABLE_RTCWK(void) (CLK->PMUCTL &= ~CLK_PMUCTL_RTCWKEN_Msk) /*!< Disable RTC Wake-up at Standby or Deep Power-down mode \hideinitializer */
#define CLK_ENABLE_RTCWK(void) (CLK->PMUCTL |= CLK_PMUCTL_RTCWKEN_Msk) /*!< Enable RTC Wake-up at Standby or Deep Power-down mode \hideinitializer */
/*@}*/ /* end of group M480_CLK_EXPORTED_CONSTANTS */
/** @addtogroup M480_CLK_EXPORTED_FUNCTIONS CLK Exported Functions
@{
*/
/**
* @brief Set Wake-up Timer Time-out Interval
*
* @param[in] u32Interval The de-bounce sampling cycle selection. It could be
* - \ref CLK_PMUCTL_WKTMRIS_128
* - \ref CLK_PMUCTL_WKTMRIS_256
* - \ref CLK_PMUCTL_WKTMRIS_512
* - \ref CLK_PMUCTL_WKTMRIS_1024
* - \ref CLK_PMUCTL_WKTMRIS_4096
* - \ref CLK_PMUCTL_WKTMRIS_8192
* - \ref CLK_PMUCTL_WKTMRIS_16384
* - \ref CLK_PMUCTL_WKTMRIS_65536
*
* @return None
*
* @details This function set Wake-up Timer Time-out Interval.
*
* \hideinitializer
*/
#define CLK_SET_WKTMR_INTERVAL(u32Interval) (CLK->PMUCTL |= (u32Interval))
/**
* @brief Set De-bounce Sampling Cycle Time
*
* @param[in] u32CycleSel The de-bounce sampling cycle selection. It could be
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_1
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_2
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_4
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_8
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_16
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_32
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_64
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_128
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_256
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_2x256
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_4x256
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_8x256
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_16x256
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_32x256
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_64x256
* - \ref CLK_SWKDBCTL_SWKDBCLKSEL_128x256
*
* @return None
*
* @details This function set Set De-bounce Sampling Cycle Time.
*
* \hideinitializer
*/
#define CLK_SET_SPDDEBOUNCETIME(u32CycleSel) (CLK->SWKDBCTL = (u32CycleSel))
/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */
static __INLINE uint32_t CLK_GetPLLClockFreq(void);
static __INLINE void CLK_SysTickDelay(uint32_t us);
/**
* @brief Get PLL clock frequency
* @param None
* @return PLL frequency
* @details This function get PLL frequency. The frequency unit is Hz.
*/
__STATIC_INLINE uint32_t CLK_GetPLLClockFreq(void)
{
uint32_t u32PllFreq = 0UL, u32PllReg;
uint32_t u32FIN, u32NF, u32NR, u32NO;
uint8_t au8NoTbl[4] = {1U, 2U, 2U, 4U};
u32PllReg = CLK->PLLCTL;
if(u32PllReg & (CLK_PLLCTL_PD_Msk | CLK_PLLCTL_OE_Msk)) {
u32PllFreq = 0UL; /* PLL is in power down mode or fix low */
} else if((u32PllReg & CLK_PLLCTL_BP_Msk) == CLK_PLLCTL_BP_Msk) {
if((u32PllReg & CLK_PLLCTL_PLLSRC_HIRC) == CLK_PLLCTL_PLLSRC_HIRC) {
u32FIN = __HIRC; /* PLL source clock from HIRC */
} else {
u32FIN = __HXT; /* PLL source clock from HXT */
}
u32PllFreq = u32FIN;
} else {
if((u32PllReg & CLK_PLLCTL_PLLSRC_HIRC) == CLK_PLLCTL_PLLSRC_HIRC) {
u32FIN = __HIRC; /* PLL source clock from HIRC */
} else {
u32FIN = __HXT; /* PLL source clock from HXT */
}
/* PLL is output enabled in normal work mode */
u32NO = au8NoTbl[((u32PllReg & CLK_PLLCTL_OUTDIV_Msk) >> CLK_PLLCTL_OUTDIV_Pos)];
u32NF = ((u32PllReg & CLK_PLLCTL_FBDIV_Msk) >> CLK_PLLCTL_FBDIV_Pos) + 2UL;
u32NR = ((u32PllReg & CLK_PLLCTL_INDIV_Msk) >> CLK_PLLCTL_INDIV_Pos) + 1UL;
/* u32FIN is shifted 2 bits to avoid overflow */
u32PllFreq = (((u32FIN >> 2) * u32NF) / (u32NR * u32NO) << 2) * 2UL;
}
return u32PllFreq;
}
/**
* @brief This function execute delay function.
* @param us Delay time. The Max value is 2^24 / CPU Clock(MHz). Ex:
* 72MHz => 233016us, 50MHz => 335544us,
* 48MHz => 349525us, 28MHz => 699050us ...
* @return None
* @details Use the SysTick to generate the delay time and the unit is in us.
* The SysTick clock source is from HCLK, i.e the same as system core clock.
*/
__STATIC_INLINE void CLK_SysTickDelay(uint32_t us)
{
SysTick->LOAD = us * CyclesPerUs;
SysTick->VAL = 0x0UL;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
/* Waiting for down-count to zero */
while((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0UL) {
}
/* Disable SysTick counter */
SysTick->CTRL = 0UL;
}
void CLK_DisableCKO(void);
void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En);
void CLK_PowerDown(void);
void CLK_Idle(void);
uint32_t CLK_GetHXTFreq(void);
uint32_t CLK_GetLXTFreq(void);
uint32_t CLK_GetHCLKFreq(void);
uint32_t CLK_GetPCLK0Freq(void);
uint32_t CLK_GetPCLK1Freq(void);
uint32_t CLK_GetCPUFreq(void);
uint32_t CLK_SetCoreClock(uint32_t u32Hclk);
void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv);
void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv);
void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc);
void CLK_EnableXtalRC(uint32_t u32ClkMask);
void CLK_DisableXtalRC(uint32_t u32ClkMask);
void CLK_EnableModuleClock(uint32_t u32ModuleIdx);
void CLK_DisableModuleClock(uint32_t u32ModuleIdx);
uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq);
void CLK_DisablePLL(void);
uint32_t CLK_WaitClockReady(uint32_t u32ClkMask);
void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count);
void CLK_DisableSysTick(void);
void CLK_SetPowerDownMode(uint32_t u32PDMode);
void CLK_EnableDPDWKPin(uint32_t u32TriggerType);
uint32_t CLK_GetPMUWKSrc(void);
void CLK_EnableSPDWKPin(uint32_t u32Port, uint32_t u32Pin, uint32_t u32TriggerType, uint32_t u32DebounceEn);
void CLK_SetUSBModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv);
/*@}*/ /* end of group M480_CLK_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_CLK_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __CLK_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,93 @@
/**************************************************************************//**
* @file crc.c
* @version V1.00
* @brief M480 CRC driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_CRC_Driver CRC Driver
@{
*/
/** @addtogroup M480_CRC_EXPORTED_FUNCTIONS CRC Exported Functions
@{
*/
/**
* @brief CRC Open
*
* @param[in] u32Mode CRC operation polynomial mode. Valid values are:
* - \ref CRC_CCITT
* - \ref CRC_8
* - \ref CRC_16
* - \ref CRC_32
* @param[in] u32Attribute CRC operation data attribute. Valid values are combined with:
* - \ref CRC_CHECKSUM_COM
* - \ref CRC_CHECKSUM_RVS
* - \ref CRC_WDATA_COM
* - \ref CRC_WDATA_RVS
* @param[in] u32Seed Seed value.
* @param[in] u32DataLen CPU Write Data Length. Valid values are:
* - \ref CRC_CPU_WDATA_8
* - \ref CRC_CPU_WDATA_16
* - \ref CRC_CPU_WDATA_32
*
* @return None
*
* @details This function will enable the CRC controller by specify CRC operation mode, attribute, initial seed and write data length. \n
* After that, user can start to perform CRC calculate by calling CRC_WRITE_DATA macro or CRC_DAT register directly.
*/
void CRC_Open(uint32_t u32Mode, uint32_t u32Attribute, uint32_t u32Seed, uint32_t u32DataLen)
{
CRC->SEED = u32Seed;
CRC->CTL = u32Mode | u32Attribute | u32DataLen | CRC_CTL_CRCEN_Msk;
/* Setting CHKSINIT bit will reload the initial seed value(CRC_SEED register) to CRC controller */
CRC->CTL |= CRC_CTL_CHKSINIT_Msk;
}
/**
* @brief Get CRC Checksum
*
* @param[in] None
*
* @return Checksum Result
*
* @details This macro gets the CRC checksum result by current CRC polynomial mode.
*/
uint32_t CRC_GetChecksum(void)
{
uint32_t ret;
switch(CRC->CTL & CRC_CTL_CRCMODE_Msk) {
case CRC_CCITT:
case CRC_16:
ret = (CRC->CHECKSUM & 0xFFFFU);
break;
case CRC_32:
ret = (CRC->CHECKSUM);
break;
case CRC_8:
ret = (CRC->CHECKSUM & 0xFFU);
break;
default:
ret = 0U;
break;
}
return ret;
}
/*@}*/ /* end of group M480_CRC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_CRC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,112 @@
/**************************************************************************//**
* @file crc.h
* @version V1.00
* @brief M480 series CRC driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __CRC_H__
#define __CRC_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_CRC_Driver CRC Driver
@{
*/
/** @addtogroup M480_CRC_EXPORTED_CONSTANTS CRC Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* CRC Polynomial Mode Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define CRC_CCITT (0UL << CRC_CTL_CRCMODE_Pos) /*!<CRC Polynomial Mode - CCITT \hideinitializer */
#define CRC_8 (1UL << CRC_CTL_CRCMODE_Pos) /*!<CRC Polynomial Mode - CRC8 \hideinitializer */
#define CRC_16 (2UL << CRC_CTL_CRCMODE_Pos) /*!<CRC Polynomial Mode - CRC16 \hideinitializer */
#define CRC_32 (3UL << CRC_CTL_CRCMODE_Pos) /*!<CRC Polynomial Mode - CRC32 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Checksum, Write data Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define CRC_CHECKSUM_COM (CRC_CTL_CHKSFMT_Msk) /*!<CRC Checksum Complement \hideinitializer */
#define CRC_CHECKSUM_RVS (CRC_CTL_CHKSREV_Msk) /*!<CRC Checksum Reverse \hideinitializer */
#define CRC_WDATA_COM (CRC_CTL_DATFMT_Msk) /*!<CRC Write Data Complement \hideinitializer */
#define CRC_WDATA_RVS (CRC_CTL_DATREV_Msk) /*!<CRC Write Data Reverse \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* CPU Write Data Length Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define CRC_CPU_WDATA_8 (0UL << CRC_CTL_DATLEN_Pos) /*!<CRC CPU Write Data length is 8-bit \hideinitializer */
#define CRC_CPU_WDATA_16 (1UL << CRC_CTL_DATLEN_Pos) /*!<CRC CPU Write Data length is 16-bit \hideinitializer */
#define CRC_CPU_WDATA_32 (2UL << CRC_CTL_DATLEN_Pos) /*!<CRC CPU Write Data length is 32-bit \hideinitializer */
/*@}*/ /* end of group M480_CRC_EXPORTED_CONSTANTS */
/** @addtogroup M480_CRC_EXPORTED_FUNCTIONS CRC Exported Functions
@{
*/
/**
* @brief Set CRC Seed Value
*
* @param[in] u32Seed Seed value
*
* @return None
*
* @details This macro is used to set CRC seed value.
*
* @note User must to perform CRC_CHKSINIT(CRC_CTL[1] CRC Engine Reset) to reload the new seed value
* to CRC controller.
* \hideinitializer
*/
#define CRC_SET_SEED(u32Seed) do{ CRC->SEED = (u32Seed); CRC->CTL |= CRC_CTL_CHKSINIT_Msk; }while(0)
/**
* @brief Get CRC Seed Value
*
* @param None
*
* @return CRC seed value
*
* @details This macro gets the current CRC seed value.
* \hideinitializer
*/
#define CRC_GET_SEED() (CRC->SEED)
/**
* @brief CRC Write Data
*
* @param[in] u32Data Write data
*
* @return None
*
* @details User can write data directly to CRC Write Data Register(CRC_DAT) by this macro to perform CRC operation.
* \hideinitializer
*/
#define CRC_WRITE_DATA(u32Data) (CRC->DAT = (u32Data))
void CRC_Open(uint32_t u32Mode, uint32_t u32Attribute, uint32_t u32Seed, uint32_t u32DataLen);
uint32_t CRC_GetChecksum(void);
/*@}*/ /* end of group M480_CRC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_CRC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,338 @@
/**************************************************************************//**
* @file crypto.h
* @version V1.10
* @brief Cryptographic Accelerator driver header file
*
* @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#ifndef __CRYPTO_H__
#define __CRYPTO_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_CRYPTO_Driver CRYPTO Driver
@{
*/
/** @addtogroup M480_CRYPTO_EXPORTED_CONSTANTS CRYPTO Exported Constants
@{
*/
#define PRNG_KEY_SIZE_64 0UL /*!< Select to generate 64-bit random key \hideinitializer */
#define PRNG_KEY_SIZE_128 1UL /*!< Select to generate 128-bit random key \hideinitializer */
#define PRNG_KEY_SIZE_192 2UL /*!< Select to generate 192-bit random key \hideinitializer */
#define PRNG_KEY_SIZE_256 3UL /*!< Select to generate 256-bit random key \hideinitializer */
#define PRNG_SEED_CONT 0UL /*!< PRNG using current seed \hideinitializer */
#define PRNG_SEED_RELOAD 1UL /*!< PRNG reload new seed \hideinitializer */
#define AES_KEY_SIZE_128 0UL /*!< AES select 128-bit key length \hideinitializer */
#define AES_KEY_SIZE_192 1UL /*!< AES select 192-bit key length \hideinitializer */
#define AES_KEY_SIZE_256 2UL /*!< AES select 256-bit key length \hideinitializer */
#define AES_MODE_ECB 0UL /*!< AES select ECB mode \hideinitializer */
#define AES_MODE_CBC 1UL /*!< AES select CBC mode \hideinitializer */
#define AES_MODE_CFB 2UL /*!< AES select CFB mode \hideinitializer */
#define AES_MODE_OFB 3UL /*!< AES select OFB mode \hideinitializer */
#define AES_MODE_CTR 4UL /*!< AES select CTR mode \hideinitializer */
#define AES_MODE_CBC_CS1 0x10UL /*!< AES select CBC CS1 mode \hideinitializer */
#define AES_MODE_CBC_CS2 0x11UL /*!< AES select CBC CS2 mode \hideinitializer */
#define AES_MODE_CBC_CS3 0x12UL /*!< AES select CBC CS3 mode \hideinitializer */
#define AES_NO_SWAP 0UL /*!< AES do not swap input and output data \hideinitializer */
#define AES_OUT_SWAP 1UL /*!< AES swap output data \hideinitializer */
#define AES_IN_SWAP 2UL /*!< AES swap input data \hideinitializer */
#define AES_IN_OUT_SWAP 3UL /*!< AES swap both input and output data \hideinitializer */
#define DES_MODE_ECB 0x000UL /*!< DES select ECB mode \hideinitializer */
#define DES_MODE_CBC 0x100UL /*!< DES select CBC mode \hideinitializer */
#define DES_MODE_CFB 0x200UL /*!< DES select CFB mode \hideinitializer */
#define DES_MODE_OFB 0x300UL /*!< DES select OFB mode \hideinitializer */
#define DES_MODE_CTR 0x400UL /*!< DES select CTR mode \hideinitializer */
#define TDES_MODE_ECB 0x004UL /*!< TDES select ECB mode \hideinitializer */
#define TDES_MODE_CBC 0x104UL /*!< TDES select CBC mode \hideinitializer */
#define TDES_MODE_CFB 0x204UL /*!< TDES select CFB mode \hideinitializer */
#define TDES_MODE_OFB 0x304UL /*!< TDES select OFB mode \hideinitializer */
#define TDES_MODE_CTR 0x404UL /*!< TDES select CTR mode \hideinitializer */
#define TDES_NO_SWAP 0UL /*!< TDES do not swap data \hideinitializer */
#define TDES_WHL_SWAP 1UL /*!< TDES swap high-low word \hideinitializer */
#define TDES_OUT_SWAP 2UL /*!< TDES swap output data \hideinitializer */
#define TDES_OUT_WHL_SWAP 3UL /*!< TDES swap output data and high-low word \hideinitializer */
#define TDES_IN_SWAP 4UL /*!< TDES swap input data \hideinitializer */
#define TDES_IN_WHL_SWAP 5UL /*!< TDES swap input data and high-low word \hideinitializer */
#define TDES_IN_OUT_SWAP 6UL /*!< TDES swap both input and output data \hideinitializer */
#define TDES_IN_OUT_WHL_SWAP 7UL /*!< TDES swap input, output and high-low word \hideinitializer */
#define SHA_MODE_SHA1 0UL /*!< SHA select SHA-1 160-bit \hideinitializer */
#define SHA_MODE_SHA224 5UL /*!< SHA select SHA-224 224-bit \hideinitializer */
#define SHA_MODE_SHA256 4UL /*!< SHA select SHA-256 256-bit \hideinitializer */
#define SHA_MODE_SHA384 7UL /*!< SHA select SHA-384 384-bit \hideinitializer */
#define SHA_MODE_SHA512 6UL /*!< SHA select SHA-512 512-bit \hideinitializer */
#define SHA_NO_SWAP 0UL /*!< SHA do not swap input and output data \hideinitializer */
#define SHA_OUT_SWAP 1UL /*!< SHA swap output data \hideinitializer */
#define SHA_IN_SWAP 2UL /*!< SHA swap input data \hideinitializer */
#define SHA_IN_OUT_SWAP 3UL /*!< SHA swap both input and output data \hideinitializer */
#define CRYPTO_DMA_FIRST 0x4UL /*!< Do first encrypt/decrypt in DMA cascade \hideinitializer */
#define CRYPTO_DMA_ONE_SHOT 0x5UL /*!< Do one shot encrypt/decrypt with DMA \hideinitializer */
#define CRYPTO_DMA_CONTINUE 0x6UL /*!< Do continuous encrypt/decrypt in DMA cascade \hideinitializer */
#define CRYPTO_DMA_LAST 0x7UL /*!< Do last encrypt/decrypt in DMA cascade \hideinitializer */
typedef enum { /*!< ECC curve \hideinitializer */
CURVE_P_192, /*!< ECC curve P-192 \hideinitializer */
CURVE_P_224, /*!< ECC curve P-224 \hideinitializer */
CURVE_P_256, /*!< ECC curve P-256 \hideinitializer */
CURVE_P_384, /*!< ECC curve P-384 \hideinitializer */
CURVE_P_521, /*!< ECC curve P-521 \hideinitializer */
CURVE_K_163, /*!< ECC curve K-163 \hideinitializer */
CURVE_K_233, /*!< ECC curve K-233 \hideinitializer */
CURVE_K_283, /*!< ECC curve K-283 \hideinitializer */
CURVE_K_409, /*!< ECC curve K-409 \hideinitializer */
CURVE_K_571, /*!< ECC curve K-571 \hideinitializer */
CURVE_B_163, /*!< ECC curve B-163 \hideinitializer */
CURVE_B_233, /*!< ECC curve B-233 \hideinitializer */
CURVE_B_283, /*!< ECC curve B-283 \hideinitializer */
CURVE_B_409, /*!< ECC curve B-409 \hideinitializer */
CURVE_B_571 /*!< ECC curve K-571 \hideinitializer */
}
E_ECC_CURVE; /*!< ECC curve \hideinitializer */
/*@}*/ /* end of group M480_CRYPTO_EXPORTED_CONSTANTS */
/** @addtogroup M480_CRYPTO_EXPORTED_FUNCTIONS CRYPTO Exported Functions
@{
*/
/*----------------------------------------------------------------------------------------------*/
/* Macros */
/*----------------------------------------------------------------------------------------------*/
/**
* @brief This macro enables PRNG interrupt.
* @return None
* \hideinitializer
*/
#define PRNG_ENABLE_INT() (CRPT->INTEN |= CRPT_INTEN_PRNGIEN_Msk)
/**
* @brief This macro disables PRNG interrupt.
* @return None
* \hideinitializer
*/
#define PRNG_DISABLE_INT() (CRPT->INTEN &= ~CRPT_INTEN_PRNGIEN_Msk)
/**
* @brief This macro gets PRNG interrupt flag.
* @return PRNG interrupt flag.
* \hideinitializer
*/
#define PRNG_GET_INT_FLAG() (CRPT->INTSTS & CRPT_INTSTS_PRNGIF_Msk)
/**
* @brief This macro clears PRNG interrupt flag.
* @return None
* \hideinitializer
*/
#define PRNG_CLR_INT_FLAG() (CRPT->INTSTS = CRPT_INTSTS_PRNGIF_Msk)
/**
* @brief This macro enables AES interrupt.
* @return None
* \hideinitializer
*/
#define AES_ENABLE_INT() (CRPT->INTEN |= (CRPT_INTEN_AESIEN_Msk|CRPT_INTEN_AESEIEN_Msk))
/**
* @brief This macro disables AES interrupt.
* @return None
* \hideinitializer
*/
#define AES_DISABLE_INT() (CRPT->INTEN &= ~(CRPT_INTEN_AESIEN_Msk|CRPT_INTEN_AESEIEN_Msk))
/**
* @brief This macro gets AES interrupt flag.
* @return AES interrupt flag.
* \hideinitializer
*/
#define AES_GET_INT_FLAG() (CRPT->INTSTS & (CRPT_INTSTS_AESIF_Msk|CRPT_INTSTS_AESEIF_Msk))
/**
* @brief This macro clears AES interrupt flag.
* @return None
* \hideinitializer
*/
#define AES_CLR_INT_FLAG() (CRPT->INTSTS = (CRPT_INTSTS_AESIF_Msk|CRPT_INTSTS_AESEIF_Msk))
/**
* @brief This macro enables AES key protection.
* @return None
* \hideinitializer
*/
#define AES_ENABLE_KEY_PROTECT() (CRPT->AES_CTL |= CRPT_AES_CTL_KEYPRT_Msk)
/**
* @brief This macro disables AES key protection.
* @return None
* \hideinitializer
*/
#define AES_DISABLE_KEY_PROTECT() (CRPT->AES_CTL = (CRPT->AES_CTL & ~CRPT_AES_CTL_KEYPRT_Msk) | (0x16UL<<CRPT_AES_CTL_KEYUNPRT_Pos)); \
(CRPT->AES_CTL &= ~CRPT_AES_CTL_KEYPRT_Msk)
/**
* @brief This macro enables TDES interrupt.
* @return None
* \hideinitializer
*/
#define TDES_ENABLE_INT() (CRPT->INTEN |= (CRPT_INTEN_TDESIEN_Msk|CRPT_INTEN_TDESEIEN_Msk))
/**
* @brief This macro disables TDES interrupt.
* @return None
* \hideinitializer
*/
#define TDES_DISABLE_INT() (CRPT->INTEN &= ~(CRPT_INTEN_TDESIEN_Msk|CRPT_INTEN_TDESEIEN_Msk))
/**
* @brief This macro gets TDES interrupt flag.
* @return TDES interrupt flag.
* \hideinitializer
*/
#define TDES_GET_INT_FLAG() (CRPT->INTSTS & (CRPT_INTSTS_TDESIF_Msk|CRPT_INTSTS_TDESEIF_Msk))
/**
* @brief This macro clears TDES interrupt flag.
* @return None
* \hideinitializer
*/
#define TDES_CLR_INT_FLAG() (CRPT->INTSTS = (CRPT_INTSTS_TDESIF_Msk|CRPT_INTSTS_TDESEIF_Msk))
/**
* @brief This macro enables TDES key protection.
* @return None
* \hideinitializer
*/
#define TDES_ENABLE_KEY_PROTECT() (CRPT->TDES_CTL |= CRPT_TDES_CTL_KEYPRT_Msk)
/**
* @brief This macro disables TDES key protection.
* @return None
* \hideinitializer
*/
#define TDES_DISABLE_KEY_PROTECT() (CRPT->TDES_CTL = (CRPT->TDES_CTL & ~CRPT_TDES_CTL_KEYPRT_Msk) | (0x16UL<<CRPT_TDES_CTL_KEYUNPRT_Pos)); \
(CRPT->TDES_CTL &= ~CRPT_TDES_CTL_KEYPRT_Msk)
/**
* @brief This macro enables SHA interrupt.
* @return None
* \hideinitializer
*/
#define SHA_ENABLE_INT() (CRPT->INTEN |= (CRPT_INTEN_HMACIEN_Msk|CRPT_INTEN_HMACEIEN_Msk))
/**
* @brief This macro disables SHA interrupt.
* @return None
* \hideinitializer
*/
#define SHA_DISABLE_INT() (CRPT->INTEN &= ~(CRPT_INTEN_HMACIEN_Msk|CRPT_INTEN_HMACEIEN_Msk))
/**
* @brief This macro gets SHA interrupt flag.
* @return SHA interrupt flag.
* \hideinitializer
*/
#define SHA_GET_INT_FLAG() (CRPT->INTSTS & (CRPT_INTSTS_HMACIF_Msk|CRPT_INTSTS_HMACEIF_Msk))
/**
* @brief This macro clears SHA interrupt flag.
* @return None
* \hideinitializer
*/
#define SHA_CLR_INT_FLAG() (CRPT->INTSTS = (CRPT_INTSTS_HMACIF_Msk|CRPT_INTSTS_HMACEIF_Msk))
/**
* @brief This macro enables ECC interrupt.
* @return None
* \hideinitializer
*/
#define ECC_ENABLE_INT() (CRPT->INTEN |= (CRPT_INTEN_ECCIEN_Msk|CRPT_INTEN_ECCEIEN_Msk))
/**
* @brief This macro disables ECC interrupt.
* @return None
* \hideinitializer
*/
#define ECC_DISABLE_INT() (CRPT->INTEN &= ~(CRPT_INTEN_ECCIEN_Msk|CRPT_INTEN_ECCEIEN_Msk))
/**
* @brief This macro gets ECC interrupt flag.
* @return ECC interrupt flag.
* \hideinitializer
*/
#define ECC_GET_INT_FLAG() (CRPT->INTSTS & (CRPT_INTSTS_ECCIF_Msk|CRPT_INTSTS_ECCEIF_Msk))
/**
* @brief This macro clears ECC interrupt flag.
* @return None
* \hideinitializer
*/
#define ECC_CLR_INT_FLAG() (CRPT->INTSTS = (CRPT_INTSTS_ECCIF_Msk|CRPT_INTSTS_ECCEIF_Msk))
/*---------------------------------------------------------------------------------------------------------*/
/* Functions */
/*---------------------------------------------------------------------------------------------------------*/
void PRNG_Open(uint32_t u32KeySize, uint32_t u32SeedReload, uint32_t u32Seed);
void PRNG_Start(void);
void PRNG_Read(uint32_t u32RandKey[]);
void AES_Open(uint32_t u32Channel, uint32_t u32EncDec, uint32_t u32OpMode, uint32_t u32KeySize, uint32_t u32SwapType);
void AES_Start(int32_t u32Channel, uint32_t u32DMAMode);
void AES_SetKey(uint32_t u32Channel, uint32_t au32Keys[], uint32_t u32KeySize);
void AES_SetInitVect(uint32_t u32Channel, uint32_t au32IV[]);
void AES_SetDMATransfer(uint32_t u32Channel, uint32_t u32SrcAddr, uint32_t u32DstAddr, uint32_t u32TransCnt);
void TDES_Open(uint32_t u32Channel, uint32_t u32EncDec, int32_t Is3DES, int32_t Is3Key, uint32_t u32OpMode, uint32_t u32SwapType);
void TDES_Start(int32_t u32Channel, uint32_t u32DMAMode);
void TDES_SetKey(uint32_t u32Channel, uint32_t au32Keys[3][2]);
void TDES_SetInitVect(uint32_t u32Channel, uint32_t u32IVH, uint32_t u32IVL);
void TDES_SetDMATransfer(uint32_t u32Channel, uint32_t u32SrcAddr, uint32_t u32DstAddr, uint32_t u32TransCnt);
void SHA_Open(uint32_t u32OpMode, uint32_t u32SwapType, uint32_t hmac_key_len);
void SHA_Start(uint32_t u32DMAMode);
void SHA_SetDMATransfer(uint32_t u32SrcAddr, uint32_t u32TransCnt);
void SHA_Read(uint32_t u32Digest[]);
void ECC_DriverISR(void);
int ECC_IsPrivateKeyValid(E_ECC_CURVE ecc_curve, char private_k[]);
int32_t ECC_GeneratePublicKey(E_ECC_CURVE ecc_curve, char *private_k, char public_k1[], char public_k2[]);
int32_t ECC_GenerateSecretZ(E_ECC_CURVE ecc_curve, char *private_k, char public_k1[], char public_k2[], char secret_z[]);
int32_t ECC_GenerateSignature(E_ECC_CURVE ecc_curve, char *message, char *d, char *k, char *R, char *S);
int32_t ECC_VerifySignature(E_ECC_CURVE ecc_curve, char *message, char *public_k1, char *public_k2, char *R, char *S);
/*@}*/ /* end of group M480_CRYPTO_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_CRYPTO_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __CRYPTO_H__ */
/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,89 @@
/**************************************************************************//**
* @file dac.c
* @version V1.00
* @brief M480 series DAC driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_DAC_Driver DAC Driver
@{
*/
/** @addtogroup M480_DAC_EXPORTED_FUNCTIONS DAC Exported Functions
@{
*/
/**
* @brief This function make DAC module be ready to convert.
* @param[in] dac Base address of DAC module.
* @param[in] u32Ch Not used in M480 DAC.
* @param[in] u32TrgSrc Decides the trigger source. Valid values are:
* - \ref DAC_WRITE_DAT_TRIGGER :Write DAC_DAT trigger
* - \ref DAC_SOFTWARE_TRIGGER :Software trigger
* - \ref DAC_LOW_LEVEL_TRIGGER :STDAC pin low level trigger
* - \ref DAC_HIGH_LEVEL_TRIGGER :STDAC pin high level trigger
* - \ref DAC_FALLING_EDGE_TRIGGER :STDAC pin falling edge trigger
* - \ref DAC_RISING_EDGE_TRIGGER :STDAC pin rising edge trigger
* - \ref DAC_TIMER0_TRIGGER :Timer 0 trigger
* - \ref DAC_TIMER1_TRIGGER :Timer 1 trigger
* - \ref DAC_TIMER2_TRIGGER :Timer 2 trigger
* - \ref DAC_TIMER3_TRIGGER :Timer 3 trigger
* - \ref DAC_EPWM0_TRIGGER :EPWM0 trigger
* - \ref DAC_EPWM1_TRIGGER :EPWM1 trigger
* @return None
* @details The DAC conversion can be started by writing DAC_DAT, software trigger or hardware trigger.
* When TRGEN (DAC_CTL[4]) is 0, the data conversion is started by writing DAC_DAT register.
* When TRGEN (DAC_CTL[4]) is 1, the data conversion is started by SWTRG (DAC_SWTRG[0]) is set to 1,
* external STDAC pin, timer event, or EPWM event.
*/
void DAC_Open(DAC_T *dac,
uint32_t u32Ch,
uint32_t u32TrgSrc)
{
dac->CTL &= ~(DAC_CTL_ETRGSEL_Msk | DAC_CTL_TRGSEL_Msk | DAC_CTL_TRGEN_Msk);
dac->CTL |= (u32TrgSrc | DAC_CTL_DACEN_Msk);
}
/**
* @brief Disable DAC analog power.
* @param[in] dac Base address of DAC module.
* @param[in] u32Ch Not used in M480 DAC.
* @return None
* @details Disable DAC analog power for saving power consumption.
*/
void DAC_Close(DAC_T *dac, uint32_t u32Ch)
{
dac->CTL &= (~DAC_CTL_DACEN_Msk);
}
/**
* @brief Set delay time for DAC to become stable.
* @param[in] dac Base address of DAC module.
* @param[in] u32Delay Decides the DAC conversion settling time, the range is from 0~(1023/PCLK1*1000000) micro seconds.
* @return Real DAC conversion settling time (micro second).
* @details For example, DAC controller clock speed is 160MHz and DAC conversion setting time is 1 us, SETTLET (DAC_TCTL[9:0]) value must be greater than 0xA0.
* @note User needs to write appropriate value to meet DAC conversion settling time base on PCLK (APB clock) speed.
*/
uint32_t DAC_SetDelayTime(DAC_T *dac, uint32_t u32Delay)
{
dac->TCTL = ((CLK_GetPCLK1Freq() * u32Delay / 1000000UL) & 0x3FFUL);
return ((dac->TCTL) * 1000000UL / CLK_GetPCLK1Freq());
}
/*@}*/ /* end of group M480_DAC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_DAC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,268 @@
/**************************************************************************//**
* @file dac.h
* @version V1.00
* @brief M480 series DAC driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __DAC_H__
#define __DAC_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_DAC_Driver DAC Driver
@{
*/
/** @addtogroup M480_DAC_EXPORTED_CONSTANTS DAC Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* DAC_CTL Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define DAC_CTL_LALIGN_RIGHT_ALIGN (0UL<<DAC_CTL_LALIGN_Pos) /*!< Right alignment. \hideinitializer */
#define DAC_CTL_LALIGN_LEFT_ALIGN (1UL<<DAC_CTL_LALIGN_Pos) /*!< Left alignment \hideinitializer */
#define DAC_WRITE_DAT_TRIGGER (0UL) /*!< Write DAC_DAT trigger \hideinitializer */
#define DAC_SOFTWARE_TRIGGER (0UL|DAC_CTL_TRGEN_Msk) /*!< Software trigger \hideinitializer */
#define DAC_LOW_LEVEL_TRIGGER ((0UL<<DAC_CTL_ETRGSEL_Pos)|(1UL<<DAC_CTL_TRGSEL_Pos)|DAC_CTL_TRGEN_Msk) /*!< STDAC pin low level trigger \hideinitializer */
#define DAC_HIGH_LEVEL_TRIGGER ((1UL<<DAC_CTL_ETRGSEL_Pos)|(1UL<<DAC_CTL_TRGSEL_Pos)|DAC_CTL_TRGEN_Msk) /*!< STDAC pin high level trigger \hideinitializer */
#define DAC_FALLING_EDGE_TRIGGER ((2UL<<DAC_CTL_ETRGSEL_Pos)|(1UL<<DAC_CTL_TRGSEL_Pos)|DAC_CTL_TRGEN_Msk) /*!< STDAC pin falling edge trigger \hideinitializer */
#define DAC_RISING_EDGE_TRIGGER ((3UL<<DAC_CTL_ETRGSEL_Pos)|(1UL<<DAC_CTL_TRGSEL_Pos)|DAC_CTL_TRGEN_Msk) /*!< STDAC pin rising edge trigger \hideinitializer */
#define DAC_TIMER0_TRIGGER ((2UL<<DAC_CTL_TRGSEL_Pos)|DAC_CTL_TRGEN_Msk) /*!< Timer 0 trigger \hideinitializer */
#define DAC_TIMER1_TRIGGER ((3UL<<DAC_CTL_TRGSEL_Pos)|DAC_CTL_TRGEN_Msk) /*!< Timer 1 trigger \hideinitializer */
#define DAC_TIMER2_TRIGGER ((4UL<<DAC_CTL_TRGSEL_Pos)|DAC_CTL_TRGEN_Msk) /*!< Timer 2 trigger \hideinitializer */
#define DAC_TIMER3_TRIGGER ((5UL<<DAC_CTL_TRGSEL_Pos)|DAC_CTL_TRGEN_Msk) /*!< Timer 3 trigger \hideinitializer */
#define DAC_EPWM0_TRIGGER ((6UL<<DAC_CTL_TRGSEL_Pos)|DAC_CTL_TRGEN_Msk) /*!< EPWM0 trigger \hideinitializer */
#define DAC_EPWM1_TRIGGER ((7UL<<DAC_CTL_TRGSEL_Pos)|DAC_CTL_TRGEN_Msk) /*!< EPWM1 trigger \hideinitializer */
#define DAC_TRIGGER_MODE_DISABLE (0UL<<DAC_CTL_TRGEN_Pos) /*!< Trigger mode disable \hideinitializer */
#define DAC_TRIGGER_MODE_ENABLE (1UL<<DAC_CTL_TRGEN_Pos) /*!< Trigger mode enable \hideinitializer */
/*@}*/ /* end of group DAC_EXPORTED_CONSTANTS */
/** @addtogroup M480_DAC_EXPORTED_FUNCTIONS DAC Exported Functions
@{
*/
/**
* @brief Start the D/A conversion.
* @param[in] dac Base address of DAC module.
* @return None
* @details User writes SWTRG bit (DAC_SWTRG[0]) to generate one shot pulse and it is cleared to 0 by hardware automatically.
* \hideinitializer
*/
#define DAC_START_CONV(dac) ((dac)->SWTRG = DAC_SWTRG_SWTRG_Msk)
/**
* @brief Enable DAC data left-aligned.
* @param[in] dac Base address of DAC module.
* @return None
* @details User has to load data into DAC_DAT[15:4] bits. DAC_DAT[31:16] and DAC_DAT[3:0] are ignored in DAC conversion.
* \hideinitializer
*/
#define DAC_ENABLE_LEFT_ALIGN(dac) ((dac)->CTL |= DAC_CTL_LALIGN_Msk)
/**
* @brief Enable DAC data right-aligned.
* @param[in] dac Base address of DAC module.
* @return None
* @details User has to load data into DAC_DAT[11:0] bits, DAC_DAT[31:12] are ignored in DAC conversion.
* \hideinitializer
*/
#define DAC_ENABLE_RIGHT_ALIGN(dac) ((dac)->CTL &= ~DAC_CTL_LALIGN_Msk)
/**
* @brief Enable output voltage buffer.
* @param[in] dac Base address of DAC module.
* @return None
* @details The DAC integrates a voltage output buffer that can be used to reduce output impedance and
* drive external loads directly without having to add an external operational amplifier.
* \hideinitializer
*/
#define DAC_ENABLE_BYPASS_BUFFER(dac) ((dac)->CTL |= DAC_CTL_BYPASS_Msk)
/**
* @brief Disable output voltage buffer.
* @param[in] dac Base address of DAC module.
* @return None
* @details This macro is used to disable output voltage buffer.
* \hideinitializer
*/
#define DAC_DISABLE_BYPASS_BUFFER(dac) ((dac)->CTL &= ~DAC_CTL_BYPASS_Msk)
/**
* @brief Enable the interrupt.
* @param[in] dac Base address of DAC module.
* @param[in] u32Ch Not used in M480 DAC.
* @return None
* @details This macro is used to enable DAC interrupt.
* \hideinitializer
*/
#define DAC_ENABLE_INT(dac, u32Ch) ((dac)->CTL |= DAC_CTL_DACIEN_Msk)
/**
* @brief Disable the interrupt.
* @param[in] dac Base address of DAC module.
* @param[in] u32Ch Not used in M480 DAC.
* @return None
* @details This macro is used to disable DAC interrupt.
* \hideinitializer
*/
#define DAC_DISABLE_INT(dac, u32Ch) ((dac)->CTL &= ~DAC_CTL_DACIEN_Msk)
/**
* @brief Enable DMA under-run interrupt.
* @param[in] dac Base address of DAC module.
* @return None
* @details This macro is used to enable DMA under-run interrupt.
* \hideinitializer
*/
#define DAC_ENABLE_DMAUDR_INT(dac) ((dac)->CTL |= DAC_CTL_DMAURIEN_Msk)
/**
* @brief Disable DMA under-run interrupt.
* @param[in] dac Base address of DAC module.
* @return None
* @details This macro is used to disable DMA under-run interrupt.
* \hideinitializer
*/
#define DAC_DISABLE_DMAUDR_INT(dac) ((dac)->CTL &= ~DAC_CTL_DMAURIEN_Msk)
/**
* @brief Enable PDMA mode.
* @param[in] dac Base address of DAC module.
* @return None
* @details DAC DMA request is generated when a hardware trigger event occurs while DMAEN (DAC_CTL[2]) is set.
* \hideinitializer
*/
#define DAC_ENABLE_PDMA(dac) ((dac)->CTL |= DAC_CTL_DMAEN_Msk)
/**
* @brief Disable PDMA mode.
* @param[in] dac Base address of DAC module.
* @return None
* @details This macro is used to disable DMA mode.
* \hideinitializer
*/
#define DAC_DISABLE_PDMA(dac) ((dac)->CTL &= ~DAC_CTL_DMAEN_Msk)
/**
* @brief Write data for conversion.
* @param[in] dac Base address of DAC module.
* @param[in] u32Ch Not used in M480 DAC.
* @param[in] u32Data Decides the data for conversion, valid range are between 0~0xFFF.
* @return None
* @details 12 bit left alignment: user has to load data into DAC_DAT[15:4] bits.
* 12 bit right alignment: user has to load data into DAC_DAT[11:0] bits.
* \hideinitializer
*/
#define DAC_WRITE_DATA(dac, u32Ch, u32Data) ((dac)->DAT = (u32Data))
/**
* @brief Read DAC 12-bit holding data.
* @param[in] dac Base address of DAC module.
* @param[in] u32Ch Not used in M480 DAC.
* @return Return DAC 12-bit holding data.
* @details This macro is used to read DAC_DAT register.
* \hideinitializer
*/
#define DAC_READ_DATA(dac, u32Ch) ((dac)->DAT)
/**
* @brief Get the busy state of DAC.
* @param[in] dac Base address of DAC module.
* @param[in] u32Ch Not used in M480 DAC.
* @retval 0 Idle state.
* @retval 1 Busy state.
* @details This macro is used to read BUSY bit (DAC_STATUS[8]) to get busy state.
* \hideinitializer
*/
#define DAC_IS_BUSY(dac, u32Ch) (((dac)->STATUS & DAC_STATUS_BUSY_Msk) >> DAC_STATUS_BUSY_Pos)
/**
* @brief Get the interrupt flag.
* @param[in] dac Base address of DAC module.
* @param[in] u32Ch Not used in M480 DAC.
* @retval 0 DAC is in conversion state.
* @retval 1 DAC conversion finish.
* @details This macro is used to read FINISH bit (DAC_STATUS[0]) to get DAC conversion complete finish flag.
* \hideinitializer
*/
#define DAC_GET_INT_FLAG(dac, u32Ch) ((dac)->STATUS & DAC_STATUS_FINISH_Msk)
/**
* @brief Get the DMA under-run flag.
* @param[in] dac Base address of DAC module.
* @retval 0 No DMA under-run error condition occurred.
* @retval 1 DMA under-run error condition occurred.
* @details This macro is used to read DMAUDR bit (DAC_STATUS[1]) to get DMA under-run state.
* \hideinitializer
*/
#define DAC_GET_DMAUDR_FLAG(dac) (((dac)->STATUS & DAC_STATUS_DMAUDR_Msk) >> DAC_STATUS_DMAUDR_Pos)
/**
* @brief This macro clear the interrupt status bit.
* @param[in] dac Base address of DAC module.
* @param[in] u32Ch Not used in M480 DAC.
* @return None
* @details User writes FINISH bit (DAC_STATUS[0]) to clear DAC conversion complete finish flag.
* \hideinitializer
*/
#define DAC_CLR_INT_FLAG(dac, u32Ch) ((dac)->STATUS = DAC_STATUS_FINISH_Msk)
/**
* @brief This macro clear the DMA under-run flag.
* @param[in] dac Base address of DAC module.
* @return None
* @details User writes DMAUDR bit (DAC_STATUS[1]) to clear DMA under-run flag.
* \hideinitializer
*/
#define DAC_CLR_DMAUDR_FLAG(dac) ((dac)->STATUS = DAC_STATUS_DMAUDR_Msk)
/**
* @brief Enable DAC group mode
* @param[in] dac Base address of DAC module.
* @return None
* \hideinitializer
*/
#define DAC_ENABLE_GROUP_MODE(dac) (DAC0->CTL |= DAC_CTL_GRPEN_Msk)
/**
* @brief Disable DAC group mode
* @param[in] dac Base address of DAC module.
* @return None
* \hideinitializer
*/
#define DAC_DISABLE_GROUP_MODE(dac) (DAC0->CTL &= ~DAC_CTL_GRPEN_Msk)
void DAC_Open(DAC_T *dac, uint32_t u32Ch, uint32_t u32TrgSrc);
void DAC_Close(DAC_T *dac, uint32_t u32Ch);
uint32_t DAC_SetDelayTime(DAC_T *dac, uint32_t u32Delay);
/*@}*/ /* end of group M480_DAC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_DAC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __DAC_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,140 @@
/**************************************************************************//**
* @file eadc.c
* @version V2.00
* @brief M480 series EADC driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup EADC_Driver EADC Driver
@{
*/
/** @addtogroup EADC_EXPORTED_FUNCTIONS EADC Exported Functions
@{
*/
/**
* @brief This function make EADC_module be ready to convert.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32InputMode Decides the input mode.
* - \ref EADC_CTL_DIFFEN_SINGLE_END :Single end input mode.
* - \ref EADC_CTL_DIFFEN_DIFFERENTIAL :Differential input type.
* @return None
* @details This function is used to set analog input mode and enable A/D Converter.
* Before starting A/D conversion function, ADCEN bit (EADC_CTL[0]) should be set to 1.
* @note
*/
void EADC_Open(EADC_T *eadc, uint32_t u32InputMode)
{
eadc->CTL &= (~EADC_CTL_DIFFEN_Msk);
eadc->CTL |= (u32InputMode | EADC_CTL_ADCEN_Msk);
while (!(eadc->PWRM & EADC_PWRM_PWUPRDY_Msk)) {}
}
/**
* @brief Disable EADC_module.
* @param[in] eadc The pointer of the specified EADC module..
* @return None
* @details Clear ADCEN bit (EADC_CTL[0]) to disable A/D converter analog circuit power consumption.
*/
void EADC_Close(EADC_T *eadc)
{
eadc->CTL &= ~EADC_CTL_ADCEN_Msk;
}
/**
* @brief Configure the sample control logic module.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 15.
* @param[in] u32TriggerSrc Decides the trigger source. Valid values are:
* - \ref EADC_SOFTWARE_TRIGGER : Disable trigger
* - \ref EADC_FALLING_EDGE_TRIGGER : STADC pin falling edge trigger
* - \ref EADC_RISING_EDGE_TRIGGER : STADC pin rising edge trigger
* - \ref EADC_FALLING_RISING_EDGE_TRIGGER : STADC pin both falling and rising edge trigger
* - \ref EADC_ADINT0_TRIGGER : ADC ADINT0 interrupt EOC pulse trigger
* - \ref EADC_ADINT1_TRIGGER : ADC ADINT1 interrupt EOC pulse trigger
* - \ref EADC_TIMER0_TRIGGER : Timer0 overflow pulse trigger
* - \ref EADC_TIMER1_TRIGGER : Timer1 overflow pulse trigger
* - \ref EADC_TIMER2_TRIGGER : Timer2 overflow pulse trigger
* - \ref EADC_TIMER3_TRIGGER : Timer3 overflow pulse trigger
* - \ref EADC_PWM0TG0_TRIGGER : PWM0TG0 trigger
* - \ref EADC_PWM0TG1_TRIGGER : PWM0TG1 trigger
* - \ref EADC_PWM0TG2_TRIGGER : PWM0TG2 trigger
* - \ref EADC_PWM0TG3_TRIGGER : PWM0TG3 trigger
* - \ref EADC_PWM0TG4_TRIGGER : PWM0TG4 trigger
* - \ref EADC_PWM0TG5_TRIGGER : PWM0TG5 trigger
* - \ref EADC_PWM1TG0_TRIGGER : PWM1TG0 trigger
* - \ref EADC_PWM1TG1_TRIGGER : PWM1TG1 trigger
* - \ref EADC_PWM1TG2_TRIGGER : PWM1TG2 trigger
* - \ref EADC_PWM1TG3_TRIGGER : PWM1TG3 trigger
* - \ref EADC_PWM1TG4_TRIGGER : PWM1TG4 trigger
* - \ref EADC_PWM1TG5_TRIGGER : PWM1TG5 trigger
* @param[in] u32Channel Specifies the sample module channel, valid value are from 0 to 15.
* @return None
* @details Each of ADC control logic modules 0~15 which is configurable for ADC converter channel EADC_CH0~15 and trigger source.
* sample module 16~18 is fixed for ADC channel 16, 17, 18 input sources as band-gap voltage, temperature sensor, and battery power (VBAT).
*/
void EADC_ConfigSampleModule(EADC_T *eadc, \
uint32_t u32ModuleNum, \
uint32_t u32TriggerSrc, \
uint32_t u32Channel)
{
eadc->SCTL[u32ModuleNum] &= ~(EADC_SCTL_EXTFEN_Msk | EADC_SCTL_EXTREN_Msk | EADC_SCTL_TRGSEL_Msk | EADC_SCTL_CHSEL_Msk);
eadc->SCTL[u32ModuleNum] |= (u32TriggerSrc | u32Channel);
}
/**
* @brief Set trigger delay time.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 15.
* @param[in] u32TriggerDelayTime Decides the trigger delay time, valid range are between 0~0xFF.
* @param[in] u32DelayClockDivider Decides the trigger delay clock divider. Valid values are:
* - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_1 : Trigger delay clock frequency is ADC_CLK/1
* - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_2 : Trigger delay clock frequency is ADC_CLK/2
* - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_4 : Trigger delay clock frequency is ADC_CLK/4
* - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_16 : Trigger delay clock frequency is ADC_CLK/16
* @return None
* @details User can configure the trigger delay time by setting TRGDLYCNT (EADC_SCTLn[15:8], n=0~15) and TRGDLYDIV (EADC_SCTLn[7:6], n=0~15).
* Trigger delay time = (u32TriggerDelayTime) x Trigger delay clock period.
*/
void EADC_SetTriggerDelayTime(EADC_T *eadc, \
uint32_t u32ModuleNum, \
uint32_t u32TriggerDelayTime, \
uint32_t u32DelayClockDivider)
{
eadc->SCTL[u32ModuleNum] &= ~(EADC_SCTL_TRGDLYDIV_Msk | EADC_SCTL_TRGDLYCNT_Msk);
eadc->SCTL[u32ModuleNum] |= ((u32TriggerDelayTime << EADC_SCTL_TRGDLYCNT_Pos) | u32DelayClockDivider);
}
/**
* @brief Set ADC extend sample time.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 18.
* @param[in] u32ExtendSampleTime Decides the extend sampling time, the range is from 0~255 ADC clock. Valid value are from 0 to 0xFF.
* @return None
* @details When A/D converting at high conversion rate, the sampling time of analog input voltage may not enough if input channel loading is heavy,
* user can extend A/D sampling time after trigger source is coming to get enough sampling time.
*/
void EADC_SetExtendSampleTime(EADC_T *eadc, uint32_t u32ModuleNum, uint32_t u32ExtendSampleTime)
{
eadc->SCTL[u32ModuleNum] &= ~EADC_SCTL_EXTSMPT_Msk;
eadc->SCTL[u32ModuleNum] |= (u32ExtendSampleTime << EADC_SCTL_EXTSMPT_Pos);
}
/*@}*/ /* end of group EADC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group EADC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,596 @@
/**************************************************************************//**
* @file eadc.h
* @version V0.10
* @brief M480 series EADC driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __EADC_H__
#define __EADC_H__
/*---------------------------------------------------------------------------------------------------------*/
/* Include related headers */
/*---------------------------------------------------------------------------------------------------------*/
#include "M480.h"
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup EADC_Driver EADC Driver
@{
*/
/** @addtogroup EADC_EXPORTED_CONSTANTS EADC Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* EADC_CTL Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EADC_CTL_DIFFEN_SINGLE_END (0UL<<EADC_CTL_DIFFEN_Pos) /*!< Single-end input mode \hideinitializer */
#define EADC_CTL_DIFFEN_DIFFERENTIAL (1UL<<EADC_CTL_DIFFEN_Pos) /*!< Differential input mode \hideinitializer */
#define EADC_CTL_DMOF_STRAIGHT_BINARY (0UL<<EADC_CTL_DMOF_Pos) /*!< Select the straight binary format as the output format of the conversion result \hideinitializer */
#define EADC_CTL_DMOF_TWOS_COMPLEMENT (1UL<<EADC_CTL_DMOF_Pos) /*!< Select the 2's complement format as the output format of the conversion result \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* EADC_SCTL Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EADC_SCTL_CHSEL(x) ((x) << EADC_SCTL_CHSEL_Pos) /*!< A/D sample module channel selection \hideinitializer */
#define EADC_SCTL_TRGDLYDIV(x) ((x) << EADC_SCTL_TRGDLYDIV_Pos) /*!< A/D sample module start of conversion trigger delay clock divider selection \hideinitializer */
#define EADC_SCTL_TRGDLYCNT(x) ((x) << EADC_SCTL_TRGDLYCNT_Pos) /*!< A/D sample module start of conversion trigger delay time \hideinitializer */
#define EADC_SOFTWARE_TRIGGER (0UL<<EADC_SCTL_TRGSEL_Pos) /*!< Software trigger \hideinitializer */
#define EADC_FALLING_EDGE_TRIGGER (EADC_SCTL_EXTFEN_Msk | (1UL<<EADC_SCTL_TRGSEL_Pos)) /*!< STADC pin falling edge trigger \hideinitializer */
#define EADC_RISING_EDGE_TRIGGER (EADC_SCTL_EXTREN_Msk | (1UL<<EADC_SCTL_TRGSEL_Pos)) /*!< STADC pin rising edge trigger \hideinitializer */
#define EADC_FALLING_RISING_EDGE_TRIGGER (EADC_SCTL_EXTFEN_Msk | EADC_SCTL_EXTREN_Msk | (1UL<<EADC_SCTL_TRGSEL_Pos)) /*!< STADC pin both falling and rising edge trigger \hideinitializer */
#define EADC_ADINT0_TRIGGER (2UL<<EADC_SCTL_TRGSEL_Pos) /*!< ADC ADINT0 interrupt EOC pulse trigger \hideinitializer */
#define EADC_ADINT1_TRIGGER (3UL<<EADC_SCTL_TRGSEL_Pos) /*!< ADC ADINT1 interrupt EOC pulse trigger \hideinitializer */
#define EADC_TIMER0_TRIGGER (4UL<<EADC_SCTL_TRGSEL_Pos) /*!< Timer0 overflow pulse trigger \hideinitializer */
#define EADC_TIMER1_TRIGGER (5UL<<EADC_SCTL_TRGSEL_Pos) /*!< Timer1 overflow pulse trigger \hideinitializer */
#define EADC_TIMER2_TRIGGER (6UL<<EADC_SCTL_TRGSEL_Pos) /*!< Timer2 overflow pulse trigger \hideinitializer */
#define EADC_TIMER3_TRIGGER (7UL<<EADC_SCTL_TRGSEL_Pos) /*!< Timer3 overflow pulse trigger \hideinitializer */
#define EADC_PWM0TG0_TRIGGER (8UL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM0TG0 trigger \hideinitializer */
#define EADC_PWM0TG1_TRIGGER (9UL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM0TG1 trigger \hideinitializer */
#define EADC_PWM0TG2_TRIGGER (0xAUL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM0TG2 trigger \hideinitializer */
#define EADC_PWM0TG3_TRIGGER (0xBUL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM0TG3 trigger \hideinitializer */
#define EADC_PWM0TG4_TRIGGER (0xCUL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM0TG4 trigger \hideinitializer */
#define EADC_PWM0TG5_TRIGGER (0xDUL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM0TG5 trigger \hideinitializer */
#define EADC_PWM1TG0_TRIGGER (0xEUL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM1TG0 trigger \hideinitializer */
#define EADC_PWM1TG1_TRIGGER (0xFUL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM1TG1 trigger \hideinitializer */
#define EADC_PWM1TG2_TRIGGER (0x10UL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM1TG2 trigger \hideinitializer */
#define EADC_PWM1TG3_TRIGGER (0x11UL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM1TG3 trigger \hideinitializer */
#define EADC_PWM1TG4_TRIGGER (0x12UL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM1TG4 trigger \hideinitializer */
#define EADC_PWM1TG5_TRIGGER (0x13UL<<EADC_SCTL_TRGSEL_Pos) /*!< PWM1TG5 trigger \hideinitializer */
#define EADC_SCTL_TRGDLYDIV_DIVIDER_1 (0<<EADC_SCTL_TRGDLYDIV_Pos) /*!< Trigger delay clock frequency is ADC_CLK/1 \hideinitializer */
#define EADC_SCTL_TRGDLYDIV_DIVIDER_2 (0x1UL<<EADC_SCTL_TRGDLYDIV_Pos) /*!< Trigger delay clock frequency is ADC_CLK/2 \hideinitializer */
#define EADC_SCTL_TRGDLYDIV_DIVIDER_4 (0x2UL<<EADC_SCTL_TRGDLYDIV_Pos) /*!< Trigger delay clock frequency is ADC_CLK/4 \hideinitializer */
#define EADC_SCTL_TRGDLYDIV_DIVIDER_16 (0x3UL<<EADC_SCTL_TRGDLYDIV_Pos) /*!< Trigger delay clock frequency is ADC_CLK/16 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* EADC_CMP Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EADC_CMP_CMPCOND_LESS_THAN (0UL<<EADC_CMP_CMPCOND_Pos) /*!< The compare condition is "less than" \hideinitializer */
#define EADC_CMP_CMPCOND_GREATER_OR_EQUAL (1UL<<EADC_CMP_CMPCOND_Pos) /*!< The compare condition is "greater than or equal to" \hideinitializer */
#define EADC_CMP_CMPWEN_ENABLE (EADC_CMP_CMPWEN_Msk) /*!< Compare window mode enable \hideinitializer */
#define EADC_CMP_CMPWEN_DISABLE (~EADC_CMP_CMPWEN_Msk) /*!< Compare window mode disable \hideinitializer */
#define EADC_CMP_ADCMPIE_ENABLE (EADC_CMP_ADCMPIE_Msk) /*!< A/D result compare interrupt enable \hideinitializer */
#define EADC_CMP_ADCMPIE_DISABLE (~EADC_CMP_ADCMPIE_Msk) /*!< A/D result compare interrupt disable \hideinitializer */
/*@}*/ /* end of group EADC_EXPORTED_CONSTANTS */
/** @addtogroup EADC_EXPORTED_FUNCTIONS EADC Exported Functions
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* EADC Macro Definitions */
/*---------------------------------------------------------------------------------------------------------*/
/**
* @brief A/D Converter Control Circuits Reset.
* @param[in] eadc The pointer of the specified EADC module.
* @return None
* @details ADCRST bit (EADC_CT[1]) remains 1 during ADC reset, when ADC reset end, the ADCRST bit is automatically cleared to 0.
* \hideinitializer
*/
#define EADC_CONV_RESET(eadc) ((eadc)->CTL |= EADC_CTL_ADCRST_Msk)
/**
* @brief Enable PDMA transfer.
* @param[in] eadc The pointer of the specified EADC module.
* @return None
* @details When A/D conversion is completed, the converted data is loaded into EADC_DATn (n: 0 ~ 18) register,
* user can enable this bit to generate a PDMA data transfer request.
* @note When set PDMAEN bit (EADC_CTL[11]), user must set ADINTENn (EADC_CTL[5:2], n=0~3) = 0 to disable interrupt.
* \hideinitializer
*/
#define EADC_ENABLE_PDMA(eadc) ((eadc)->CTL |= EADC_CTL_PDMAEN_Msk)
/**
* @brief Disable PDMA transfer.
* @param[in] eadc The pointer of the specified EADC module.
* @return None
* @details This macro is used to disable PDMA transfer.
* \hideinitializer
*/
#define EADC_DISABLE_PDMA(eadc) ((eadc)->CTL &= (~EADC_CTL_PDMAEN_Msk))
/**
* @brief Enable double buffer mode.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 3.
* @return None
* @details The ADC controller supports a double buffer mode in sample module 0~3.
* If user enable DBMEN (EADC_SCTLn[23], n=0~3), the double buffer mode will enable.
* \hideinitializer
*/
#define EADC_ENABLE_DOUBLE_BUFFER(eadc, u32ModuleNum) ((eadc)->SCTL[(u32ModuleNum)] |= EADC_SCTL_DBMEN_Msk)
/**
* @brief Disable double buffer mode.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 3.
* @return None
* @details Sample has one sample result register.
* \hideinitializer
*/
#define EADC_DISABLE_DOUBLE_BUFFER(eadc, u32ModuleNum) ((eadc)->SCTL[(u32ModuleNum)] &= ~EADC_SCTL_DBMEN_Msk)
/**
* @brief Set ADIFn at A/D end of conversion.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 15.
* @return None
* @details The A/D converter generates ADIFn (EADC_STATUS2[3:0], n=0~3) at the start of conversion.
* \hideinitializer
*/
#define EADC_ENABLE_INT_POSITION(eadc, u32ModuleNum) ((eadc)->SCTL[(u32ModuleNum)] |= EADC_SCTL_INTPOS_Msk)
/**
* @brief Set ADIFn at A/D start of conversion.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 15.
* @return None
* @details The A/D converter generates ADIFn (EADC_STATUS2[3:0], n=0~3) at the end of conversion.
* \hideinitializer
*/
#define EADC_DISABLE_INT_POSITION(eadc, u32ModuleNum) ((eadc)->SCTL[(u32ModuleNum)] &= ~EADC_SCTL_INTPOS_Msk)
/**
* @brief Enable the interrupt.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32Mask Decides the combination of interrupt status bits. Each bit corresponds to a interrupt status.
* This parameter decides which interrupts will be enabled. Bit 0 is ADCIEN0, bit 1 is ADCIEN1..., bit 3 is ADCIEN3.
* @return None
* @details The A/D converter generates a conversion end ADIFn (EADC_STATUS2[n]) upon the end of specific sample module A/D conversion.
* If ADCIENn bit (EADC_CTL[n+2]) is set then conversion end interrupt request ADINTn is generated (n=0~3).
* \hideinitializer
*/
#define EADC_ENABLE_INT(eadc, u32Mask) ((eadc)->CTL |= ((u32Mask) << EADC_CTL_ADCIEN0_Pos))
/**
* @brief Disable the interrupt.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32Mask Decides the combination of interrupt status bits. Each bit corresponds to a interrupt status.
* This parameter decides which interrupts will be disabled. Bit 0 is ADCIEN0, bit 1 is ADCIEN1..., bit 3 is ADCIEN3.
* @return None
* @details Specific sample module A/D ADINT0 interrupt function Disabled.
* \hideinitializer
*/
#define EADC_DISABLE_INT(eadc, u32Mask) ((eadc)->CTL &= ~((u32Mask) << EADC_CTL_ADCIEN0_Pos))
/**
* @brief Enable the sample module interrupt.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32IntSel Decides which interrupt source will be used, valid value are from 0 to 3.
* @param[in] u32ModuleMask the combination of sample module interrupt status bits. Each bit corresponds to a sample module interrupt status.
* This parameter decides which sample module interrupts will be enabled, valid range are between 1~0x7FFFF.
* @return None
* @details There are 4 ADC interrupts ADINT0~3, and each of these interrupts has its own interrupt vector address.
* \hideinitializer
*/
#define EADC_ENABLE_SAMPLE_MODULE_INT(eadc, u32IntSel, u32ModuleMask) ((eadc)->INTSRC[(u32IntSel)] |= (u32ModuleMask))
/**
* @brief Disable the sample module interrupt.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32IntSel Decides which interrupt source will be used, valid value are from 0 to 3.
* @param[in] u32ModuleMask the combination of sample module interrupt status bits. Each bit corresponds to a sample module interrupt status.
* This parameter decides which sample module interrupts will be disabled, valid range are between 1~0x7FFFF.
* @return None
* @details There are 4 ADC interrupts ADINT0~3, and each of these interrupts has its own interrupt vector address.
* \hideinitializer
*/
#define EADC_DISABLE_SAMPLE_MODULE_INT(eadc, u32IntSel, u32ModuleMask) ((eadc)->INTSRC[(u32IntSel)] &= ~(u32ModuleMask))
/**
* @brief Set the input mode output format.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32Format Decides the output format. Valid values are:
* - EADC_CTL_DMOF_STRAIGHT_BINARY :Select the straight binary format as the output format of the conversion result.
* - EADC_CTL_DMOF_TWOS_COMPLEMENT :Select the 2's complement format as the output format of the conversion result.
* @return None
* @details The macro is used to set A/D input mode output format.
* \hideinitializer
*/
#define EADC_SET_DMOF(eadc, u32Format) ((eadc)->CTL = ((eadc)->CTL & ~EADC_CTL_DMOF_Msk) | (u32Format))
/**
* @brief Start the A/D conversion.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleMask The combination of sample module. Each bit corresponds to a sample module.
* This parameter decides which sample module will be conversion, valid range are between 1~0x7FFFF.
* Bit 0 is sample module 0, bit 1 is sample module 1..., bit 18 is sample module 18.
* @return None
* @details After write EADC_SWTRG register to start ADC conversion, the EADC_PENDSTS register will show which SAMPLE will conversion.
* \hideinitializer
*/
#define EADC_START_CONV(eadc, u32ModuleMask) ((eadc)->SWTRG = (u32ModuleMask))
/**
* @brief Cancel the conversion for sample module.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleMask The combination of sample module. Each bit corresponds to a sample module.
* This parameter decides which sample module will stop the conversion, valid range are between 1~0x7FFFF.
* Bit 0 is sample module 0, bit 1 is sample module 1..., bit 18 is sample module18.
* @return None
* @details If user want to disable the conversion of the sample module, user can write EADC_PENDSTS register to clear it.
* \hideinitializer
*/
#define EADC_STOP_CONV(eadc, u32ModuleMask) ((eadc)->PENDSTS = (u32ModuleMask))
/**
* @brief Get the conversion pending flag.
* @param[in] eadc The pointer of the specified EADC module.
* @return Return the conversion pending sample module.
* @details This STPFn(EADC_PENDSTS[18:0]) bit remains 1 during pending state, when the respective ADC conversion is end,
* the STPFn (n=0~18) bit is automatically cleared to 0.
* \hideinitializer
*/
#define EADC_GET_PENDING_CONV(eadc) ((eadc)->PENDSTS)
/**
* @brief Get the conversion data of the user-specified sample module.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 18.
* @return Return the conversion data of the user-specified sample module.
* @details This macro is used to read RESULT bit (EADC_DATn[15:0], n=0~18) field to get conversion data.
* \hideinitializer
*/
#define EADC_GET_CONV_DATA(eadc, u32ModuleNum) ((eadc)->DAT[(u32ModuleNum)] & EADC_DAT_RESULT_Msk)
/**
* @brief Get the data overrun flag of the user-specified sample module.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleMask The combination of data overrun status bits. Each bit corresponds to a data overrun status, valid range are between 1~0x7FFFF.
* @return Return the data overrun flag of the user-specified sample module.
* @details This macro is used to read OV bit (EADC_STATUS0[31:16], EADC_STATUS1[18:16]) field to get data overrun status.
* \hideinitializer
*/
#define EADC_GET_DATA_OVERRUN_FLAG(eadc, u32ModuleMask) ((((eadc)->STATUS0 >> EADC_STATUS0_OV_Pos) | ((eadc)->STATUS1 & EADC_STATUS1_OV_Msk)) & (u32ModuleMask))
/**
* @brief Get the data valid flag of the user-specified sample module.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleMask The combination of data valid status bits. Each bit corresponds to a data valid status, valid range are between 1~0x7FFFF.
* @return Return the data valid flag of the user-specified sample module.
* @details This macro is used to read VALID bit (EADC_STATUS0[15:0], EADC_STATUS1[2:0]) field to get data valid status.
* \hideinitializer
*/
#define EADC_GET_DATA_VALID_FLAG(eadc, u32ModuleMask) ((((eadc)->STATUS0 & EADC_STATUS0_VALID_Msk) | (((eadc)->STATUS1 & EADC_STATUS1_VALID_Msk) << 16)) & (u32ModuleMask))
/**
* @brief Get the double data of the user-specified sample module.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 18.
* @return Return the double data of the user-specified sample module.
* @details This macro is used to read RESULT bit (EADC_DDATn[15:0], n=0~3) field to get conversion data.
* \hideinitializer
*/
#define EADC_GET_DOUBLE_DATA(eadc, u32ModuleNum) ((eadc)->DDAT[(u32ModuleNum)] & EADC_DDAT0_RESULT_Msk)
/**
* @brief Get the user-specified interrupt flags.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32Mask The combination of interrupt status bits. Each bit corresponds to a interrupt status.
* Bit 0 is ADIF0, bit 1 is ADIF1..., bit 3 is ADIF3.
* Bit 4 is ADCMPF0, bit 5 is ADCMPF1..., bit 7 is ADCMPF3.
* @return Return the user-specified interrupt flags.
* @details This macro is used to get the user-specified interrupt flags.
* \hideinitializer
*/
#define EADC_GET_INT_FLAG(eadc, u32Mask) ((eadc)->STATUS2 & (u32Mask))
/**
* @brief Get the user-specified sample module overrun flags.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleMask The combination of sample module overrun status bits. Each bit corresponds to a sample module overrun status, valid range are between 1~0x7FFFF.
* @return Return the user-specified sample module overrun flags.
* @details This macro is used to get the user-specified sample module overrun flags.
* \hideinitializer
*/
#define EADC_GET_SAMPLE_MODULE_OV_FLAG(eadc, u32ModuleMask) ((eadc)->OVSTS & (u32ModuleMask))
/**
* @brief Clear the selected interrupt status bits.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32Mask The combination of compare interrupt status bits. Each bit corresponds to a compare interrupt status.
* Bit 0 is ADIF0, bit 1 is ADIF1..., bit 3 is ADIF3.
* Bit 4 is ADCMPF0, bit 5 is ADCMPF1..., bit 7 is ADCMPF3.
* @return None
* @details This macro is used to clear clear the selected interrupt status bits.
* \hideinitializer
*/
#define EADC_CLR_INT_FLAG(eadc, u32Mask) ((eadc)->STATUS2 = (u32Mask))
/**
* @brief Clear the selected sample module overrun status bits.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleMask The combination of sample module overrun status bits. Each bit corresponds to a sample module overrun status.
* Bit 0 is SPOVF0, bit 1 is SPOVF1..., bit 18 is SPOVF18.
* @return None
* @details This macro is used to clear the selected sample module overrun status bits.
* \hideinitializer
*/
#define EADC_CLR_SAMPLE_MODULE_OV_FLAG(eadc, u32ModuleMask) ((eadc)->OVSTS = (u32ModuleMask))
/**
* @brief Check all sample module A/D result data register overrun flags.
* @param[in] eadc The pointer of the specified EADC module.
* @retval 0 None of sample module data register overrun flag is set to 1.
* @retval 1 Any one of sample module data register overrun flag is set to 1.
* @details The AOV bit (EADC_STATUS2[27]) will keep 1 when any one of sample module data register overrun flag OVn (EADC_DATn[16]) is set to 1.
* \hideinitializer
*/
#define EADC_IS_DATA_OV(eadc) (((eadc)->STATUS2 & EADC_STATUS2_AOV_Msk) >> EADC_STATUS2_AOV_Pos)
/**
* @brief Check all sample module A/D result data register valid flags.
* @param[in] eadc The pointer of the specified EADC module.
* @retval 0 None of sample module data register valid flag is set to 1.
* @retval 1 Any one of sample module data register valid flag is set to 1.
* @details The AVALID bit (EADC_STATUS2[26]) will keep 1 when any one of sample module data register valid flag VALIDn (EADC_DATn[17]) is set to 1.
* \hideinitializer
*/
#define EADC_IS_DATA_VALID(eadc) (((eadc)->STATUS2 & EADC_STATUS2_AVALID_Msk) >> EADC_STATUS2_AVALID_Pos)
/**
* @brief Check all A/D sample module start of conversion overrun flags.
* @param[in] eadc The pointer of the specified EADC module.
* @retval 0 None of sample module event overrun flag is set to 1.
* @retval 1 Any one of sample module event overrun flag is set to 1.
* @details The STOVF bit (EADC_STATUS2[25]) will keep 1 when any one of sample module event overrun flag SPOVFn (EADC_OVSTS[n]) is set to 1.
* \hideinitializer
*/
#define EADC_IS_SAMPLE_MODULE_OV(eadc) (((eadc)->STATUS2 & EADC_STATUS2_STOVF_Msk) >> EADC_STATUS2_STOVF_Pos)
/**
* @brief Check all A/D interrupt flag overrun bits.
* @param[in] eadc The pointer of the specified EADC module.
* @retval 0 None of ADINT interrupt flag is overwritten to 1.
* @retval 1 Any one of ADINT interrupt flag is overwritten to 1.
* @details The ADOVIF bit (EADC_STATUS2[24]) will keep 1 when any one of ADINT interrupt flag ADOVIFn (EADC_STATUS2[11:8]) is overwritten to 1.
* \hideinitializer
*/
#define EADC_IS_INT_FLAG_OV(eadc) (((eadc)->STATUS2 & EADC_STATUS2_ADOVIF_Msk) >> EADC_STATUS2_ADOVIF_Pos)
/**
* @brief Get the busy state of EADC.
* @param[in] eadc The pointer of the specified EADC module.
* @retval 0 Idle state.
* @retval 1 Busy state.
* @details This macro is used to read BUSY bit (EADC_STATUS2[23]) to get busy state.
* \hideinitializer
*/
#define EADC_IS_BUSY(eadc) (((eadc)->STATUS2 & EADC_STATUS2_BUSY_Msk) >> EADC_STATUS2_BUSY_Pos)
/**
* @brief Configure the comparator 0 and enable it.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum specifies the compare sample module, valid value are from 0 to 18.
* @param[in] u32Condition specifies the compare condition. Valid values are:
* - \ref EADC_CMP_CMPCOND_LESS_THAN :The compare condition is "less than the compare value"
* - \ref EADC_CMP_CMPCOND_GREATER_OR_EQUAL :The compare condition is "greater than or equal to the compare value
* @param[in] u16CMPData specifies the compare value, valid range are between 0~0xFFF.
* @param[in] u32MatchCount specifies the match count setting, valid range are between 0~0xF.
* @return None
* @details For example, ADC_ENABLE_CMP0(EADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x800, 10, EADC_CMP_CMPWEN_DISABLE, EADC_CMP_ADCMPIE_ENABLE);
* Means EADC will assert comparator 0 flag if sample module 5 conversion result is greater or
* equal to 0x800 for 10 times continuously, and a compare interrupt request is generated.
* \hideinitializer
*/
#define EADC_ENABLE_CMP0(eadc,\
u32ModuleNum,\
u32Condition,\
u16CMPData,\
u32MatchCount) ((eadc)->CMP[0] |=(((u32ModuleNum) << EADC_CMP_CMPSPL_Pos)|\
(u32Condition) |\
((u16CMPData) << EADC_CMP_CMPDAT_Pos)| \
(((u32MatchCount) - 1) << EADC_CMP_CMPMCNT_Pos)|\
EADC_CMP_ADCMPEN_Msk))
/**
* @brief Configure the comparator 1 and enable it.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum specifies the compare sample module, valid value are from 0 to 18.
* @param[in] u32Condition specifies the compare condition. Valid values are:
* - \ref EADC_CMP_CMPCOND_LESS_THAN :The compare condition is "less than the compare value"
* - \ref EADC_CMP_CMPCOND_GREATER_OR_EQUAL :The compare condition is "greater than or equal to the compare value
* @param[in] u16CMPData specifies the compare value, valid range are between 0~0xFFF.
* @param[in] u32MatchCount specifies the match count setting, valid range are between 0~0xF.
* @return None
* @details For example, ADC_ENABLE_CMP1(EADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x800, 10, EADC_CMP_ADCMPIE_ENABLE);
* Means EADC will assert comparator 1 flag if sample module 5 conversion result is greater or
* equal to 0x800 for 10 times continuously, and a compare interrupt request is generated.
* \hideinitializer
*/
#define EADC_ENABLE_CMP1(eadc,\
u32ModuleNum,\
u32Condition,\
u16CMPData,\
u32MatchCount) ((eadc)->CMP[1] |=(((u32ModuleNum) << EADC_CMP_CMPSPL_Pos)|\
(u32Condition) |\
((u16CMPData) << EADC_CMP_CMPDAT_Pos)| \
(((u32MatchCount) - 1) << EADC_CMP_CMPMCNT_Pos)|\
EADC_CMP_ADCMPEN_Msk))
/**
* @brief Configure the comparator 2 and enable it.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum specifies the compare sample module, valid value are from 0 to 18.
* @param[in] u32Condition specifies the compare condition. Valid values are:
* - \ref EADC_CMP_CMPCOND_LESS_THAN :The compare condition is "less than the compare value"
* - \ref EADC_CMP_CMPCOND_GREATER_OR_EQUAL :The compare condition is "greater than or equal to the compare value
* @param[in] u16CMPData specifies the compare value, valid range are between 0~0xFFF.
* @param[in] u32MatchCount specifies the match count setting, valid range are between 0~0xF.
* @return None
* @details For example, ADC_ENABLE_CMP2(EADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x800, 10, EADC_CMP_CMPWEN_DISABLE, EADC_CMP_ADCMPIE_ENABLE);
* Means EADC will assert comparator 2 flag if sample module 5 conversion result is greater or
* equal to 0x800 for 10 times continuously, and a compare interrupt request is generated.
* \hideinitializer
*/
#define EADC_ENABLE_CMP2(eadc,\
u32ModuleNum,\
u32Condition,\
u16CMPData,\
u32MatchCount) ((eadc)->CMP[2] |=(((u32ModuleNum) << EADC_CMP_CMPSPL_Pos)|\
(u32Condition) |\
((u16CMPData) << EADC_CMP_CMPDAT_Pos)| \
(((u32MatchCount) - 1) << EADC_CMP_CMPMCNT_Pos)|\
EADC_CMP_ADCMPEN_Msk))
/**
* @brief Configure the comparator 3 and enable it.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32ModuleNum specifies the compare sample module, valid value are from 0 to 18.
* @param[in] u32Condition specifies the compare condition. Valid values are:
* - \ref EADC_CMP_CMPCOND_LESS_THAN :The compare condition is "less than the compare value"
* - \ref EADC_CMP_CMPCOND_GREATER_OR_EQUAL :The compare condition is "greater than or equal to the compare value
* @param[in] u16CMPData specifies the compare value, valid range are between 0~0xFFF.
* @param[in] u32MatchCount specifies the match count setting, valid range are between 1~0xF.
* @return None
* @details For example, ADC_ENABLE_CMP3(EADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x800, 10, EADC_CMP_ADCMPIE_ENABLE);
* Means EADC will assert comparator 3 flag if sample module 5 conversion result is greater or
* equal to 0x800 for 10 times continuously, and a compare interrupt request is generated.
* \hideinitializer
*/
#define EADC_ENABLE_CMP3(eadc,\
u32ModuleNum,\
u32Condition,\
u16CMPData,\
u32MatchCount) ((eadc)->CMP[3] |=(((u32ModuleNum) << EADC_CMP_CMPSPL_Pos)|\
(u32Condition) |\
((u16CMPData) << EADC_CMP_CMPDAT_Pos)| \
(((u32MatchCount) - 1) << EADC_CMP_CMPMCNT_Pos)|\
EADC_CMP_ADCMPEN_Msk))
/**
* @brief Enable the compare window mode.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32CMP Specifies the compare register, valid value are 0 and 2.
* @return None
* @details ADCMPF0 (EADC_STATUS2[4]) will be set when both EADC_CMP0 and EADC_CMP1 compared condition matched.
* \hideinitializer
*/
#define EADC_ENABLE_CMP_WINDOW_MODE(eadc, u32CMP) ((eadc)->CMP[(u32CMP)] |= EADC_CMP_CMPWEN_Msk)
/**
* @brief Disable the compare window mode.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32CMP Specifies the compare register, valid value are 0 and 2.
* @return None
* @details ADCMPF2 (EADC_STATUS2[6]) will be set when both EADC_CMP2 and EADC_CMP3 compared condition matched.
* \hideinitializer
*/
#define EADC_DISABLE_CMP_WINDOW_MODE(eadc, u32CMP) ((eadc)->CMP[(u32CMP)] &= ~EADC_CMP_CMPWEN_Msk)
/**
* @brief Enable the compare interrupt.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32CMP Specifies the compare register, valid value are from 0 to 3.
* @return None
* @details If the compare function is enabled and the compare condition matches the setting of CMPCOND (EADC_CMPn[2], n=0~3)
* and CMPMCNT (EADC_CMPn[11:8], n=0~3), ADCMPFn (EADC_STATUS2[7:4], n=0~3) will be asserted, in the meanwhile,
* if ADCMPIE is set to 1, a compare interrupt request is generated.
* \hideinitializer
*/
#define EADC_ENABLE_CMP_INT(eadc, u32CMP) ((eadc)->CMP[(u32CMP)] |= EADC_CMP_ADCMPIE_Msk)
/**
* @brief Disable the compare interrupt.
* @param[in] eadc The pointer of the specified EADC module.
* @param[in] u32CMP Specifies the compare register, valid value are from 0 to 3.
* @return None
* @details This macro is used to disable the compare interrupt.
* \hideinitializer
*/
#define EADC_DISABLE_CMP_INT(eadc, u32CMP) ((eadc)->CMP[(u32CMP)] &= ~EADC_CMP_ADCMPIE_Msk)
/**
* @brief Disable comparator 0.
* @param[in] eadc The pointer of the specified EADC module.
* @return None
* @details This macro is used to disable comparator 0.
* \hideinitializer
*/
#define EADC_DISABLE_CMP0(eadc) ((eadc)->CMP[0] = 0)
/**
* @brief Disable comparator 1.
* @param[in] eadc The pointer of the specified EADC module.
* @return None
* @details This macro is used to disable comparator 1.
* \hideinitializer
*/
#define EADC_DISABLE_CMP1(eadc) ((eadc)->CMP[1] = 0)
/**
* @brief Disable comparator 2.
* @param[in] eadc The pointer of the specified EADC module.
* @return None
* @details This macro is used to disable comparator 2.
* \hideinitializer
*/
#define EADC_DISABLE_CMP2(eadc) ((eadc)->CMP[2] = 0)
/**
* @brief Disable comparator 3.
* @param[in] eadc The pointer of the specified EADC module.
* @return None
* @details This macro is used to disable comparator 3.
* \hideinitializer
*/
#define EADC_DISABLE_CMP3(eadc) ((eadc)->CMP[3] = 0)
/*---------------------------------------------------------------------------------------------------------*/
/* Define EADC functions prototype */
/*---------------------------------------------------------------------------------------------------------*/
void EADC_Open(EADC_T *eadc, uint32_t u32InputMode);
void EADC_Close(EADC_T *eadc);
void EADC_ConfigSampleModule(EADC_T *eadc, uint32_t u32ModuleNum, uint32_t u32TriggerSrc, uint32_t u32Channel);
void EADC_SetTriggerDelayTime(EADC_T *eadc, uint32_t u32ModuleNum, uint32_t u32TriggerDelayTime, uint32_t u32DelayClockDivider);
void EADC_SetExtendSampleTime(EADC_T *eadc, uint32_t u32ModuleNum, uint32_t u32ExtendSampleTime);
/*@}*/ /* end of group EADC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group EADC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __EADC_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,190 @@
/**************************************************************************//**
* @file ebi.c
* @version V3.00
* @brief M480 series External Bus Interface(EBI) driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_EBI_Driver EBI Driver
@{
*/
/** @addtogroup M480_EBI_EXPORTED_FUNCTIONS EBI Exported Functions
@{
*/
/**
* @brief Initialize EBI for specify Bank
*
* @param[in] u32Bank Bank number for EBI. Valid values are:
* - \ref EBI_BANK0
* - \ref EBI_BANK1
* - \ref EBI_BANK2
* @param[in] u32DataWidth Data bus width. Valid values are:
* - \ref EBI_BUSWIDTH_8BIT
* - \ref EBI_BUSWIDTH_16BIT
* @param[in] u32TimingClass Default timing configuration. Valid values are:
* - \ref EBI_TIMING_FASTEST
* - \ref EBI_TIMING_VERYFAST
* - \ref EBI_TIMING_FAST
* - \ref EBI_TIMING_NORMAL
* - \ref EBI_TIMING_SLOW
* - \ref EBI_TIMING_VERYSLOW
* - \ref EBI_TIMING_SLOWEST
* @param[in] u32BusMode Set EBI bus operate mode. Valid values are:
* - \ref EBI_OPMODE_NORMAL
* - \ref EBI_OPMODE_CACCESS
* - \ref EBI_OPMODE_ADSEPARATE
* @param[in] u32CSActiveLevel CS is active High/Low. Valid values are:
* - \ref EBI_CS_ACTIVE_HIGH
* - \ref EBI_CS_ACTIVE_LOW
*
* @return None
*
* @details This function is used to open specify EBI bank with different bus width, timing setting and \n
* active level of CS pin to access EBI device.
* @note Write Buffer Enable(WBUFEN) and Extend Time Of ALE(TALE) are only available in EBI bank0 control register.
*/
void EBI_Open(uint32_t u32Bank, uint32_t u32DataWidth, uint32_t u32TimingClass, uint32_t u32BusMode, uint32_t u32CSActiveLevel)
{
uint32_t u32Index0 = (uint32_t)&EBI->CTL0 + (uint32_t)u32Bank * 0x10U;
uint32_t u32Index1 = (uint32_t)&EBI->TCTL0 + (uint32_t)u32Bank * 0x10U;
volatile uint32_t *pu32EBICTL = (uint32_t *)( u32Index0 );
volatile uint32_t *pu32EBITCTL = (uint32_t *)( u32Index1 );
if(u32DataWidth == EBI_BUSWIDTH_8BIT) {
*pu32EBICTL &= ~EBI_CTL_DW16_Msk;
} else {
*pu32EBICTL |= EBI_CTL_DW16_Msk;
}
*pu32EBICTL |= u32BusMode;
switch(u32TimingClass) {
case EBI_TIMING_FASTEST:
*pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) |
(EBI_MCLKDIV_1 << EBI_CTL_MCLKDIV_Pos) |
(u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk;
*pu32EBITCTL = 0x0U;
break;
case EBI_TIMING_VERYFAST:
*pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) |
(EBI_MCLKDIV_1 << EBI_CTL_MCLKDIV_Pos) |
(u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk |
(0x3U << EBI_CTL_TALE_Pos) ;
*pu32EBITCTL = 0x03003318U;
break;
case EBI_TIMING_FAST:
*pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) |
(EBI_MCLKDIV_2 << EBI_CTL_MCLKDIV_Pos) |
(u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk;
*pu32EBITCTL = 0x0U;
break;
case EBI_TIMING_NORMAL:
*pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) |
(EBI_MCLKDIV_2 << EBI_CTL_MCLKDIV_Pos) |
(u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk |
(0x3U << EBI_CTL_TALE_Pos) ;
*pu32EBITCTL = 0x03003318U;
break;
case EBI_TIMING_SLOW:
*pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) |
(EBI_MCLKDIV_2 << EBI_CTL_MCLKDIV_Pos) |
(u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk |
(0x7U << EBI_CTL_TALE_Pos) ;
*pu32EBITCTL = 0x07007738U;
break;
case EBI_TIMING_VERYSLOW:
*pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) |
(EBI_MCLKDIV_4 << EBI_CTL_MCLKDIV_Pos) |
(u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk |
(0x7U << EBI_CTL_TALE_Pos) ;
*pu32EBITCTL = 0x07007738U;
break;
case EBI_TIMING_SLOWEST:
*pu32EBICTL = (*pu32EBICTL & ~(EBI_CTL_MCLKDIV_Msk | EBI_CTL_TALE_Msk)) |
(EBI_MCLKDIV_8 << EBI_CTL_MCLKDIV_Pos) |
(u32CSActiveLevel << EBI_CTL_CSPOLINV_Pos) | EBI_CTL_EN_Msk |
(0x7U << EBI_CTL_TALE_Pos) ;
*pu32EBITCTL = 0x07007738U;
break;
default:
*pu32EBICTL &= ~EBI_CTL_EN_Msk;
break;
}
}
/**
* @brief Disable EBI on specify Bank
*
* @param[in] u32Bank Bank number for EBI. Valid values are:
* - \ref EBI_BANK0
* - \ref EBI_BANK1
* - \ref EBI_BANK2
*
* @return None
*
* @details This function is used to close specify EBI function.
*/
void EBI_Close(uint32_t u32Bank)
{
uint32_t u32Index = (uint32_t)&EBI->CTL0 + u32Bank * 0x10U;
volatile uint32_t *pu32EBICTL = (uint32_t *)( u32Index );
*pu32EBICTL &= ~EBI_CTL_EN_Msk;
}
/**
* @brief Set EBI Bus Timing for specify Bank
*
* @param[in] u32Bank Bank number for EBI. Valid values are:
* - \ref EBI_BANK0
* - \ref EBI_BANK1
* - \ref EBI_BANK2
* @param[in] u32TimingConfig Configure EBI timing settings, includes TACC, TAHD, W2X and R2R setting.
* @param[in] u32MclkDiv Divider for MCLK. Valid values are:
* - \ref EBI_MCLKDIV_1
* - \ref EBI_MCLKDIV_2
* - \ref EBI_MCLKDIV_4
* - \ref EBI_MCLKDIV_8
* - \ref EBI_MCLKDIV_16
* - \ref EBI_MCLKDIV_32
* - \ref EBI_MCLKDIV_64
* - \ref EBI_MCLKDIV_128
*
* @return None
*
* @details This function is used to configure specify EBI bus timing for access EBI device.
*/
void EBI_SetBusTiming(uint32_t u32Bank, uint32_t u32TimingConfig, uint32_t u32MclkDiv)
{
uint32_t u32Index0 = (uint32_t)&EBI->CTL0 + (uint32_t)u32Bank * 0x10U;
uint32_t u32Index1 = (uint32_t)&EBI->TCTL0 + (uint32_t)u32Bank * 0x10U;
volatile uint32_t *pu32EBICTL = (uint32_t *)( u32Index0 );
volatile uint32_t *pu32EBITCTL = (uint32_t *)( u32Index1 );
*pu32EBICTL = (*pu32EBICTL & ~EBI_CTL_MCLKDIV_Msk) | (u32MclkDiv << EBI_CTL_MCLKDIV_Pos);
*pu32EBITCTL = u32TimingConfig;
}
/*@}*/ /* end of group M480_EBI_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_EBI_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,351 @@
/**************************************************************************//**
* @file ebi.h
* @version V3.00
* @brief M480 series External Bus Interface(EBI) driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __EBI_H__
#define __EBI_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_EBI_Driver EBI Driver
@{
*/
/** @addtogroup M480_EBI_EXPORTED_CONSTANTS EBI Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* Miscellaneous Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EBI_BANK0_BASE_ADDR 0x60000000UL /*!< EBI bank0 base address \hideinitializer */
#define EBI_BANK1_BASE_ADDR 0x60100000UL /*!< EBI bank1 base address \hideinitializer */
#define EBI_BANK2_BASE_ADDR 0x60200000UL /*!< EBI bank2 base address \hideinitializer */
#define EBI_MAX_SIZE 0x00100000UL /*!< Maximum EBI size for each bank is 1 MB \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Constants for EBI bank number */
/*---------------------------------------------------------------------------------------------------------*/
#define EBI_BANK0 0UL /*!< EBI bank 0 \hideinitializer */
#define EBI_BANK1 1UL /*!< EBI bank 1 \hideinitializer */
#define EBI_BANK2 2UL /*!< EBI bank 2 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Constants for EBI data bus width */
/*---------------------------------------------------------------------------------------------------------*/
#define EBI_BUSWIDTH_8BIT 8UL /*!< EBI bus width is 8-bit \hideinitializer */
#define EBI_BUSWIDTH_16BIT 16UL /*!< EBI bus width is 16-bit \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Constants for EBI CS Active Level */
/*---------------------------------------------------------------------------------------------------------*/
#define EBI_CS_ACTIVE_LOW 0UL /*!< EBI CS active level is low \hideinitializer */
#define EBI_CS_ACTIVE_HIGH 1UL /*!< EBI CS active level is high \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Constants for EBI MCLK divider and Timing */
/*---------------------------------------------------------------------------------------------------------*/
#define EBI_MCLKDIV_1 0x0UL /*!< EBI output clock(MCLK) is HCLK/1 \hideinitializer */
#define EBI_MCLKDIV_2 0x1UL /*!< EBI output clock(MCLK) is HCLK/2 \hideinitializer */
#define EBI_MCLKDIV_4 0x2UL /*!< EBI output clock(MCLK) is HCLK/4 \hideinitializer */
#define EBI_MCLKDIV_8 0x3UL /*!< EBI output clock(MCLK) is HCLK/8 \hideinitializer */
#define EBI_MCLKDIV_16 0x4UL /*!< EBI output clock(MCLK) is HCLK/16 \hideinitializer */
#define EBI_MCLKDIV_32 0x5UL /*!< EBI output clock(MCLK) is HCLK/32 \hideinitializer */
#define EBI_MCLKDIV_64 0x6UL /*!< EBI output clock(MCLK) is HCLK/64 \hideinitializer */
#define EBI_MCLKDIV_128 0x7UL /*!< EBI output clock(MCLK) is HCLK/128 \hideinitializer */
#define EBI_TIMING_FASTEST 0x0UL /*!< EBI timing is the fastest \hideinitializer */
#define EBI_TIMING_VERYFAST 0x1UL /*!< EBI timing is very fast \hideinitializer */
#define EBI_TIMING_FAST 0x2UL /*!< EBI timing is fast \hideinitializer */
#define EBI_TIMING_NORMAL 0x3UL /*!< EBI timing is normal \hideinitializer */
#define EBI_TIMING_SLOW 0x4UL /*!< EBI timing is slow \hideinitializer */
#define EBI_TIMING_VERYSLOW 0x5UL /*!< EBI timing is very slow \hideinitializer */
#define EBI_TIMING_SLOWEST 0x6UL /*!< EBI timing is the slowest \hideinitializer */
#define EBI_OPMODE_NORMAL 0x0UL /*!< EBI bus operate in normal mode \hideinitializer */
#define EBI_OPMODE_CACCESS (EBI_CTL_CACCESS_Msk) /*!< EBI bus operate in Continuous Data Access mode \hideinitializer */
#define EBI_OPMODE_ADSEPARATE (EBI_CTL_ADSEPEN_Msk) /*!< EBI bus operate in AD Separate mode \hideinitializer */
/*@}*/ /* end of group EBI_EXPORTED_CONSTANTS */
/** @addtogroup M480_EBI_EXPORTED_FUNCTIONS EBI Exported Functions
@{
*/
/**
* @brief Read 8-bit data on EBI bank0
*
* @param[in] u32Addr The data address on EBI bank0.
*
* @return 8-bit Data
*
* @details This macro is used to read 8-bit data from specify address on EBI bank0.
* \hideinitializer
*/
#define EBI0_READ_DATA8(u32Addr) (*((volatile unsigned char *)(EBI_BANK0_BASE_ADDR+(u32Addr))))
/**
* @brief Write 8-bit data to EBI bank0
*
* @param[in] u32Addr The data address on EBI bank0.
* @param[in] u32Data Specify data to be written.
*
* @return None
*
* @details This macro is used to write 8-bit data to specify address on EBI bank0.
* \hideinitializer
*/
#define EBI0_WRITE_DATA8(u32Addr, u32Data) (*((volatile unsigned char *)(EBI_BANK0_BASE_ADDR+(u32Addr))) = (u32Data))
/**
* @brief Read 16-bit data on EBI bank0
*
* @param[in] u32Addr The data address on EBI bank0.
*
* @return 16-bit Data
*
* @details This macro is used to read 16-bit data from specify address on EBI bank0.
* \hideinitializer
*/
#define EBI0_READ_DATA16(u32Addr) (*((volatile unsigned short *)(EBI_BANK0_BASE_ADDR+(u32Addr))))
/**
* @brief Write 16-bit data to EBI bank0
*
* @param[in] u32Addr The data address on EBI bank0.
* @param[in] u32Data Specify data to be written.
*
* @return None
*
* @details This macro is used to write 16-bit data to specify address on EBI bank0.
* \hideinitializer
*/
#define EBI0_WRITE_DATA16(u32Addr, u32Data) (*((volatile unsigned short *)(EBI_BANK0_BASE_ADDR+(u32Addr))) = (u32Data))
/**
* @brief Read 32-bit data on EBI bank0
*
* @param[in] u32Addr The data address on EBI bank0.
*
* @return 32-bit Data
*
* @details This macro is used to read 32-bit data from specify address on EBI bank0.
* \hideinitializer
*/
#define EBI0_READ_DATA32(u32Addr) (*((volatile unsigned int *)(EBI_BANK0_BASE_ADDR+(u32Addr))))
/**
* @brief Write 32-bit data to EBI bank0
*
* @param[in] u32Addr The data address on EBI bank0.
* @param[in] u32Data Specify data to be written.
*
* @return None
*
* @details This macro is used to write 32-bit data to specify address on EBI bank0.
* \hideinitializer
*/
#define EBI0_WRITE_DATA32(u32Addr, u32Data) (*((volatile unsigned int *)(EBI_BANK0_BASE_ADDR+(u32Addr))) = (u32Data))
/**
* @brief Read 8-bit data on EBI bank1
*
* @param[in] u32Addr The data address on EBI bank1.
*
* @return 8-bit Data
*
* @details This macro is used to read 8-bit data from specify address on EBI bank1.
* \hideinitializer
*/
#define EBI1_READ_DATA8(u32Addr) (*((volatile unsigned char *)(EBI_BANK1_BASE_ADDR+(u32Addr))))
/**
* @brief Write 8-bit data to EBI bank1
*
* @param[in] u32Addr The data address on EBI bank1.
* @param[in] u32Data Specify data to be written.
*
* @return None
*
* @details This macro is used to write 8-bit data to specify address on EBI bank1.
* \hideinitializer
*/
#define EBI1_WRITE_DATA8(u32Addr, u32Data) (*((volatile unsigned char *)(EBI_BANK1_BASE_ADDR+(u32Addr))) = (u32Data))
/**
* @brief Read 16-bit data on EBI bank1
*
* @param[in] u32Addr The data address on EBI bank1.
*
* @return 16-bit Data
*
* @details This macro is used to read 16-bit data from specify address on EBI bank1.
* \hideinitializer
*/
#define EBI1_READ_DATA16(u32Addr) (*((volatile unsigned short *)(EBI_BANK1_BASE_ADDR+(u32Addr))))
/**
* @brief Write 16-bit data to EBI bank1
*
* @param[in] u32Addr The data address on EBI bank1.
* @param[in] u32Data Specify data to be written.
*
* @return None
*
* @details This macro is used to write 16-bit data to specify address on EBI bank1.
* \hideinitializer
*/
#define EBI1_WRITE_DATA16(u32Addr, u32Data) (*((volatile unsigned short *)(EBI_BANK1_BASE_ADDR+(u32Addr))) = (u32Data))
/**
* @brief Read 32-bit data on EBI bank1
*
* @param[in] u32Addr The data address on EBI bank1.
*
* @return 32-bit Data
*
* @details This macro is used to read 32-bit data from specify address on EBI bank1.
* \hideinitializer
*/
#define EBI1_READ_DATA32(u32Addr) (*((volatile unsigned int *)(EBI_BANK1_BASE_ADDR+(u32Addr))))
/**
* @brief Write 32-bit data to EBI bank1
*
* @param[in] u32Addr The data address on EBI bank1.
* @param[in] u32Data Specify data to be written.
*
* @return None
*
* @details This macro is used to write 32-bit data to specify address on EBI bank1.
* \hideinitializer
*/
#define EBI1_WRITE_DATA32(u32Addr, u32Data) (*((volatile unsigned int *)(EBI_BANK1_BASE_ADDR+(u32Addr))) = (u32Data))
/**
* @brief Read 8-bit data on EBI bank2
*
* @param[in] u32Addr The data address on EBI bank2.
*
* @return 8-bit Data
*
* @details This macro is used to read 8-bit data from specify address on EBI bank2.
* \hideinitializer
*/
#define EBI2_READ_DATA8(u32Addr) (*((volatile unsigned char *)(EBI_BANK2_BASE_ADDR+(u32Addr))))
/**
* @brief Write 8-bit data to EBI bank2
*
* @param[in] u32Addr The data address on EBI bank2.
* @param[in] u32Data Specify data to be written.
*
* @return None
*
* @details This macro is used to write 8-bit data to specify address on EBI bank2.
* \hideinitializer
*/
#define EBI2_WRITE_DATA8(u32Addr, u32Data) (*((volatile unsigned char *)(EBI_BANK2_BASE_ADDR+(u32Addr))) = (u32Data))
/**
* @brief Read 16-bit data on EBI bank2
*
* @param[in] u32Addr The data address on EBI bank2.
*
* @return 16-bit Data
*
* @details This macro is used to read 16-bit data from specify address on EBI bank2.
* \hideinitializer
*/
#define EBI2_READ_DATA16(u32Addr) (*((volatile unsigned short *)(EBI_BANK2_BASE_ADDR+(u32Addr))))
/**
* @brief Write 16-bit data to EBI bank2
*
* @param[in] u32Addr The data address on EBI bank2.
* @param[in] u32Data Specify data to be written.
*
* @return None
*
* @details This macro is used to write 16-bit data to specify address on EBI bank2.
* \hideinitializer
*/
#define EBI2_WRITE_DATA16(u32Addr, u32Data) (*((volatile unsigned short *)(EBI_BANK2_BASE_ADDR+(u32Addr))) = (u32Data))
/**
* @brief Read 32-bit data on EBI bank2
*
* @param[in] u32Addr The data address on EBI bank2.
*
* @return 32-bit Data
*
* @details This macro is used to read 32-bit data from specify address on EBI bank2.
* \hideinitializer
*/
#define EBI2_READ_DATA32(u32Addr) (*((volatile unsigned int *)(EBI_BANK2_BASE_ADDR+(u32Addr))))
/**
* @brief Write 32-bit data to EBI bank2
*
* @param[in] u32Addr The data address on EBI bank2.
* @param[in] u32Data Specify data to be written.
*
* @return None
*
* @details This macro is used to write 32-bit data to specify address on EBI bank2.
* \hideinitializer
*/
#define EBI2_WRITE_DATA32(u32Addr, u32Data) (*((volatile unsigned int *)(EBI_BANK2_BASE_ADDR+(u32Addr))) = (u32Data))
/**
* @brief Enable EBI Write Buffer
*
* @param None
*
* @return None
*
* @details This macro is used to improve EBI write operation for EBI bank0 and bank1.
* \hideinitializer
*/
#define EBI_ENABLE_WRITE_BUFFER() (EBI->CTL0 |= EBI_CTL_WBUFEN_Msk);
/**
* @brief Disable EBI Write Buffer
*
* @param None
*
* @return None
*
* @details This macro is used to disable EBI write buffer function.
* \hideinitializer
*/
#define EBI_DISABLE_WRITE_BUFFER() (EBI->CTL0 &= ~EBI_CTL_WBUFEN_Msk);
void EBI_Open(uint32_t u32Bank, uint32_t u32DataWidth, uint32_t u32TimingClass, uint32_t u32BusMode, uint32_t u32CSActiveLevel);
void EBI_Close(uint32_t u32Bank);
void EBI_SetBusTiming(uint32_t u32Bank, uint32_t u32TimingConfig, uint32_t u32MclkDiv);
/*@}*/ /* end of group M480_EBI_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_EBI_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,111 @@
/**************************************************************************//**
* @file ecap.c
* @version V3.00
* @brief Enhanced Input Capture Timer (ECAP) driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup ECAP_Driver ECAP Driver
@{
*/
/** @addtogroup ECAP_EXPORTED_FUNCTIONS ECAP Exported Functions
@{
*/
/**
* @brief Enable ECAP function
* @param[in] ecap The pointer of the specified ECAP module.
* @param[in] u32FuncMask Input capture function select
* - \ref ECAP_DISABLE_COMPARE
* - \ref ECAP_COMPARE_FUNCTION
* @return None
* @details This macro enable input capture function and select compare and reload function.
*/
void ECAP_Open(ECAP_T* ecap, uint32_t u32FuncMask)
{
/* Clear Input capture mode*/
ecap->CTL0 = ecap->CTL0 & ~(ECAP_CTL0_CMPEN_Msk);
/* Enable Input Capture and set mode */
ecap->CTL0 |= ECAP_CTL0_CAPEN_Msk | (u32FuncMask);
}
/**
* @brief Disable ECAP function
* @param[in] ecap The pointer of the specified ECAP module.
* @return None
* @details This macro disable input capture function.
*/
void ECAP_Close(ECAP_T* ecap)
{
/* Disable Input Capture*/
ecap->CTL0 &= ~ECAP_CTL0_CAPEN_Msk;
}
/**
* @brief This macro is used to enable input channel interrupt
* @param[in] ecap Specify ECAP port
* @param[in] u32Mask The input channel Mask
* - \ref ECAP_CTL0_CAPIEN0_Msk
* - \ref ECAP_CTL0_CAPIEN1_Msk
* - \ref ECAP_CTL0_CAPIEN2_Msk
* - \ref ECAP_CTL0_OVIEN_Msk
* - \ref ECAP_CTL0_CMPIEN_Msk
* @return None
* @details This macro will enable the input channel_n interrupt.
*/
void ECAP_EnableINT(ECAP_T* ecap, uint32_t u32Mask)
{
/* Enable input channel interrupt */
ecap->CTL0 |= (u32Mask);
/* Enable NVIC ECAP IRQ */
if(ecap == (ECAP_T*)ECAP0) {
NVIC_EnableIRQ((IRQn_Type)ECAP0_IRQn);
} else {
NVIC_EnableIRQ((IRQn_Type)ECAP1_IRQn);
}
}
/**
* @brief This macro is used to disable input channel interrupt
* @param[in] ecap Specify ECAP port
* @param[in] u32Mask The input channel number
* - \ref ECAP_CTL0_CAPIEN0_Msk
* - \ref ECAP_CTL0_CAPIEN1_Msk
* - \ref ECAP_CTL0_CAPIEN2_Msk
* - \ref ECAP_CTL0_OVIEN_Msk
* - \ref ECAP_CTL0_CMPIEN_Msk
* @return None
* @details This macro will disable the input channel_n interrupt.
*/
void ECAP_DisableINT(ECAP_T* ecap, uint32_t u32Mask)
{
/* Disable input channel interrupt */
ecap->CTL0 &= ~(u32Mask);
/* Disable NVIC ECAP IRQ */
if(ecap == (ECAP_T*)ECAP0) {
NVIC_DisableIRQ((IRQn_Type)ECAP0_IRQn);
} else {
NVIC_DisableIRQ((IRQn_Type)ECAP1_IRQn);
}
}
/*@}*/ /* end of group ECAP_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group ECAP_Driver */
/*@}*/ /* end of group Standard_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,457 @@
/**************************************************************************//**
* @file ecap.h
* @version V3.00
* @brief EnHanced Input Capture Timer(ECAP) driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __ECAP_H__
#define __ECAP_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup ECAP_Driver ECAP Driver
@{
*/
/** @addtogroup ECAP_EXPORTED_CONSTANTS ECAP Exported Constants
@{
*/
#define ECAP_IC0 (0UL) /*!< ECAP IC0 Unit \hideinitializer */
#define ECAP_IC1 (1UL) /*!< ECAP IC1 Unit \hideinitializer */
#define ECAP_IC2 (2UL) /*!< ECAP IC2 Unit \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* ECAP CTL0 constant definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define ECAP_NOISE_FILTER_CLKDIV_1 (0UL<<ECAP_CTL0_NFCLKSEL_Pos) /*!< Noise filter clock divide by 1 \hideinitializer */
#define ECAP_NOISE_FILTER_CLKDIV_2 (1UL<<ECAP_CTL0_NFCLKSEL_Pos) /*!< Noise filter clock divide by 2 \hideinitializer */
#define ECAP_NOISE_FILTER_CLKDIV_4 (2UL<<ECAP_CTL0_NFCLKSEL_Pos) /*!< Noise filter clock divide by 4 \hideinitializer */
#define ECAP_NOISE_FILTER_CLKDIV_16 (3UL<<ECAP_CTL0_NFCLKSEL_Pos) /*!< Noise filter clock divide by 16 \hideinitializer */
#define ECAP_NOISE_FILTER_CLKDIV_32 (4UL<<ECAP_CTL0_NFCLKSEL_Pos) /*!< Noise filter clock divide by 32 \hideinitializer */
#define ECAP_NOISE_FILTER_CLKDIV_64 (5UL<<ECAP_CTL0_NFCLKSEL_Pos) /*!< Noise filter clock divide by 64 \hideinitializer */
#define ECAP_CAP_INPUT_SRC_FROM_IC (0UL) /*!< CAP input source from IC \hideinitializer */
#define ECAP_CAP_INPUT_SRC_FROM_CH (2UL) /*!< CAP input source from CH of QEI \hideinitializer */
#define ECAP_DISABLE_COMPARE (0UL<<ECAP_CTL0_CMPEN_Pos) /*!< Input capture compare and reload function disable \hideinitializer */
#define ECAP_COMPARE_FUNCTION (1UL<<ECAP_CTL0_CMPEN_Pos) /*!< Input capture compare function \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* ECAP CTL1 constant definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define ECAP_RISING_EDGE (0UL<<ECAP_CTL1_EDGESEL0_Pos) /*!< ECAP capture rising edge selection \hideinitializer */
#define ECAP_FALLING_EDGE (1UL<<ECAP_CTL1_EDGESEL0_Pos) /*!< ECAP capture falling edge selection \hideinitializer */
#define ECAP_RISING_FALLING_EDGE (2UL<<ECAP_CTL1_EDGESEL0_Pos) /*!< ECAP capture either rising or falling edge selection \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLKDIV_1 (0UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer clock divide by 1 \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLKDIV_4 (1UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer clock divide by 4 \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLKDIV_16 (2UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer clock divide by 16 \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLKDIV_32 (3UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer clock divide by 32 \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLKDIV_64 (4UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer clock divide by 64 \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLKDIV_96 (5UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer clock divide by 96 \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLKDIV_112 (6UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer clock divide by 112 \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLKDIV_128 (7UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer clock divide by 128 \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLK_SRC_CAP_CLK (0UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer/clock source from CAP_CLK \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLK_SRC_CAP0 (1UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer/clock source from CAP0 \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLK_SRC_CAP1 (2UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer/clock source from CAP1 \hideinitializer */
#define ECAP_CAPTURE_TIMER_CLK_SRC_CAP2 (3UL<<ECAP_CTL1_CLKSEL_Pos) /*!< ECAP capture timer/clock source from CAP2 \hideinitializer */
/*@}*/ /* end of group ECAP_EXPORTED_CONSTANTS */
/** @addtogroup ECAP_EXPORTED_FUNCTIONS ECAP Exported Functions
@{
*/
/**
* @brief This macro is used to select noise filter clock pre-divide number
* @param[in] ecap Specify ECAP port
* @param[in] u32ClkSel The noise filter clock divide number
* - \ref ECAP_NOISE_FILTER_CLKDIV_1
* - \ref ECAP_NOISE_FILTER_CLKDIV_2
* - \ref ECAP_NOISE_FILTER_CLKDIV_4
* - \ref ECAP_NOISE_FILTER_CLKDIV_16
* - \ref ECAP_NOISE_FILTER_CLKDIV_32
* - \ref ECAP_NOISE_FILTER_CLKDIV_64
* @return None
* @details This macro will set the sampling frequency of the noise filter cock.
* \hideinitializer
*/
#define ECAP_SET_NOISE_FILTER_CLKDIV(ecap, u32ClkSel) ((ecap)->CTL0 = ((ecap)->CTL0 & ~ECAP_CTL0_NFCLKSEL_Msk)|(u32ClkSel))
/**
* @brief This macro is used to disable noise filter
* @param[in] ecap Specify ECAP port
* @return None
* @details This macro will disable the noise filter of input capture.
* \hideinitializer
*/
#define ECAP_NOISE_FILTER_DISABLE(ecap) ((ecap)->CTL0 |= ECAP_CTL0_CAPNFDIS_Msk)
/**
* @brief This macro is used to enable noise filter
* @param[in] ecap Specify ECAP port
* @param[in] u32ClkSel Select noise filter clock divide number
* - \ref ECAP_NOISE_FILTER_CLKDIV_1
* - \ref ECAP_NOISE_FILTER_CLKDIV_2
* - \ref ECAP_NOISE_FILTER_CLKDIV_4
* - \ref ECAP_NOISE_FILTER_CLKDIV_16
* - \ref ECAP_NOISE_FILTER_CLKDIV_32
* - \ref ECAP_NOISE_FILTER_CLKDIV_64
* @return None
* @details This macro will enable the noise filter of input capture and set noise filter clock divide.
* \hideinitializer
*/
#define ECAP_NOISE_FILTER_ENABLE(ecap, u32ClkSel) ((ecap)->CTL0 = ((ecap)->CTL0 & ~(ECAP_CTL0_CAPNFDIS_Msk|ECAP_CTL0_NFCLKSEL_Msk))|(u32ClkSel));
/**
* @brief This macro is used to enable input channel unit
* @param[in] ecap Specify ECAP port
* @param[in] u32Mask The input channel mask
* - \ref ECAP_CTL0_IC0EN_Msk
* - \ref ECAP_CTL0_IC1EN_Msk
* - \ref ECAP_CTL0_IC2EN_Msk
* @return None
* @details This macro will enable the input channel_n to input capture.
* \hideinitializer
*/
#define ECAP_ENABLE_INPUT_CHANNEL(ecap, u32Mask) ((ecap)->CTL0 |= (u32Mask))
/**
* @brief This macro is used to disable input channel unit
* @param[in] ecap Specify ECAP port
* @param[in] u32Mask The input channel mask
* - \ref ECAP_CTL0_IC0EN_Msk
* - \ref ECAP_CTL0_IC1EN_Msk
* - \ref ECAP_CTL0_IC2EN_Msk
* @return None
* @details This macro will disable the input channel_n to input capture.
* \hideinitializer
*/
#define ECAP_DISABLE_INPUT_CHANNEL(ecap, u32Mask) ((ecap)->CTL0 &= ~(u32Mask))
/**
* @brief This macro is used to select input channel source
* @param[in] ecap Specify ECAP port
* @param[in] u32Index The input channel number
* - \ref ECAP_IC0
* - \ref ECAP_IC1
* - \ref ECAP_IC2
* @param[in] u32Src The input source
* - \ref ECAP_CAP_INPUT_SRC_FROM_IC
* - \ref ECAP_CAP_INPUT_SRC_FROM_CH
* @return None
* @details This macro will select the input source from ICx, CPOx, CHx, ADCMPO or OPDO.
* \hideinitializer
*/
#define ECAP_SEL_INPUT_SRC(ecap, u32Index, u32Src) ((ecap)->CTL0 = ((ecap)->CTL0 & ~(ECAP_CTL0_CAPSEL0_Msk<<((u32Index)<<1)))|(((u32Src)<<ECAP_CTL0_CAPSEL0_Pos)<<((u32Index)<<1)))
/**
* @brief This macro is used to enable input channel interrupt
* @param[in] ecap Specify ECAP port
* @param[in] u32Mask The input channel mask
* - \ref ECAP_CTL0_CAPIEN0_Msk
* - \ref ECAP_CTL0_CAPIEN1_Msk
* - \ref ECAP_CTL0_CAPIEN2_Msk
* @return None
* @details This macro will enable the input channel_n interrupt.
* \hideinitializer
*/
#define ECAP_ENABLE_INT(ecap, u32Mask) ((ecap)->CTL0 |= (u32Mask))
/**
* @brief This macro is used to disable input channel interrupt
* @param[in] ecap Specify ECAP port
* @param[in] u32Mask The input channel mask
* - \ref ECAP_IC0
* - \ref ECAP_IC1
* - \ref ECAP_IC2
* @return None
* @details This macro will disable the input channel_n interrupt.
* \hideinitializer
*/
#define ECAP_DISABLE_INT(ecap, u32Mask) ((ecap)->CTL0 &= ~(u32Mask))
/**
* @brief This macro is used to enable input channel overflow interrupt
* @param[in] ecap Specify ECAP port
* @return None
* @details This macro will enable the input channel overflow interrupt.
* \hideinitializer
*/
#define ECAP_ENABLE_OVF_INT(ecap) ((ecap)->CTL0 |= ECAP_CTL0_OVIEN_Msk)
/**
* @brief This macro is used to disable input channel overflow interrupt
* @param[in] ecap Specify ECAP port
* @return None
* @details This macro will disable the input channel overflow interrupt.
* \hideinitializer
*/
#define ECAP_DISABLE_OVF_INT(ecap) ((ecap)->CTL0 &= ~ECAP_CTL0_OVIEN_Msk)
/**
* @brief This macro is used to enable input channel compare-match interrupt
* @param[in] ecap Specify ECAP port
* @return None
* @details This macro will enable the input channel compare-match interrupt.
* \hideinitializer
*/
#define ECAP_ENABLE_CMP_MATCH_INT(ecap) ((ecap)->CTL0 |= ECAP_CTL0_CMPIEN_Msk)
/**
* @brief This macro is used to disable input channel compare-match interrupt
* @param[in] ecap Specify ECAP port
* @return None
* @details This macro will disable the input channel compare-match interrupt.
* \hideinitializer
*/
#define ECAP_DISABLE_CMP_MATCH_INT(ecap) ((ecap)->CTL0 &= ~ECAP_CTL0_CMPIEN_Msk)
/**
* @brief This macro is used to start capture counter
* @param[in] ecap Specify ECAP port
* @return None
* @details This macro will start capture counter up-counting.
* \hideinitializer
*/
#define ECAP_CNT_START(ecap) ((ecap)->CTL0 |= ECAP_CTL0_CNTEN_Msk)
/**
* @brief This macro is used to stop capture counter
* @param[in] ecap Specify ECAP port
* @return None
* @details This macro will stop capture counter up-counting.
* \hideinitializer
*/
#define ECAP_CNT_STOP(ecap) ((ecap)->CTL0 &= ~ECAP_CTL0_CNTEN_Msk)
/**
* @brief This macro is used to set event to clear capture counter
* @param[in] ecap Specify ECAP port
* @param[in] u32Event The input channel number
* - \ref ECAP_CTL0_CMPCLREN_Msk
* - \ref ECAP_CTL1_CAP0RLDEN_Msk
* - \ref ECAP_CTL1_CAP1RLDEN_Msk
* - \ref ECAP_CTL1_CAP2RLDEN_Msk
* - \ref ECAP_CTL1_OVRLDEN_Msk
* @return None
* @details This macro will enable and select compare or capture event that can clear capture counter.
* \hideinitializer
*/
#define ECAP_SET_CNT_CLEAR_EVENT(ecap, u32Event) do{ \
if((u32Event) & ECAP_CTL0_CMPCLREN_Msk) \
(ecap)->CTL0 |= ECAP_CTL0_CMPCLREN_Msk; \
else \
(ecap)->CTL0 &= ~ECAP_CTL0_CMPCLREN_Msk; \
(ecap)->CTL1 = ((ecap)->CTL1 &~0xF00) | ((u32Event) & 0xF00); \
}while(0);
/**
* @brief This macro is used to enable compare function
* @param[in] ecap Specify ECAP port
* @return None
* @details This macro will enable the compare function.
* \hideinitializer
*/
#define ECAP_ENABLE_CMP(ecap) ((ecap)->CTL0 |= ECAP_CTL0_CMPEN_Msk)
/**
* @brief This macro is used to disable compare function
* @param[in] ecap Specify ECAP port
* @return None
* @details This macro will disable the compare function.
* \hideinitializer
*/
#define ECAP_DISABLE_CMP(ecap) ((ecap)->CTL0 &= ~ECAP_CTL0_CMPEN_Msk)
/**
* @brief This macro is used to enable input capture function.
* @param[in] ecap Specify ECAP port
* @return None
* @details This macro will enable input capture timer/counter.
* \hideinitializer
*/
#define ECAP_ENABLE_CNT(ecap) ((ecap)->CTL0 |= ECAP_CTL0_CAPEN_Msk)
/**
* @brief This macro is used to disable input capture function.
* @param[in] ecap Specify ECAP port
* @return None
* @details This macro will disable input capture timer/counter.
* \hideinitializer
*/
#define ECAP_DISABLE_CNT(ecap) ((ecap)->CTL0 &= ~ECAP_CTL0_CAPEN_Msk)
/**
* @brief This macro is used to select input channel edge detection
* @param[in] ecap Specify ECAP port
* @param[in] u32Index The input channel number
* - \ref ECAP_IC0
* - \ref ECAP_IC1
* - \ref ECAP_IC2
* @param[in] u32Edge The input source
* - \ref ECAP_RISING_EDGE
* - \ref ECAP_FALLING_EDGE
* - \ref ECAP_RISING_FALLING_EDGE
* @return None
* @details This macro will select input capture can detect falling edge, rising edge or either rising or falling edge change.
* \hideinitializer
*/
#define ECAP_SEL_CAPTURE_EDGE(ecap, u32Index, u32Edge) ((ecap)->CTL1 = ((ecap)->CTL1 & ~(ECAP_CTL1_EDGESEL0_Msk<<((u32Index)<<1)))|((u32Edge)<<((u32Index)<<1)))
/**
* @brief This macro is used to select ECAP counter reload trigger source
* @param[in] ecap Specify ECAP port
* @param[in] u32TrigSrc The input source
* - \ref ECAP_CTL1_CAP0RLDEN_Msk
* - \ref ECAP_CTL1_CAP1RLDEN_Msk
* - \ref ECAP_CTL1_CAP2RLDEN_Msk
* - \ref ECAP_CTL1_OVRLDEN_Msk
* @return None
* @details This macro will select capture counter reload trigger source.
* \hideinitializer
*/
#define ECAP_SEL_RELOAD_TRIG_SRC(ecap, u32TrigSrc) ((ecap)->CTL1 = ((ecap)->CTL1 & ~0xF00)|(u32TrigSrc))
/**
* @brief This macro is used to select capture timer clock divide.
* @param[in] ecap Specify ECAP port
* @param[in] u32Clkdiv The input source
* - \ref ECAP_CAPTURE_TIMER_CLKDIV_1
* - \ref ECAP_CAPTURE_TIMER_CLKDIV_4
* - \ref ECAP_CAPTURE_TIMER_CLKDIV_16
* - \ref ECAP_CAPTURE_TIMER_CLKDIV_32
* - \ref ECAP_CAPTURE_TIMER_CLKDIV_64
* - \ref ECAP_CAPTURE_TIMER_CLKDIV_96
* - \ref ECAP_CAPTURE_TIMER_CLKDIV_112
* - \ref ECAP_CAPTURE_TIMER_CLKDIV_128
* @return None
* @details This macro will select capture timer clock has a pre-divider with eight divided option.
* \hideinitializer
*/
#define ECAP_SEL_TIMER_CLK_DIV(ecap, u32Clkdiv) ((ecap)->CTL1 = ((ecap)->CTL1 & ~ECAP_CTL1_CLKSEL_Msk)|(u32Clkdiv))
/**
* @brief This macro is used to select capture timer/counter clock source
* @param[in] ecap Specify ECAP port
* @param[in] u32ClkSrc The input source
* - \ref ECAP_CAPTURE_TIMER_CLK_SRC_CAP_CLK
* - \ref ECAP_CAPTURE_TIMER_CLK_SRC_CAP0
* - \ref ECAP_CAPTURE_TIMER_CLK_SRC_CAP1
* - \ref ECAP_CAPTURE_TIMER_CLK_SRC_CAP2
* @return None
* @details This macro will select capture timer/clock clock source.
* \hideinitializer
*/
#define ECAP_SEL_TIMER_CLK_SRC(ecap, u32ClkSrc) ((ecap)->CTL1 = ((ecap)->CTL1 & ~ECAP_CTL1_CLKSEL_Msk)|(u32ClkSrc))
/**
* @brief This macro is used to read input capture status
* @param[in] ecap Specify ECAP port
* @return Input capture status flags
* @details This macro will get the input capture interrupt status.
* \hideinitializer
*/
#define ECAP_GET_INT_STATUS(ecap) ((ecap)->STATUS)
/**
* @brief This macro is used to get input channel interrupt flag
* @param[in] ecap Specify ECAP port
* @param[in] u32Mask The input channel mask
* - \ref ECAP_STATUS_CAPTF0_Msk
* - \ref ECAP_STATUS_CAPTF1_Msk
* - \ref ECAP_STATUS_CAPTF2_Msk
* - \ref ECAP_STATUS_CAPOVF_Msk
* - \ref ECAP_STATUS_CAPCMPF_Msk
* @return None
* @details This macro will write 1 to get the input channel_n interrupt flag.
* \hideinitializer
*/
#define ECAP_GET_CAPTURE_FLAG(ecap, u32Mask) (((ecap)->STATUS & (u32Mask))?1:0)
/**
* @brief This macro is used to clear input channel interrupt flag
* @param[in] ecap Specify ECAP port
* @param[in] u32Mask The input channel mask
* - \ref ECAP_STATUS_CAPTF0_Msk
* - \ref ECAP_STATUS_CAPTF1_Msk
* - \ref ECAP_STATUS_CAPTF2_Msk
* - \ref ECAP_STATUS_CAPOVF_Msk
* - \ref ECAP_STATUS_CAPCMPF_Msk
* @return None
* @details This macro will write 1 to clear the input channel_n interrupt flag.
* \hideinitializer
*/
#define ECAP_CLR_CAPTURE_FLAG(ecap, u32Mask) ((ecap)->STATUS = (u32Mask))
/**
* @brief This macro is used to set input capture counter value
* @param[in] ecap Specify ECAP port
* @param[in] u32Val Counter value
* @return None
* @details This macro will set a counter value of input capture.
* \hideinitializer
*/
#define ECAP_SET_CNT_VALUE(ecap, u32Val) ((ecap)->CNT = (u32Val))
/**
* @brief This macro is used to get input capture counter value
* @param[in] ecap Specify ECAP port
* @return Capture counter value
* @details This macro will get a counter value of input capture.
* \hideinitializer
*/
#define ECAP_GET_CNT_VALUE(ecap) ((ecap)->CNT)
/**
* @brief This macro is used to get input capture counter hold value
* @param[in] ecap Specify ECAP port
* @param[in] u32Index The input channel number
* - \ref ECAP_IC0
* - \ref ECAP_IC1
* - \ref ECAP_IC2
* @return Capture counter hold value
* @details This macro will get a hold value of input capture channel_n.
* \hideinitializer
*/
#define ECAP_GET_CNT_HOLD_VALUE(ecap, u32Index) (*(__IO uint32_t *) (&((ecap)->HLD0) + (u32Index)))
/**
* @brief This macro is used to set input capture counter compare value
* @param[in] ecap Specify ECAP port
* @param[in] u32Val Input capture compare value
* @return None
* @details This macro will set a compare value of input capture counter.
* \hideinitializer
*/
#define ECAP_SET_CNT_CMP(ecap, u32Val) ((ecap)->CNTCMP = (u32Val))
void ECAP_Open(ECAP_T* ecap, uint32_t u32FuncMask);
void ECAP_Close(ECAP_T* ecap);
void ECAP_EnableINT(ECAP_T* ecap, uint32_t u32Mask);
void ECAP_DisableINT(ECAP_T* ecap, uint32_t u32Mask);
/*@}*/ /* end of group ECAP_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group ECAP_Driver */
/*@}*/ /* end of group Standard_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __ECAP_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,880 @@
/**************************************************************************//**
* @file emac.c
* @version V1.00
* @brief M480 EMAC driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_EMAC_Driver EMAC Driver
@{
*/
/* Below are structure, definitions, static variables used locally by EMAC driver and does not want to parse by doxygen unless HIDDEN_SYMBOLS is defined */
/** @cond HIDDEN_SYMBOLS */
/** @addtogroup M480_EMAC_EXPORTED_CONSTANTS EMAC Exported Constants
@{
*/
/* PHY Register Description */
#define PHY_CNTL_REG 0x00UL /*!< PHY control register address */
#define PHY_STATUS_REG 0x01UL /*!< PHY status register address */
#define PHY_ID1_REG 0x02UL /*!< PHY ID1 register */
#define PHY_ID2_REG 0x03UL /*!< PHY ID2 register */
#define PHY_ANA_REG 0x04UL /*!< PHY auto-negotiation advertisement register */
#define PHY_ANLPA_REG 0x05UL /*!< PHY auto-negotiation link partner availability register */
#define PHY_ANE_REG 0x06UL /*!< PHY auto-negotiation expansion register */
/* PHY Control Register */
#define PHY_CNTL_RESET_PHY (1UL << 15UL)
#define PHY_CNTL_DR_100MB (1UL << 13UL)
#define PHY_CNTL_ENABLE_AN (1UL << 12UL)
#define PHY_CNTL_POWER_DOWN (1UL << 11UL)
#define PHY_CNTL_RESTART_AN (1UL << 9UL)
#define PHY_CNTL_FULLDUPLEX (1UL << 8UL)
/* PHY Status Register */
#define PHY_STATUS_AN_COMPLETE (1UL << 5UL)
#define PHY_STATUS_LINK_VALID (1UL << 2UL)
/* PHY Auto-negotiation Advertisement Register */
#define PHY_ANA_DR100_TX_FULL (1UL << 8UL)
#define PHY_ANA_DR100_TX_HALF (1UL << 7UL)
#define PHY_ANA_DR10_TX_FULL (1UL << 6UL)
#define PHY_ANA_DR10_TX_HALF (1UL << 5UL)
#define PHY_ANA_IEEE_802_3_CSMA_CD (1UL << 0UL)
/* PHY Auto-negotiation Link Partner Advertisement Register */
#define PHY_ANLPA_DR100_TX_FULL (1UL << 8UL)
#define PHY_ANLPA_DR100_TX_HALF (1UL << 7UL)
#define PHY_ANLPA_DR10_TX_FULL (1UL << 6UL)
#define PHY_ANLPA_DR10_TX_HALF (1UL << 5UL)
/* EMAC Tx/Rx descriptor's owner bit */
#define EMAC_DESC_OWN_EMAC 0x80000000UL /*!< Set owner to EMAC */
#define EMAC_DESC_OWN_CPU 0x00000000UL /*!< Set owner to CPU */
/* Rx Frame Descriptor Status */
#define EMAC_RXFD_RTSAS 0x0080UL /*!< Time Stamp Available */
#define EMAC_RXFD_RP 0x0040UL /*!< Runt Packet */
#define EMAC_RXFD_ALIE 0x0020UL /*!< Alignment Error */
#define EMAC_RXFD_RXGD 0x0010UL /*!< Receiving Good packet received */
#define EMAC_RXFD_PTLE 0x0008UL /*!< Packet Too Long Error */
#define EMAC_RXFD_CRCE 0x0002UL /*!< CRC Error */
#define EMAC_RXFD_RXINTR 0x0001UL /*!< Interrupt on receive */
/* Tx Frame Descriptor's Control bits */
#define EMAC_TXFD_TTSEN 0x08UL /*!< Tx time stamp enable */
#define EMAC_TXFD_INTEN 0x04UL /*!< Tx interrupt enable */
#define EMAC_TXFD_CRCAPP 0x02UL /*!< Append CRC */
#define EMAC_TXFD_PADEN 0x01UL /*!< Padding mode enable */
/* Tx Frame Descriptor Status */
#define EMAC_TXFD_TXINTR 0x0001UL /*!< Interrupt on Transmit */
#define EMAC_TXFD_DEF 0x0002UL /*!< Transmit deferred */
#define EMAC_TXFD_TXCP 0x0008UL /*!< Transmission Completion */
#define EMAC_TXFD_EXDEF 0x0010UL /*!< Exceed Deferral */
#define EMAC_TXFD_NCS 0x0020UL /*!< No Carrier Sense Error */
#define EMAC_TXFD_TXABT 0x0040UL /*!< Transmission Abort */
#define EMAC_TXFD_LC 0x0080UL /*!< Late Collision */
#define EMAC_TXFD_TXHA 0x0100UL /*!< Transmission halted */
#define EMAC_TXFD_PAU 0x0200UL /*!< Paused */
#define EMAC_TXFD_SQE 0x0400UL /*!< SQE error */
#define EMAC_TXFD_TTSAS 0x0800UL /*!< Time Stamp available */
/*@}*/ /* end of group M480_EMAC_EXPORTED_CONSTANTS */
/** @addtogroup M480_EMAC_EXPORTED_TYPEDEF EMAC Exported Type Defines
@{
*/
/** Tx/Rx buffer descriptor structure */
typedef struct {
uint32_t u32Status1; /*!< Status word 1 */
uint32_t u32Data; /*!< Pointer to data buffer */
uint32_t u32Status2; /*!< Status word 2 */
uint32_t u32Next; /*!< Pointer to next descriptor */
uint32_t u32Backup1; /*!< For backup descriptor fields over written by time stamp */
uint32_t u32Backup2; /*!< For backup descriptor fields over written by time stamp */
} EMAC_DESCRIPTOR_T;
/** Tx/Rx buffer structure */
typedef struct {
uint8_t au8Buf[1520];
} EMAC_FRAME_T;
/*@}*/ /* end of group M480_EMAC_EXPORTED_TYPEDEF */
/* local variables */
static volatile EMAC_DESCRIPTOR_T rx_desc[EMAC_RX_DESC_SIZE];
static volatile EMAC_FRAME_T rx_buf[EMAC_RX_DESC_SIZE];
static volatile EMAC_DESCRIPTOR_T tx_desc[EMAC_TX_DESC_SIZE];
static volatile EMAC_FRAME_T tx_buf[EMAC_TX_DESC_SIZE];
static uint32_t u32CurrentTxDesc, u32NextTxDesc, u32CurrentRxDesc;
static uint32_t s_u32EnableTs = 0UL;
static void EMAC_MdioWrite(uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data);
static uint32_t EMAC_MdioRead(uint32_t u32Reg, uint32_t u32Addr);
static void EMAC_PhyInit(void);
static void EMAC_TxDescInit(void);
static void EMAC_RxDescInit(void);
static uint32_t EMAC_Subsec2Nsec(uint32_t subsec);
static uint32_t EMAC_Nsec2Subsec(uint32_t nsec);
/** @addtogroup M480_EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions
@{
*/
/**
* @brief Trigger EMAC Rx function
* @param None
* @return None
*/
#define EMAC_TRIGGER_RX() do{EMAC->RXST = 0UL;}while(0)
/**
* @brief Trigger EMAC Tx function
* @param None
* @return None
*/
#define EMAC_TRIGGER_TX() do{EMAC->TXST = 0UL;}while(0)
/**
* @brief Write PHY register
* @param[in] u32Reg PHY register number
* @param[in] u32Addr PHY address, this address is board dependent
* @param[in] u32Data data to write to PHY register
* @return None
*/
static void EMAC_MdioWrite(uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data)
{
/* Set data register */
EMAC->MIIMDAT = u32Data ;
/* Set PHY address, PHY register address, busy bit and write bit */
EMAC->MIIMCTL = u32Reg | (u32Addr << 8) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
/* Wait write complete by polling busy bit. */
while(EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) {
;
}
}
/**
* @brief Read PHY register
* @param[in] u32Reg PHY register number
* @param[in] u32Addr PHY address, this address is board dependent
* @return Value read from PHY register
*/
static uint32_t EMAC_MdioRead(uint32_t u32Reg, uint32_t u32Addr)
{
/* Set PHY address, PHY register address, busy bit */
EMAC->MIIMCTL = u32Reg | (u32Addr << EMAC_MIIMCTL_PHYADDR_Pos) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
/* Wait read complete by polling busy bit */
while(EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) {
;
}
/* Get return data */
return EMAC->MIIMDAT;
}
/**
* @brief Initialize PHY chip, check for the auto-negotiation result.
* @param None
* @return None
*/
static void EMAC_PhyInit(void)
{
uint32_t reg;
uint32_t i = 0UL;
/* Reset Phy Chip */
EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, PHY_CNTL_RESET_PHY);
/* Wait until reset complete */
while (1) {
reg = EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) ;
if ((reg & PHY_CNTL_RESET_PHY)==0UL) {
break;
}
}
while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID)) {
if(i++ > 80000UL) { /* Cable not connected */
EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
break;
}
}
if(i <= 80000UL) {
/* Configure auto negotiation capability */
EMAC_MdioWrite(PHY_ANA_REG, EMAC_PHY_ADDR, PHY_ANA_DR100_TX_FULL |
PHY_ANA_DR100_TX_HALF |
PHY_ANA_DR10_TX_FULL |
PHY_ANA_DR10_TX_HALF |
PHY_ANA_IEEE_802_3_CSMA_CD);
/* Restart auto negotiation */
EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) | PHY_CNTL_RESTART_AN);
/* Wait for auto-negotiation complete */
while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_AN_COMPLETE)) {
;
}
/* Check link valid again. Some PHYs needs to check result after link valid bit set */
while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID)) {
;
}
/* Check link partner capability */
reg = EMAC_MdioRead(PHY_ANLPA_REG, EMAC_PHY_ADDR) ;
if (reg & PHY_ANLPA_DR100_TX_FULL) {
EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
} else if (reg & PHY_ANLPA_DR100_TX_HALF) {
EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
} else if (reg & PHY_ANLPA_DR10_TX_FULL) {
EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
} else {
EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
}
}
}
/**
* @brief Initial EMAC Tx descriptors and get Tx descriptor base address
* @param None
* @return None
*/
static void EMAC_TxDescInit(void)
{
uint32_t i;
/* Get Frame descriptor's base address. */
EMAC->TXDSA = (uint32_t)&tx_desc[0];
u32NextTxDesc = u32CurrentTxDesc = (uint32_t)&tx_desc[0];
for(i = 0UL; i < EMAC_TX_DESC_SIZE; i++) {
if(s_u32EnableTs) {
tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN;
} else {
tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN | EMAC_TXFD_TTSEN;
}
tx_desc[i].u32Data = (uint32_t)((uint32_t)&tx_buf[i]);
tx_desc[i].u32Backup1 = tx_desc[i].u32Data;
tx_desc[i].u32Status2 = 0UL;
tx_desc[i].u32Next = (uint32_t)&tx_desc[(i + 1UL) % EMAC_TX_DESC_SIZE];
tx_desc[i].u32Backup2 = tx_desc[i].u32Next;
}
}
/**
* @brief Initial EMAC Rx descriptors and get Rx descriptor base address
* @param None
* @return None
*/
static void EMAC_RxDescInit(void)
{
uint32_t i;
/* Get Frame descriptor's base address. */
EMAC->RXDSA = (uint32_t)&rx_desc[0];
u32CurrentRxDesc = (uint32_t)&rx_desc[0];
for(i = 0UL; i < EMAC_RX_DESC_SIZE; i++) {
rx_desc[i].u32Status1 = EMAC_DESC_OWN_EMAC;
rx_desc[i].u32Data = (uint32_t)((uint32_t)&rx_buf[i]);
rx_desc[i].u32Backup1 = rx_desc[i].u32Data;
rx_desc[i].u32Status2 = 0UL;
rx_desc[i].u32Next = (uint32_t)&rx_desc[(i + 1UL) % EMAC_RX_DESC_SIZE];
rx_desc[i].u32Backup2 = rx_desc[i].u32Next;
}
}
/**
* @brief Convert subsecond value to nano second
* @param[in] subsec Subsecond value to be convert
* @return Nano second
*/
static uint32_t EMAC_Subsec2Nsec(uint32_t subsec)
{
/* 2^31 subsec == 10^9 ns */
uint64_t i;
i = 1000000000ull * (uint64_t)subsec;
i >>= 31;
return((uint32_t)i);
}
/**
* @brief Convert nano second to subsecond value
* @param[in] nsec Nano second to be convert
* @return Subsecond
*/
static uint32_t EMAC_Nsec2Subsec(uint32_t nsec)
{
/* 10^9 ns = 2^31 subsec */
uint64_t i;
i = (1ull << 31) * nsec;
i /= 1000000000ull;
return((uint32_t)i);
}
/*@}*/ /* end of group M480_EMAC_EXPORTED_FUNCTIONS */
/** @endcond HIDDEN_SYMBOLS */
/** @addtogroup M480_EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions
@{
*/
/**
* @brief Initialize EMAC interface, including descriptors, MAC address, and PHY.
* @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address
* @return None
* @note This API sets EMAC to work in RMII mode, but could configure to MII mode later with \ref EMAC_ENABLE_MII_INTF macro
* @note This API configures EMAC to receive all broadcast and multicast packets, but could configure to other settings with
* \ref EMAC_ENABLE_RECV_BCASTPKT, \ref EMAC_DISABLE_RECV_BCASTPKT, \ref EMAC_ENABLE_RECV_MCASTPKT, and \ref EMAC_DISABLE_RECV_MCASTPKT
* @note Receive(RX) and transmit(TX) are not enabled yet, application must call \ref EMAC_ENABLE_RX and \ref EMAC_ENABLE_TX to
* enable receive and transmit function.
*/
void EMAC_Open(uint8_t *pu8MacAddr)
{
/* Enable transmit and receive descriptor */
EMAC_TxDescInit();
EMAC_RxDescInit();
/* Set the CAM Control register and the MAC address value */
EMAC_SetMacAddr(pu8MacAddr);
/* Configure the MAC interrupt enable register. */
EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
EMAC_INTEN_TXIEN_Msk |
EMAC_INTEN_RXGDIEN_Msk |
EMAC_INTEN_TXCPIEN_Msk |
EMAC_INTEN_RXBEIEN_Msk |
EMAC_INTEN_TXBEIEN_Msk |
EMAC_INTEN_RDUIEN_Msk |
EMAC_INTEN_TSALMIEN_Msk |
EMAC_INTEN_WOLIEN_Msk;
/* Configure the MAC control register. */
EMAC->CTL = EMAC_CTL_STRIPCRC_Msk |
EMAC_CTL_RMIIEN_Msk;
/* Accept packets for us and all broadcast and multicast packets */
EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
EMAC_CAMCTL_AMP_Msk |
EMAC_CAMCTL_ABP_Msk;
EMAC_PhyInit();
}
/**
* @brief This function stop all receive and transmit activity and disable MAC interface
* @param None
* @return None
*/
void EMAC_Close(void)
{
EMAC->CTL |= EMAC_CTL_RST_Msk;
while(EMAC->CTL & EMAC_CTL_RST_Msk) {}
}
/**
* @brief Set the device MAC address
* @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address
* @return None
*/
void EMAC_SetMacAddr(uint8_t *pu8MacAddr)
{
EMAC_EnableCamEntry(0UL, pu8MacAddr);
}
/**
* @brief Fill a CAM entry for MAC address comparison.
* @param[in] u32Entry MAC entry to fill. Entry 0 is used to store device MAC address, do not overwrite the setting in it.
* @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address
* @return None
*/
void EMAC_EnableCamEntry(uint32_t u32Entry, uint8_t pu8MacAddr[])
{
uint32_t u32Lsw, u32Msw;
uint32_t reg;
u32Lsw = (uint32_t)(((uint32_t)pu8MacAddr[4] << 24) |
((uint32_t)pu8MacAddr[5] << 16));
u32Msw = (uint32_t)(((uint32_t)pu8MacAddr[0] << 24)|
((uint32_t)pu8MacAddr[1] << 16)|
((uint32_t)pu8MacAddr[2] << 8)|
(uint32_t)pu8MacAddr[3]);
reg = (uint32_t)&EMAC->CAM0M + u32Entry * 2UL * 4UL;
*(uint32_t volatile *)reg = u32Msw;
reg = (uint32_t)&EMAC->CAM0L + u32Entry * 2UL * 4UL;
*(uint32_t volatile *)reg = u32Lsw;
EMAC->CAMEN |= (1UL << u32Entry);
}
/**
* @brief Disable a specified CAM entry
* @param[in] u32Entry CAM entry to be disabled
* @return None
*/
void EMAC_DisableCamEntry(uint32_t u32Entry)
{
EMAC->CAMEN &= ~(1UL << u32Entry);
}
/**
* @brief Receive an Ethernet packet
* @param[in] pu8Data Pointer to a buffer to store received packet (4 byte CRC removed)
* @param[in] pu32Size Received packet size (without 4 byte CRC).
* @return Packet receive success or not
* @retval 0 No packet available for receive
* @retval 1 A packet is received
* @note Return 0 doesn't guarantee the packet will be sent and received successfully.
*/
uint32_t EMAC_RecvPkt(uint8_t *pu8Data, uint32_t *pu32Size)
{
EMAC_DESCRIPTOR_T *desc;
uint32_t status, reg;
uint32_t u32Count = 0UL;
/* Clear Rx interrupt flags */
reg = EMAC->INTSTS;
EMAC->INTSTS = reg & 0xFFFFUL; /* Clear all RX related interrupt status */
if (reg & EMAC_INTSTS_RXBEIF_Msk) {
/* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
while(1) {}
} else {
/* Get Rx Frame Descriptor */
desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
/* If we reach last recv Rx descriptor, leave the loop */
if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) { /* ownership=CPU */
status = desc->u32Status1 >> 16;
/* If Rx frame is good, process received frame */
if(status & EMAC_RXFD_RXGD) {
/* lower 16 bit in descriptor status1 stores the Rx packet length */
*pu32Size = desc->u32Status1 & 0xFFFFUL;
memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
u32Count = 1UL;
} else {
/* Save Error status if necessary */
if (status & EMAC_RXFD_RP) {}
if (status & EMAC_RXFD_ALIE) {}
if (status & EMAC_RXFD_PTLE) {}
if (status & EMAC_RXFD_CRCE) {}
}
}
}
return(u32Count);
}
/**
* @brief Receive an Ethernet packet and the time stamp while it's received
* @param[out] pu8Data Pointer to a buffer to store received packet (4 byte CRC removed)
* @param[out] pu32Size Received packet size (without 4 byte CRC).
* @param[out] pu32Sec Second value while packet sent
* @param[out] pu32Nsec Nano second value while packet sent
* @return Packet receive success or not
* @retval 0 No packet available for receive
* @retval 1 A packet is received
* @note Return 0 doesn't guarantee the packet will be sent and received successfully.
* @note Largest Ethernet packet is 1514 bytes after stripped CRC, application must give
* a buffer large enough to store such packet
*/
uint32_t EMAC_RecvPktTS(uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec)
{
EMAC_DESCRIPTOR_T *desc;
uint32_t status, reg;
uint32_t u32Count = 0UL;
/* Clear Rx interrupt flags */
reg = EMAC->INTSTS;
EMAC->INTSTS = reg & 0xFFFFUL; /* Clear all Rx related interrupt status */
if (reg & EMAC_INTSTS_RXBEIF_Msk) {
/* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
while(1) {}
} else {
/* Get Rx Frame Descriptor */
desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
/* If we reach last recv Rx descriptor, leave the loop */
if(EMAC->CRXDSA != (uint32_t)desc) {
if ((desc->u32Status1 | EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) { /* ownership=CPU */
status = desc->u32Status1 >> 16;
/* If Rx frame is good, process received frame */
if(status & EMAC_RXFD_RXGD) {
/* lower 16 bit in descriptor status1 stores the Rx packet length */
*pu32Size = desc->u32Status1 & 0xFFFFUL;
memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
*pu32Sec = desc->u32Next; /* second stores in descriptor's NEXT field */
*pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); /* Sub nano second store in DATA field */
u32Count = 1UL;
} else {
/* Save Error status if necessary */
if (status & EMAC_RXFD_RP) {}
if (status & EMAC_RXFD_ALIE) {}
if (status & EMAC_RXFD_PTLE) {}
if (status & EMAC_RXFD_CRCE) {}
}
}
}
}
return(u32Count);
}
/**
* @brief Clean up process after a packet is received
* @param None
* @return None
* @details EMAC Rx interrupt service routine \b must call this API to release the resource use by receive process
* @note Application can only call this function once every time \ref EMAC_RecvPkt or \ref EMAC_RecvPktTS returns 1
*/
void EMAC_RecvPktDone(void)
{
EMAC_DESCRIPTOR_T *desc;
/* Get Rx Frame Descriptor */
desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
/* Restore descriptor link list and data pointer they will be overwrite if time stamp enabled */
desc->u32Data = desc->u32Backup1;
desc->u32Next = desc->u32Backup2;
/* Get Next Frame Descriptor pointer to process */
desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
/* Save last processed Rx descriptor */
u32CurrentRxDesc = (uint32_t)desc;
/* Change ownership to DMA for next use */
desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
EMAC_TRIGGER_RX();
}
/**
* @brief Send an Ethernet packet
* @param[in] pu8Data Pointer to a buffer holds the packet to transmit
* @param[in] u32Size Packet size (without 4 byte CRC).
* @return Packet transmit success or not
* @retval 0 Transmit failed due to descriptor unavailable.
* @retval 1 Packet is copied to descriptor and triggered to transmit.
* @note Return 1 doesn't guarantee the packet will be sent and received successfully.
*/
uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size)
{
EMAC_DESCRIPTOR_T *desc;
uint32_t status;
uint32_t ret = 0UL;
/* Get Tx frame descriptor & data pointer */
desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
status = desc->u32Status1;
/* Check descriptor ownership */
if((status & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) {
memcpy((uint8_t *)desc->u32Data, pu8Data, u32Size);
/* Set Tx descriptor transmit byte count */
desc->u32Status2 = u32Size;
/* Change descriptor ownership to EMAC */
desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
/* Get next Tx descriptor */
u32NextTxDesc = (uint32_t)(desc->u32Next);
/* Trigger EMAC to send the packet */
EMAC_TRIGGER_TX();
ret = 1UL;
}
return(ret);
}
/**
* @brief Clean up process after packet(s) are sent
* @param None
* @return Number of packet sent between two function calls
* @details EMAC Tx interrupt service routine \b must call this API or \ref EMAC_SendPktDoneTS to
* release the resource use by transmit process
*/
uint32_t EMAC_SendPktDone(void)
{
EMAC_DESCRIPTOR_T *desc;
uint32_t status, reg;
uint32_t last_tx_desc;
uint32_t u32Count = 0UL;
reg = EMAC->INTSTS;
/* Clear Tx interrupt flags */
EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk);
if (reg & EMAC_INTSTS_TXBEIF_Msk) {
/* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
while(1) {}
} else {
/* Process the descriptor(s). */
last_tx_desc = EMAC->CTXDSA ;
/* Get our first descriptor to process */
desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
do {
/* Descriptor ownership is still EMAC, so this packet haven't been send. */
if(desc->u32Status1 & EMAC_DESC_OWN_EMAC) {
break;
}
/* Get Tx status stored in descriptor */
status = desc->u32Status2 >> 16UL;
if (status & EMAC_TXFD_TXCP) {
u32Count++;
} else {
/* Do nothing here on error. */
if (status & EMAC_TXFD_TXABT) {}
if (status & EMAC_TXFD_DEF) {}
if (status & EMAC_TXFD_PAU) {}
if (status & EMAC_TXFD_EXDEF) {}
if (status & EMAC_TXFD_NCS) {}
if (status & EMAC_TXFD_SQE) {}
if (status & EMAC_TXFD_LC) {}
if (status & EMAC_TXFD_TXHA) {}
}
/* restore descriptor link list and data pointer they will be overwrite if time stamp enabled */
desc->u32Data = desc->u32Backup1;
desc->u32Next = desc->u32Backup2;
/* go to next descriptor in link */
desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
} while (last_tx_desc != (uint32_t)desc); /* If we reach last sent Tx descriptor, leave the loop */
/* Save last processed Tx descriptor */
u32CurrentTxDesc = (uint32_t)desc;
}
return(u32Count);
}
/**
* @brief Clean up process after a packet is sent, and get the time stamp while packet is sent
* @param[in] pu32Sec Second value while packet sent
* @param[in] pu32Nsec Nano second value while packet sent
* @return If a packet sent successfully
* @retval 0 No packet sent successfully, and the value in *pu32Sec and *pu32Nsec are meaningless
* @retval 1 A packet sent successfully, and the value in *pu32Sec and *pu32Nsec is the time stamp while packet sent
* @details EMAC Tx interrupt service routine \b must call this API or \ref EMAC_SendPktDone to
* release the resource use by transmit process
*/
uint32_t EMAC_SendPktDoneTS(uint32_t *pu32Sec, uint32_t *pu32Nsec)
{
EMAC_DESCRIPTOR_T *desc;
uint32_t status, reg;
uint32_t u32Count = 0UL;
reg = EMAC->INTSTS;
/* Clear Tx interrupt flags */
EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk);
if (reg & EMAC_INTSTS_TXBEIF_Msk) {
/* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
while(1) {}
} else {
/* Process the descriptor.
Get our first descriptor to process */
desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
/* Descriptor ownership is still EMAC, so this packet haven't been send. */
if((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) {
/* Get Tx status stored in descriptor */
status = desc->u32Status2 >> 16UL;
if (status & EMAC_TXFD_TXCP) {
u32Count = 1UL;
*pu32Sec = desc->u32Next; /* second stores in descriptor's NEXT field */
*pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); /* Sub nano second store in DATA field */
} else {
/* Do nothing here on error. */
if (status & EMAC_TXFD_TXABT) {}
if (status & EMAC_TXFD_DEF) {}
if (status & EMAC_TXFD_PAU) {}
if (status & EMAC_TXFD_EXDEF) {}
if (status & EMAC_TXFD_NCS) {}
if (status & EMAC_TXFD_SQE) {}
if (status & EMAC_TXFD_LC) {}
if (status & EMAC_TXFD_TXHA) {}
}
/* restore descriptor link list and data pointer they will be overwrite if time stamp enabled */
desc->u32Data = desc->u32Backup1;
desc->u32Next = desc->u32Backup2;
/* go to next descriptor in link */
desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
/* Save last processed Tx descriptor */
u32CurrentTxDesc = (uint32_t)desc;
}
}
return(u32Count);
}
/**
* @brief Enable IEEE1588 time stamp function and set current time
* @param[in] u32Sec Second value
* @param[in] u32Nsec Nano second value
* @return None
*/
void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec)
{
double f;
uint32_t reg;
EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
EMAC->UPDSEC = u32Sec; /* Assume current time is 0 sec + 0 nano sec */
EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
/* PTP source clock is 160MHz (Real chip using PLL). Each tick is 6.25ns
Assume we want to set each tick to 100ns.
Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
Addend register = 2^32 * tick_freq / (160MHz), where tick_freq = (2^31 / 215) MHz
From above equation, addend register = 2^63 / (160M * 215) ~= 268121280 = 0xFFB34C0
So:
EMAC->TSIR = 0xD7;
EMAC->TSAR = 0x1E70C600; */
f = (100.0 * 2147483648.0) / (1000000000.0) + 0.5;
EMAC->TSINC = (reg = (uint32_t)f);
f = (double)9223372036854775808.0 / ((double)(CLK_GetHCLKFreq()) * (double)reg);
EMAC->TSADDEND = (uint32_t)f;
EMAC->TSCTL |= (EMAC_TSCTL_TSUPDATE_Msk | EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk); /* Fine update */
}
/**
* @brief Disable IEEE1588 time stamp function
* @param None
* @return None
*/
void EMAC_DisableTS(void)
{
EMAC->TSCTL = 0UL;
}
/**
* @brief Get current time stamp
* @param[out] pu32Sec Current second value
* @param[out] pu32Nsec Current nano second value
* @return None
*/
void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec)
{
/* Must read TSLSR firstly. Hardware will preserve TSMSR value at the time TSLSR read. */
*pu32Nsec = EMAC_Subsec2Nsec(EMAC->TSSUBSEC);
*pu32Sec = EMAC->TSSEC;
}
/**
* @brief Set current time stamp
* @param[in] u32Sec Second value
* @param[in] u32Nsec Nano second value
* @return None
*/
void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec)
{
/* Disable time stamp counter before update time value (clear EMAC_TSCTL_TSIEN_Msk) */
EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
EMAC->UPDSEC = u32Sec;
EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
EMAC->TSCTL |= (EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk);
}
/**
* @brief Enable alarm function and set alarm time
* @param[in] u32Sec Second value to trigger alarm
* @param[in] u32Nsec Nano second value to trigger alarm
* @return None
*/
void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec)
{
EMAC->ALMSEC = u32Sec;
EMAC->ALMSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
EMAC->TSCTL |= EMAC_TSCTL_TSALMEN_Msk;
}
/**
* @brief Disable alarm function
* @param None
* @return None
*/
void EMAC_DisableAlarm(void)
{
EMAC->TSCTL &= ~EMAC_TSCTL_TSALMEN_Msk;
}
/**
* @brief Add a offset to current time
* @param[in] u32Neg Offset is negative value (u32Neg == 1) or positive value (u32Neg == 0).
* @param[in] u32Sec Second value to add to current time
* @param[in] u32Nsec Nano second value to add to current time
* @return None
*/
void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec)
{
EMAC->UPDSEC = u32Sec;
EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
if(u32Neg) {
EMAC->UPDSUBSEC |= BIT31; /* Set bit 31 indicates this is a negative value */
}
EMAC->TSCTL |= EMAC_TSCTL_TSUPDATE_Msk;
}
/*@}*/ /* end of group M480_EMAC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_EMAC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,190 @@
/**************************************************************************//**
* @file emac.h
* @version V1.00
* @brief M480 EMAC driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __EMAC_H__
#define __EMAC_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_EMAC_Driver EMAC Driver
@{
*/
/** @addtogroup M480_EMAC_EXPORTED_CONSTANTS EMAC Exported Constants
@{
*/
#define EMAC_PHY_ADDR 1UL /*!< PHY address, this address is board dependent \hideinitializer */
#define EMAC_RX_DESC_SIZE 4UL /*!< Number of Rx Descriptors, should be 2 at least \hideinitializer */
#define EMAC_TX_DESC_SIZE 4UL /*!< Number of Tx Descriptors, should be 2 at least \hideinitializer */
/*@}*/ /* end of group M480_EMAC_EXPORTED_CONSTANTS */
/** @addtogroup M480_EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions
@{
*/
/**
* @brief Enable EMAC Tx function
* @param None
* @return None
* \hideinitializer
*/
#define EMAC_ENABLE_TX() (EMAC->CTL |= EMAC_CTL_TXON_Msk)
/**
* @brief Enable EMAC Rx function
* @param None
* @return None
* \hideinitializer
*/
#define EMAC_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON_Msk; EMAC->RXST = 0;}while(0)
/**
* @brief Disable EMAC Tx function
* @param None
* @return None
* \hideinitializer
*/
#define EMAC_DISABLE_TX() (EMAC->CTL &= ~EMAC_CTL_TXON_Msk)
/**
* @brief Disable EMAC Rx function
* @param None
* @return None
* \hideinitializer
*/
#define EMAC_DISABLE_RX() (EMAC->CTL &= ~EMAC_CTL_RXON_Msk)
/**
* @brief Enable EMAC Magic Packet Wakeup function
* @param None
* @return None
* \hideinitializer
*/
#define EMAC_ENABLE_MAGIC_PKT_WAKEUP() (EMAC->CTL |= EMAC_CTL_WOLEN_Msk)
/**
* @brief Disable EMAC Magic Packet Wakeup function
* @param None
* @return None
* \hideinitializer
*/
#define EMAC_DISABLE_MAGIC_PKT_WAKEUP() (EMAC->CTL &= ~EMAC_CTL_WOLEN_Msk)
/**
* @brief Enable EMAC MII interface
* @param None
* @return None
* @details After calling \ref EMAC_Open, EMAC use RMII interface by default, but can switch to
* MII interface by calling this macro
* \hideinitializer
*/
#define EMAC_ENABLE_MII_INTF() (EMAC->CTL &= ~(EMAC_CTL_RMIIEN_Msk | EMAC_CTL_RMIIRXCTL_Msk))
/**
* @brief Enable EMAC to receive broadcast packets
* @param None
* @return None
* \hideinitializer
*/
#define EMAC_ENABLE_RECV_BCASTPKT() (EMAC->CAMCTL |= EMAC_CAMCTL_ABP_Msk)
/**
* @brief Disable EMAC to receive broadcast packets
* @param None
* @return None
* \hideinitializer
*/
#define EMAC_DISABLE_RECV_BCASTPKT() (EMAC->CAMCTL &= ~EMAC_CAMCTL_ABP_Msk)
/**
* @brief Enable EMAC to receive multicast packets
* @param None
* @return None
* \hideinitializer
*/
#define EMAC_ENABLE_RECV_MCASTPKT() (EMAC->CAMCTL |= EMAC_CAMCTL_AMP_Msk)
/**
* @brief Disable EMAC Magic Packet Wakeup function
* @param None
* @return None
* \hideinitializer
*/
#define EMAC_DISABLE_RECV_MCASTPKT() (EMAC->CAMCTL &= ~EMAC_CAMCTL_AMP_Msk)
/**
* @brief Check if EMAC time stamp alarm interrupt occurred or not
* @param None
* @return If time stamp alarm interrupt occurred or not
* @retval 0 Alarm interrupt does not occur
* @retval 1 Alarm interrupt occurred
* \hideinitializer
*/
#define EMAC_GET_ALARM_FLAG() (EMAC->INTSTS & EMAC_INTSTS_TSALMIF_Msk ? 1 : 0)
/**
* @brief Clear EMAC time stamp alarm interrupt flag
* @param None
* @return None
* \hideinitializer
*/
#define EMAC_CLR_ALARM_FLAG() (EMAC->INTSTS = EMAC_INTSTS_TSALMIF_Msk)
void EMAC_Open(uint8_t *pu8MacAddr);
void EMAC_Close(void);
void EMAC_SetMacAddr(uint8_t *pu8MacAddr);
void EMAC_EnableCamEntry(uint32_t u32Entry, uint8_t pu8MacAddr[]);
void EMAC_DisableCamEntry(uint32_t u32Entry);
uint32_t EMAC_RecvPkt(uint8_t *pu8Data, uint32_t *pu32Size);
uint32_t EMAC_RecvPktTS(uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec);
void EMAC_RecvPktDone(void);
uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size);
uint32_t EMAC_SendPktDone(void);
uint32_t EMAC_SendPktDoneTS(uint32_t *pu32Sec, uint32_t *pu32Nsec);
void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec);
void EMAC_DisableTS(void);
void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec);
void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec);
void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec);
void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec);
void EMAC_DisableAlarm(void);
/*@}*/ /* end of group M480_EMAC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_EMAC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __EMAC_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,621 @@
/**************************************************************************//**
* @file epwm.h
* @version V3.00
* @brief M480 series EPWM driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __EPWM_H__
#define __EPWM_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup EPWM_Driver EPWM Driver
@{
*/
/** @addtogroup EPWM_EXPORTED_CONSTANTS EPWM Exported Constants
@{
*/
#define EPWM_CHANNEL_NUM (6U) /*!< EPWM channel number \hideinitializer */
#define EPWM_CH_0_MASK (0x1U) /*!< EPWM channel 0 mask \hideinitializer */
#define EPWM_CH_1_MASK (0x2U) /*!< EPWM channel 1 mask \hideinitializer */
#define EPWM_CH_2_MASK (0x4U) /*!< EPWM channel 2 mask \hideinitializer */
#define EPWM_CH_3_MASK (0x8U) /*!< EPWM channel 3 mask \hideinitializer */
#define EPWM_CH_4_MASK (0x10U) /*!< EPWM channel 4 mask \hideinitializer */
#define EPWM_CH_5_MASK (0x20U) /*!< EPWM channel 5 mask \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Counter Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_UP_COUNTER (0U) /*!< Up counter type \hideinitializer */
#define EPWM_DOWN_COUNTER (1U) /*!< Down counter type \hideinitializer */
#define EPWM_UP_DOWN_COUNTER (2U) /*!< Up-Down counter type \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Aligned Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_EDGE_ALIGNED (1U) /*!< EPWM working in edge aligned type(down count) \hideinitializer */
#define EPWM_CENTER_ALIGNED (2U) /*!< EPWM working in center aligned type \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Output Level Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_OUTPUT_NOTHING (0U) /*!< EPWM output nothing \hideinitializer */
#define EPWM_OUTPUT_LOW (1U) /*!< EPWM output low \hideinitializer */
#define EPWM_OUTPUT_HIGH (2U) /*!< EPWM output high \hideinitializer */
#define EPWM_OUTPUT_TOGGLE (3U) /*!< EPWM output toggle \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Synchronous Start Function Control Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_SSCTL_SSRC_EPWM0 (0U<<EPWM_SSCTL_SSRC_Pos) /*!< Synchronous start source comes from EPWM0 \hideinitializer */
#define EPWM_SSCTL_SSRC_EPWM1 (1U<<EPWM_SSCTL_SSRC_Pos) /*!< Synchronous start source comes from EPWM0 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Trigger Source Select Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_TRG_ADC_EVEN_ZERO (0U) /*!< EPWM trigger ADC while counter of even channel matches zero point \hideinitializer */
#define EPWM_TRG_ADC_EVEN_PERIOD (1U) /*!< EPWM trigger ADC while counter of even channel matches period point \hideinitializer */
#define EPWM_TRG_ADC_EVEN_ZERO_PERIOD (2U) /*!< EPWM trigger ADC while counter of even channel matches zero or period point \hideinitializer */
#define EPWM_TRG_ADC_EVEN_COMPARE_UP (3U) /*!< EPWM trigger ADC while counter of even channel matches up count to comparator point \hideinitializer */
#define EPWM_TRG_ADC_EVEN_COMPARE_DOWN (4U) /*!< EPWM trigger ADC while counter of even channel matches down count to comparator point \hideinitializer */
#define EPWM_TRG_ADC_ODD_ZERO (5U) /*!< EPWM trigger ADC while counter of odd channel matches zero point \hideinitializer */
#define EPWM_TRG_ADC_ODD_PERIOD (6U) /*!< EPWM trigger ADC while counter of odd channel matches period point \hideinitializer */
#define EPWM_TRG_ADC_ODD_ZERO_PERIOD (7U) /*!< EPWM trigger ADC while counter of odd channel matches zero or period point \hideinitializer */
#define EPWM_TRG_ADC_ODD_COMPARE_UP (8U) /*!< EPWM trigger ADC while counter of odd channel matches up count to comparator point \hideinitializer */
#define EPWM_TRG_ADC_ODD_COMPARE_DOWN (9U) /*!< EPWM trigger ADC while counter of odd channel matches down count to comparator point \hideinitializer */
#define EPWM_TRG_ADC_CH_0_FREE_CMP_UP (10U) /*!< EPWM trigger ADC while counter of channel 0 matches up count to free comparator point \hideinitializer */
#define EPWM_TRG_ADC_CH_0_FREE_CMP_DOWN (11U) /*!< EPWM trigger ADC while counter of channel 0 matches down count to free comparator point \hideinitializer */
#define EPWM_TRG_ADC_CH_2_FREE_CMP_UP (12U) /*!< EPWM trigger ADC while counter of channel 2 matches up count to free comparator point \hideinitializer */
#define EPWM_TRG_ADC_CH_2_FREE_CMP_DOWN (13U) /*!< EPWM trigger ADC while counter of channel 2 matches down count to free comparator point \hideinitializer */
#define EPWM_TRG_ADC_CH_4_FREE_CMP_UP (14U) /*!< EPWM trigger ADC while counter of channel 4 matches up count to free comparator point \hideinitializer */
#define EPWM_TRG_ADC_CH_4_FREE_CMP_DOWN (15U) /*!< EPWM trigger ADC while counter of channel 4 matches down count to free comparator point \hideinitializer */
#define EPWM_TRIGGER_DAC_ZERO (0x1U) /*!< EPWM trigger ADC while counter down count to 0 \hideinitializer */
#define EPWM_TRIGGER_DAC_PERIOD (0x100U) /*!< EPWM trigger ADC while counter matches (PERIOD + 1) \hideinitializer */
#define EPWM_TRIGGER_DAC_COMPARE_UP (0x10000U) /*!< EPWM trigger ADC while counter up count to CMPDAT \hideinitializer */
#define EPWM_TRIGGER_DAC_COMPARE_DOWN (0x1000000U) /*!< EPWM trigger ADC while counter down count to CMPDAT \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Fail brake Control Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_FB_EDGE_ACMP0 (EPWM_BRKCTL0_1_CPO0EBEN_Msk) /*!< Comparator 0 as edge-detect fault brake source \hideinitializer */
#define EPWM_FB_EDGE_ACMP1 (EPWM_BRKCTL0_1_CPO1EBEN_Msk) /*!< Comparator 1 as edge-detect fault brake source \hideinitializer */
#define EPWM_FB_EDGE_BKP0 (EPWM_BRKCTL0_1_BRKP0EEN_Msk) /*!< BKP0 pin as edge-detect fault brake source \hideinitializer */
#define EPWM_FB_EDGE_BKP1 (EPWM_BRKCTL0_1_BRKP1EEN_Msk) /*!< BKP1 pin as edge-detect fault brake source \hideinitializer */
#define EPWM_FB_EDGE_ADCRM (EPWM_BRKCTL0_1_ADCEBEN_Msk) /*!< ADC Result Monitor (ADCRM) as edge-detect fault brake source \hideinitializer */
#define EPWM_FB_EDGE_SYS_CSS (EPWM_BRKCTL0_1_SYSEBEN_Msk | EPWM_FAILBRK_CSSBRKEN_Msk) /*!< System fail condition: clock security system detection as edge-detect fault brake source \hideinitializer */
#define EPWM_FB_EDGE_SYS_BOD (EPWM_BRKCTL0_1_SYSEBEN_Msk | EPWM_FAILBRK_BODBRKEN_Msk) /*!< System fail condition: brown-out detection as edge-detect fault brake source \hideinitializer */
#define EPWM_FB_EDGE_SYS_RAM (EPWM_BRKCTL0_1_SYSEBEN_Msk | EPWM_FAILBRK_RAMBRKEN_Msk) /*!< System fail condition: SRAM parity error detection as edge-detect fault brake source \hideinitializer */
#define EPWM_FB_EDGE_SYS_COR (EPWM_BRKCTL0_1_SYSEBEN_Msk | EPWM_FAILBRK_CORBRKEN_Msk) /*!< System fail condition: core lockup detection as edge-detect fault brake source \hideinitializer */
#define EPWM_FB_LEVEL_ACMP0 (EPWM_BRKCTL0_1_CPO0LBEN_Msk) /*!< Comparator 0 as level-detect fault brake source \hideinitializer */
#define EPWM_FB_LEVEL_ACMP1 (EPWM_BRKCTL0_1_CPO1LBEN_Msk) /*!< Comparator 1 as level-detect fault brake source \hideinitializer */
#define EPWM_FB_LEVEL_BKP0 (EPWM_BRKCTL0_1_BRKP0LEN_Msk) /*!< BKP0 pin as level-detect fault brake source \hideinitializer */
#define EPWM_FB_LEVEL_BKP1 (EPWM_BRKCTL0_1_BRKP1LEN_Msk) /*!< BKP1 pin as level-detect fault brake source \hideinitializer */
#define EPWM_FB_LEVEL_ADCRM (EPWM_BRKCTL0_1_ADCLBEN_Msk) /*!< ADC Result Monitor (ADCRM) as level-detect fault brake source \hideinitializer */
#define EPWM_FB_LEVEL_SYS_CSS (EPWM_BRKCTL0_1_SYSLBEN_Msk | EPWM_FAILBRK_CSSBRKEN_Msk) /*!< System fail condition: clock security system detection as level-detect fault brake source \hideinitializer */
#define EPWM_FB_LEVEL_SYS_BOD (EPWM_BRKCTL0_1_SYSLBEN_Msk | EPWM_FAILBRK_BODBRKEN_Msk) /*!< System fail condition: brown-out detection as level-detect fault brake source \hideinitializer */
#define EPWM_FB_LEVEL_SYS_RAM (EPWM_BRKCTL0_1_SYSLBEN_Msk | EPWM_FAILBRK_RAMBRKEN_Msk) /*!< System fail condition: SRAM parity error detection as level-detect fault brake source \hideinitializer */
#define EPWM_FB_LEVEL_SYS_COR (EPWM_BRKCTL0_1_SYSLBEN_Msk | EPWM_FAILBRK_CORBRKEN_Msk) /*!< System fail condition: core lockup detection as level-detect fault brake source \hideinitializer */
#define EPWM_FB_EDGE (0U) /*!< edge-detect fault brake \hideinitializer */
#define EPWM_FB_LEVEL (8U) /*!< level-detect fault brake \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Leading Edge Blanking Control Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_LEBCTL_TRGTYPE_RISING (0U<<EPWM_LEBCTL_TRGTYPE_Pos) /*!< EPWM Leading Edge Blanking Trigger Type Is Rising Edge \hideinitializer */
#define EPWM_LEBCTL_TRGTYPE_FALLING (1U<<EPWM_LEBCTL_TRGTYPE_Pos) /*!< EPWM Leading Edge Blanking Trigger Type Is Falling Edge \hideinitializer */
#define EPWM_LEBCTL_TRGTYPE_RISING_OR_FALLING (2U<<EPWM_LEBCTL_TRGTYPE_Pos) /*!< EPWM Leading Edge Blanking Trigger Type Is Rising or Falling Edge \hideinitializer */
#define EPWM_LEBCTL_SRCEN0 (EPWM_LEBCTL_SRCEN0_Msk) /*!< EPWM Leading Edge Blanking Source From EPWMx_CH0 Enable \hideinitializer */
#define EPWM_LEBCTL_SRCEN2 (EPWM_LEBCTL_SRCEN2_Msk) /*!< EPWM Leading Edge Blanking Source From EPWMx_CH2 Enable \hideinitializer */
#define EPWM_LEBCTL_SRCEN4 (EPWM_LEBCTL_SRCEN4_Msk) /*!< EPWM Leading Edge Blanking Source From EPWMx_CH4 Enable \hideinitializer */
#define EPWM_LEBCTL_SRCEN0_2 (EPWM_LEBCTL_SRCEN0_Msk|EPWM_LEBCTL_SRCEN2_Msk) /*!< EPWM Leading Edge Blanking Source From EPWMx_CH0 and EPWMx_CH2 Enable \hideinitializer */
#define EPWM_LEBCTL_SRCEN0_4 (EPWM_LEBCTL_SRCEN0_Msk|EPWM_LEBCTL_SRCEN4_Msk) /*!< EPWM Leading Edge Blanking Source From EPWMx_CH0 and EPWMx_CH4 Enable \hideinitializer */
#define EPWM_LEBCTL_SRCEN2_4 (EPWM_LEBCTL_SRCEN2_Msk|EPWM_LEBCTL_SRCEN4_Msk) /*!< EPWM Leading Edge Blanking Source From EPWMx_CH2 and EPWMx_CH4 Enable \hideinitializer */
#define EPWM_LEBCTL_SRCEN0_2_4 (EPWM_LEBCTL_SRCEN0_Msk|EPWM_LEBCTL_SRCEN2_Msk|EPWM_LEBCTL_SRCEN4_Msk) /*!< EPWM Leading Edge Blanking Source From EPWMx_CH0, EPWMx_CH2 and EPWMx_CH4 Enable \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Capture Control Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_CAPTURE_INT_RISING_LATCH (1U) /*!< EPWM capture interrupt if channel has rising transition \hideinitializer */
#define EPWM_CAPTURE_INT_FALLING_LATCH (0x100U) /*!< EPWM capture interrupt if channel has falling transition \hideinitializer */
#define EPWM_CAPTURE_PDMA_RISING_LATCH (0x2U) /*!< EPWM capture rising latched data transfer by PDMA \hideinitializer */
#define EPWM_CAPTURE_PDMA_FALLING_LATCH (0x4U) /*!< EPWM capture falling latched data transfer by PDMA \hideinitializer */
#define EPWM_CAPTURE_PDMA_RISING_FALLING_LATCH (0x6U) /*!< EPWM capture rising and falling latched data transfer by PDMA \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Duty Interrupt Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_DUTY_INT_DOWN_COUNT_MATCH_CMP (1U << EPWM_INTEN0_CMPDIEN0_Pos) /*!< EPWM duty interrupt triggered if down count match comparator \hideinitializer */
#define EPWM_DUTY_INT_UP_COUNT_MATCH_CMP (1U << EPWM_INTEN0_CMPUIEN0_Pos) /*!< EPWM duty interrupt triggered if up down match comparator \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Interrupt Flag Accumulator Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_IFA_ZERO_POINT (0U) /*!< EPWM counter equal to zero \hideinitializer */
#define EPWM_IFA_PERIOD_POINT (1U) /*!< EPWM counter equal to period \hideinitializer */
#define EPWM_IFA_COMPARE_UP_COUNT_POINT (2U) /*!< EPWM counter up count to comparator value \hideinitializer */
#define EPWM_IFA_COMPARE_DOWN_COUNT_POINT (3U) /*!< EPWM counter down count to comparator value \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Load Mode Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_LOAD_MODE_IMMEDIATE (1U << EPWM_CTL0_IMMLDEN0_Pos) /*!< EPWM immediately load mode \hideinitializer */
#define EPWM_LOAD_MODE_WINDOW (1U << EPWM_CTL0_WINLDEN0_Pos) /*!< EPWM window load mode \hideinitializer */
#define EPWM_LOAD_MODE_CENTER (1U << EPWM_CTL0_CTRLD0_Pos) /*!< EPWM center load mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Synchronize Control Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_SYNC_OUT_FROM_SYNCIN_SWSYNC (0U) /*!< Synchronize source from SYNC_IN or SWSYNC \hideinitializer */
#define EPWM_SYNC_OUT_FROM_COUNT_TO_ZERO (1U) /*!< Synchronize source from counter equal to 0 \hideinitializer */
#define EPWM_SYNC_OUT_FROM_COUNT_TO_COMPARATOR (2U) /*!< Synchronize source from counter equal to CMPDAT1, CMPDAT3, CMPDAT5 \hideinitializer */
#define EPWM_SYNC_OUT_DISABLE (3U) /*!< SYNC_OUT will not be generated \hideinitializer */
#define EPWM_PHS_DIR_DECREMENT (0U) /*!< EPWM counter count decrement \hideinitializer */
#define EPWM_PHS_DIR_INCREMENT (1U) /*!< EPWM counter count increment \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Noise Filter Clock Divide Select Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_NF_CLK_DIV_1 (0U) /*!< Noise filter clock is HCLK divide by 1 \hideinitializer */
#define EPWM_NF_CLK_DIV_2 (1U) /*!< Noise filter clock is HCLK divide by 2 \hideinitializer */
#define EPWM_NF_CLK_DIV_4 (2U) /*!< Noise filter clock is HCLK divide by 4 \hideinitializer */
#define EPWM_NF_CLK_DIV_8 (3U) /*!< Noise filter clock is HCLK divide by 8 \hideinitializer */
#define EPWM_NF_CLK_DIV_16 (4U) /*!< Noise filter clock is HCLK divide by 16 \hideinitializer */
#define EPWM_NF_CLK_DIV_32 (5U) /*!< Noise filter clock is HCLK divide by 32 \hideinitializer */
#define EPWM_NF_CLK_DIV_64 (6U) /*!< Noise filter clock is HCLK divide by 64 \hideinitializer */
#define EPWM_NF_CLK_DIV_128 (7U) /*!< Noise filter clock is HCLK divide by 128 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Clock Source Select Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define EPWM_CLKSRC_EPWM_CLK (0U) /*!< EPWM Clock source selects to EPWM0_CLK or EPWM1_CLK \hideinitializer */
#define EPWM_CLKSRC_TIMER0 (1U) /*!< EPWM Clock source selects to TIMER0 overflow \hideinitializer */
#define EPWM_CLKSRC_TIMER1 (2U) /*!< EPWM Clock source selects to TIMER1 overflow \hideinitializer */
#define EPWM_CLKSRC_TIMER2 (3U) /*!< EPWM Clock source selects to TIMER2 overflow \hideinitializer */
#define EPWM_CLKSRC_TIMER3 (4U) /*!< EPWM Clock source selects to TIMER3 overflow \hideinitializer */
/*@}*/ /* end of group EPWM_EXPORTED_CONSTANTS */
/** @addtogroup EPWM_EXPORTED_FUNCTIONS EPWM Exported Functions
@{
*/
/**
* @brief This macro enable complementary mode
* @param[in] epwm The pointer of the specified EPWM module
* @return None
* @details This macro is used to enable complementary mode of EPWM module.
* \hideinitializer
*/
#define EPWM_ENABLE_COMPLEMENTARY_MODE(epwm) ((epwm)->CTL1 = (epwm)->CTL1 | (0x7ul<<EPWM_CTL1_OUTMODE0_Pos))
/**
* @brief This macro disable complementary mode, and enable independent mode.
* @param[in] epwm The pointer of the specified EPWM module
* @return None
* @details This macro is used to disable complementary mode of EPWM module.
* \hideinitializer
*/
#define EPWM_DISABLE_COMPLEMENTARY_MODE(epwm) ((epwm)->CTL1 = (epwm)->CTL1 & ~(0x7ul<<EPWM_CTL1_OUTMODE0_Pos))
/**
* @brief This macro enable group mode
* @param[in] epwm The pointer of the specified EPWM module
* @return None
* @details This macro is used to enable group mode of EPWM module.
* \hideinitializer
*/
#define EPWM_ENABLE_GROUP_MODE(epwm) ((epwm)->CTL0 = (epwm)->CTL0 | EPWM_CTL0_GROUPEN_Msk)
/**
* @brief This macro disable group mode
* @param[in] epwm The pointer of the specified EPWM module
* @return None
* @details This macro is used to disable group mode of EPWM module.
* \hideinitializer
*/
#define EPWM_DISABLE_GROUP_MODE(epwm) ((epwm)->CTL0 = (epwm)->CTL0 & ~EPWM_CTL0_GROUPEN_Msk)
/**
* @brief Enable timer synchronous start counting function of specified channel(s)
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 1...
* @param[in] u32SyncSrc Synchronous start source selection, valid values are:
* - \ref EPWM_SSCTL_SSRC_EPWM0
* - \ref EPWM_SSCTL_SSRC_EPWM1
* @return None
* @details This macro is used to enable timer synchronous start counting function of specified channel(s).
* \hideinitializer
*/
#define EPWM_ENABLE_TIMER_SYNC(epwm, u32ChannelMask, u32SyncSrc) ((epwm)->SSCTL = ((epwm)->SSCTL & ~EPWM_SSCTL_SSRC_Msk) | (u32SyncSrc) | (u32ChannelMask))
/**
* @brief Disable timer synchronous start counting function of specified channel(s)
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 1...
* @return None
* @details This macro is used to disable timer synchronous start counting function of specified channel(s).
* \hideinitializer
*/
#define EPWM_DISABLE_TIMER_SYNC(epwm, u32ChannelMask) \
do{ \
int i;\
for(i = 0; i < 6; i++) { \
if((u32ChannelMask) & (1 << i)) \
(epwm)->SSCTL &= ~(1UL << i); \
} \
}while(0)
/**
* @brief This macro enable EPWM counter synchronous start counting function.
* @param[in] epwm The pointer of the specified EPWM module
* @return None
* @details This macro is used to make selected EPWM0 and EPWM1 channel(s) start counting at the same time.
* To configure synchronous start counting channel(s) by EPWM_ENABLE_TIMER_SYNC() and EPWM_DISABLE_TIMER_SYNC().
* \hideinitializer
*/
#define EPWM_TRIGGER_SYNC_START(epwm) ((epwm)->SSTRG = EPWM_SSTRG_CNTSEN_Msk)
/**
* @brief This macro enable output inverter of specified channel(s)
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 1...
* @return None
* @details This macro is used to enable output inverter of specified channel(s).
* \hideinitializer
*/
#define EPWM_ENABLE_OUTPUT_INVERTER(epwm, u32ChannelMask) ((epwm)->POLCTL = (u32ChannelMask))
/**
* @brief This macro get captured rising data
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelNum EPWM channel number. Valid values are between 0~5
* @return None
* @details This macro is used to get captured rising data of specified channel.
* \hideinitializer
*/
#define EPWM_GET_CAPTURE_RISING_DATA(epwm, u32ChannelNum) (*(__IO uint32_t *) (&((epwm)->RCAPDAT0) + ((u32ChannelNum) << 1)))
/**
* @brief This macro get captured falling data
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelNum EPWM channel number. Valid values are between 0~5
* @return None
* @details This macro is used to get captured falling data of specified channel.
* \hideinitializer
*/
#define EPWM_GET_CAPTURE_FALLING_DATA(epwm, u32ChannelNum) (*(__IO uint32_t *) (&((epwm)->FCAPDAT0) + ((u32ChannelNum) << 1)))
/**
* @brief This macro mask output logic to high or low
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 1...
* @param[in] u32LevelMask Output logic to high or low
* @return None
* @details This macro is used to mask output logic to high or low of specified channel(s).
* @note If u32ChannelMask parameter is 0, then mask function will be disabled.
* \hideinitializer
*/
#define EPWM_MASK_OUTPUT(epwm, u32ChannelMask, u32LevelMask) \
{ \
(epwm)->MSKEN = (u32ChannelMask); \
(epwm)->MSK = (u32LevelMask); \
}
/**
* @brief This macro set the prescaler of the selected channel
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelNum EPWM channel number. Valid values are between 0~5
* @param[in] u32Prescaler Clock prescaler of specified channel. Valid values are between 0 ~ 0xFFF
* @return None
* @details This macro is used to set the prescaler of specified channel.
* @note Every even channel N, and channel (N + 1) share a prescaler. So if channel 0 prescaler changed, channel 1 will also be affected.
* The clock of EPWM counter is divided by (u32Prescaler + 1).
* \hideinitializer
*/
#define EPWM_SET_PRESCALER(epwm, u32ChannelNum, u32Prescaler) (epwm)->CLKPSC[(u32ChannelNum) >> 1] = (u32Prescaler)
/**
* @brief This macro get the prescaler of the selected channel
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelNum EPWM channel number. Valid values are between 0~5
* @return Return Clock prescaler of specified channel. Valid values are between 0 ~ 0xFFF
* @details This macro is used to get the prescaler of specified channel.
* @note Every even channel N, and channel (N + 1) share a prescaler. So if channel 0 prescaler changed, channel 1 will also be affected.
* The clock of EPWM counter is divided by (u32Prescaler + 1).
* \hideinitializer
*/
#define EPWM_GET_PRESCALER(epwm, u32ChannelNum) ((epwm)->CLKPSC[(u32ChannelNum) >> 1U])
/**
* @brief This macro set the comparator of the selected channel
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelNum EPWM channel number. Valid values are between 0~5
* @param[in] u32CMR Comparator of specified channel. Valid values are between 0~0xFFFF
* @return None
* @details This macro is used to set the comparator of specified channel.
* @note This new setting will take effect on next EPWM period.
* \hideinitializer
*/
#define EPWM_SET_CMR(epwm, u32ChannelNum, u32CMR) ((epwm)->CMPDAT[(u32ChannelNum)]= (u32CMR))
/**
* @brief This macro get the comparator of the selected channel
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelNum EPWM channel number. Valid values are between 0~5
* @return Return the comparator of specified channel. Valid values are between 0~0xFFFF
* @details This macro is used to get the comparator of specified channel.
* \hideinitializer
*/
#define EPWM_GET_CMR(epwm, u32ChannelNum) ((epwm)->CMPDAT[(u32ChannelNum)])
/**
* @brief This macro set the free trigger comparator of the selected channel
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelNum EPWM channel number. Valid values are between 0~5
* @param[in] u32FTCMR Free trigger comparator of specified channel. Valid values are between 0~0xFFFF
* @return None
* @details This macro is used to set the free trigger comparator of specified channel.
* @note This new setting will take effect on next EPWM period.
* \hideinitializer
*/
#define EPWM_SET_FTCMR(epwm, u32ChannelNum, u32FTCMR) (((epwm)->FTCMPDAT[((u32ChannelNum) >> 1U)]) = (u32FTCMR))
/**
* @brief This macro set the period of the selected channel
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelNum EPWM channel number. Valid values are between 0~5
* @param[in] u32CNR Period of specified channel. Valid values are between 0~0xFFFF
* @return None
* @details This macro is used to set the period of specified channel.
* @note This new setting will take effect on next EPWM period.
* @note EPWM counter will stop if period length set to 0.
* \hideinitializer
*/
#define EPWM_SET_CNR(epwm, u32ChannelNum, u32CNR) ((epwm)->PERIOD[(u32ChannelNum)] = (u32CNR))
/**
* @brief This macro get the period of the selected channel
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelNum EPWM channel number. Valid values are between 0~5
* @return Return the period of specified channel. Valid values are between 0~0xFFFF
* @details This macro is used to get the period of specified channel.
* \hideinitializer
*/
#define EPWM_GET_CNR(epwm, u32ChannelNum) ((epwm)->PERIOD[(u32ChannelNum)])
/**
* @brief This macro set the EPWM aligned type
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 1...
* @param[in] u32AlignedType EPWM aligned type, valid values are:
* - \ref EPWM_EDGE_ALIGNED
* - \ref EPWM_CENTER_ALIGNED
* @return None
* @details This macro is used to set the EPWM aligned type of specified channel(s).
* \hideinitializer
*/
#define EPWM_SET_ALIGNED_TYPE(epwm, u32ChannelMask, u32AlignedType) \
do{ \
int i; \
for(i = 0; i < 6; i++) { \
if((u32ChannelMask) & (1 << i)) \
(epwm)->CTL1 = (((epwm)->CTL1 & ~(3UL << (i << 1))) | ((u32AlignedType) << (i << 1))); \
} \
}while(0)
/**
* @brief Set load window of window loading mode for specified channel(s)
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 1...
* @return None
* @details This macro is used to set load window of window loading mode for specified channel(s).
* \hideinitializer
*/
#define EPWM_SET_LOAD_WINDOW(epwm, u32ChannelMask) ((epwm)->LOAD |= (u32ChannelMask))
/**
* @brief Trigger synchronous event from specified channel(s)
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelNum EPWM channel number. Valid values are 0, 2, 4
* Bit 0 represents channel 0, bit 1 represents channel 2 and bit 2 represents channel 4
* @return None
* @details This macro is used to trigger synchronous event from specified channel(s).
* \hideinitializer
*/
#define EPWM_TRIGGER_SYNC(epwm, u32ChannelNum) ((epwm)->SWSYNC |= (1 << ((u32ChannelNum) >> 1)))
/**
* @brief Clear counter of specified channel(s)
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 1...
* @return None
* @details This macro is used to clear counter of specified channel(s).
* \hideinitializer
*/
#define EPWM_CLR_COUNTER(epwm, u32ChannelMask) ((epwm)->CNTCLR |= (u32ChannelMask))
/**
* @brief Set output level at zero, compare up, period(center) and compare down of specified channel(s)
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 1...
* @param[in] u32ZeroLevel output level at zero point, valid values are:
* - \ref EPWM_OUTPUT_NOTHING
* - \ref EPWM_OUTPUT_LOW
* - \ref EPWM_OUTPUT_HIGH
* - \ref EPWM_OUTPUT_TOGGLE
* @param[in] u32CmpUpLevel output level at compare up point, valid values are:
* - \ref EPWM_OUTPUT_NOTHING
* - \ref EPWM_OUTPUT_LOW
* - \ref EPWM_OUTPUT_HIGH
* - \ref EPWM_OUTPUT_TOGGLE
* @param[in] u32PeriodLevel output level at period(center) point, valid values are:
* - \ref EPWM_OUTPUT_NOTHING
* - \ref EPWM_OUTPUT_LOW
* - \ref EPWM_OUTPUT_HIGH
* - \ref EPWM_OUTPUT_TOGGLE
* @param[in] u32CmpDownLevel output level at compare down point, valid values are:
* - \ref EPWM_OUTPUT_NOTHING
* - \ref EPWM_OUTPUT_LOW
* - \ref EPWM_OUTPUT_HIGH
* - \ref EPWM_OUTPUT_TOGGLE
* @return None
* @details This macro is used to Set output level at zero, compare up, period(center) and compare down of specified channel(s).
* \hideinitializer
*/
#define EPWM_SET_OUTPUT_LEVEL(epwm, u32ChannelMask, u32ZeroLevel, u32CmpUpLevel, u32PeriodLevel, u32CmpDownLevel) \
do{ \
int i; \
for(i = 0; i < 6; i++) { \
if((u32ChannelMask) & (1 << i)) { \
(epwm)->WGCTL0 = (((epwm)->WGCTL0 & ~(3UL << (i << 1))) | ((u32ZeroLevel) << (i << 1))); \
(epwm)->WGCTL0 = (((epwm)->WGCTL0 & ~(3UL << (EPWM_WGCTL0_PRDPCTL0_Pos + (i << 1)))) | ((u32PeriodLevel) << (EPWM_WGCTL0_PRDPCTL0_Pos + (i << 1)))); \
(epwm)->WGCTL1 = (((epwm)->WGCTL1 & ~(3UL << (i << 1))) | ((u32CmpUpLevel) << (i << 1))); \
(epwm)->WGCTL1 = (((epwm)->WGCTL1 & ~(3UL << (EPWM_WGCTL1_CMPDCTL0_Pos + (i << 1)))) | ((u32CmpDownLevel) << (EPWM_WGCTL1_CMPDCTL0_Pos + (i << 1)))); \
} \
} \
}while(0)
/**
* @brief Trigger brake event from specified channel(s)
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
* Bit 0 represents channel 0, bit 1 represents channel 2 and bit 2 represents channel 4
* @param[in] u32BrakeType Type of brake trigger.
* - \ref EPWM_FB_EDGE
* - \ref EPWM_FB_LEVEL
* @return None
* @details This macro is used to trigger brake event from specified channel(s).
* \hideinitializer
*/
#define EPWM_TRIGGER_BRAKE(epwm, u32ChannelMask, u32BrakeType) ((epwm)->SWBRK |= ((u32ChannelMask) << (u32BrakeType)))
/**
* @brief Set Dead zone clock source
* @param[in] epwm The pointer of the specified EPWM module
* @param[in] u32ChannelNum EPWM channel number. Valid values are between 0~5
* @param[in] u32AfterPrescaler Dead zone clock source is from prescaler output. Valid values are TRUE (after prescaler) or FALSE (before prescaler).
* @return None
* @details This macro is used to set Dead zone clock source. Every two channels share the same setting.
* @note The write-protection function should be disabled before using this function.
* \hideinitializer
*/
#define EPWM_SET_DEADZONE_CLK_SRC(epwm, u32ChannelNum, u32AfterPrescaler) \
((epwm)->DTCTL[(u32ChannelNum) >> 1]) = ((epwm)->DTCTL[(u32ChannelNum) >> 1] & ~EPWM_DTCTL0_1_DTCKSEL_Msk) | \
((u32AfterPrescaler) << EPWM_DTCTL0_1_DTCKSEL_Pos))
/*---------------------------------------------------------------------------------------------------------*/
/* Define EPWM functions prototype */
/*---------------------------------------------------------------------------------------------------------*/
uint32_t EPWM_ConfigCaptureChannel(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32UnitTimeNsec, uint32_t u32CaptureEdge);
uint32_t EPWM_ConfigOutputChannel(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32Frequency, uint32_t u32DutyCycle);
uint32_t EPWM_ConfigOutputChannel2(EPWM_T *epwm,
uint32_t u32ChannelNum,
uint32_t u32Frequency,
uint32_t u32DutyCycle,
uint32_t u32Frequency2);
void EPWM_Start(EPWM_T *epwm, uint32_t u32ChannelMask);
void EPWM_Stop(EPWM_T *epwm, uint32_t u32ChannelMask);
void EPWM_ForceStop(EPWM_T *epwm, uint32_t u32ChannelMask);
void EPWM_EnableADCTrigger(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32Condition);
void EPWM_DisableADCTrigger(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_ClearADCTriggerFlag(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32Condition);
uint32_t EPWM_GetADCTriggerFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_EnableDACTrigger(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32Condition);
void EPWM_DisableDACTrigger(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_ClearDACTriggerFlag(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32Condition);
uint32_t EPWM_GetDACTriggerFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_EnableFaultBrake(EPWM_T *epwm, uint32_t u32ChannelMask, uint32_t u32LevelMask, uint32_t u32BrakeSource);
void EPWM_EnableCapture(EPWM_T *epwm, uint32_t u32ChannelMask);
void EPWM_DisableCapture(EPWM_T *epwm, uint32_t u32ChannelMask);
void EPWM_EnableOutput(EPWM_T *epwm, uint32_t u32ChannelMask);
void EPWM_DisableOutput(EPWM_T *epwm, uint32_t u32ChannelMask);
void EPWM_EnablePDMA(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32RisingFirst, uint32_t u32Mode);
void EPWM_DisablePDMA(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_EnableDeadZone(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32Duration);
void EPWM_DisableDeadZone(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_EnableCaptureInt(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32Edge);
void EPWM_DisableCaptureInt(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32Edge);
void EPWM_ClearCaptureIntFlag(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32Edge);
uint32_t EPWM_GetCaptureIntFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_EnableDutyInt(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType);
void EPWM_DisableDutyInt(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_ClearDutyIntFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
uint32_t EPWM_GetDutyIntFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_EnableFaultBrakeInt(EPWM_T *epwm, uint32_t u32BrakeSource);
void EPWM_DisableFaultBrakeInt(EPWM_T *epwm, uint32_t u32BrakeSource);
void EPWM_ClearFaultBrakeIntFlag(EPWM_T *epwm, uint32_t u32BrakeSource);
uint32_t EPWM_GetFaultBrakeIntFlag(EPWM_T *epwm, uint32_t u32BrakeSource);
void EPWM_EnablePeriodInt(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType);
void EPWM_DisablePeriodInt(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_ClearPeriodIntFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
uint32_t EPWM_GetPeriodIntFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_EnableZeroInt(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_DisableZeroInt(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_ClearZeroIntFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
uint32_t EPWM_GetZeroIntFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_EnableAcc(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32IntFlagCnt, uint32_t u32IntAccSrc);
void EPWM_DisableAcc(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_EnableAccInt(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_DisableAccInt(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_ClearAccInt(EPWM_T *epwm, uint32_t u32ChannelNum);
uint32_t EPWM_GetAccInt(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_EnableAccPDMA(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_DisableAccPDMA(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_ClearFTDutyIntFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
uint32_t EPWM_GetFTDutyIntFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_EnableLoadMode(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32LoadMode);
void EPWM_DisableLoadMode(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32LoadMode);
void EPWM_ConfigSyncPhase(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32SyncSrc, uint32_t u32Direction, uint32_t u32StartPhase);
void EPWM_EnableSyncPhase(EPWM_T *epwm, uint32_t u32ChannelMask);
void EPWM_DisableSyncPhase(EPWM_T *epwm, uint32_t u32ChannelMask);
void EPWM_EnableSyncNoiseFilter(EPWM_T *epwm, uint32_t u32ClkCnt, uint32_t u32ClkDivSel);
void EPWM_DisableSyncNoiseFilter(EPWM_T *epwm);
void EPWM_EnableSyncPinInverse(EPWM_T *epwm);
void EPWM_DisableSyncPinInverse(EPWM_T *epwm);
void EPWM_SetClockSource(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32ClkSrcSel);
void EPWM_EnableBrakeNoiseFilter(EPWM_T *epwm, uint32_t u32BrakePinNum, uint32_t u32ClkCnt, uint32_t u32ClkDivSel);
void EPWM_DisableBrakeNoiseFilter(EPWM_T *epwm, uint32_t u32BrakePinNum);
void EPWM_EnableBrakePinInverse(EPWM_T *epwm, uint32_t u32BrakePinNum);
void EPWM_DisableBrakePinInverse(EPWM_T *epwm, uint32_t u32BrakePinNum);
void EPWM_SetBrakePinSource(EPWM_T *epwm, uint32_t u32BrakePinNum, uint32_t u32SelAnotherModule);
void EPWM_SetLeadingEdgeBlanking(EPWM_T *epwm, uint32_t u32TrigSrcSel, uint32_t u32TrigType, uint32_t u32BlankingCnt, uint32_t u32BlankingEnable);
uint32_t EPWM_GetWrapAroundFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
void EPWM_ClearWrapAroundFlag(EPWM_T *epwm, uint32_t u32ChannelNum);
/*@}*/ /* end of group EPWM_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group EPWM_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __EPWM_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,756 @@
/**************************************************************************//**
* @file fmc.c
* @version V1.00
* @brief M480 series FMC driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_FMC_Driver FMC Driver
@{
*/
/** @addtogroup M480_FMC_EXPORTED_FUNCTIONS FMC Exported Functions
@{
*/
/**
* @brief Disable FMC ISP function.
* @return None
*/
void FMC_Close(void)
{
FMC->ISPCTL &= ~FMC_ISPCTL_ISPEN_Msk;
}
/**
* @brief Execute FMC_ISPCMD_PAGE_ERASE command to erase a flash page. The page size is 4096 bytes.
* @param[in] u32PageAddr Address of the flash page to be erased.
* It must be a 4096 bytes aligned address.
* @return ISP page erase success or not.
* @retval 0 Success
* @retval -1 Erase failed
*/
int32_t FMC_Erase(uint32_t u32PageAddr)
{
int32_t ret = 0;
if (u32PageAddr == FMC_SPROM_BASE) {
ret = FMC_Erase_SPROM();
}
if (ret == 0) {
FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE;
FMC->ISPADDR = u32PageAddr;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) {
FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
ret = -1;
}
}
return ret;
}
/**
* @brief Execute FMC_ISPCMD_PAGE_ERASE command to erase SPROM. The page size is 4096 bytes.
* @return SPROM page erase success or not.
* @retval 0 Success
* @retval -1 Erase failed
*/
int32_t FMC_Erase_SPROM(void)
{
int32_t ret = 0;
FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE;
FMC->ISPADDR = FMC_SPROM_BASE;
FMC->ISPDAT = 0x0055AA03UL;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) {
FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
ret = -1;
}
return ret;
}
/**
* @brief Execute FMC_ISPCMD_BLOCK_ERASE command to erase a flash block. The block size is 4 pages.
* @param[in] u32BlockAddr Address of the flash block to be erased.
* It must be a 4 pages aligned address.
* @return ISP page erase success or not.
* @retval 0 Success
* @retval -1 Erase failed
*/
int32_t FMC_Erase_Block(uint32_t u32BlockAddr)
{
int32_t ret = 0;
FMC->ISPCMD = FMC_ISPCMD_BLOCK_ERASE;
FMC->ISPADDR = u32BlockAddr;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) {
FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
ret = -1;
}
return ret;
}
/**
* @brief Execute FMC_ISPCMD_BANK_ERASE command to erase a flash block.
* @param[in] u32BankAddr Base address of the flash bank to be erased.
* @return ISP page erase success or not.
* @retval 0 Success
* @retval -1 Erase failed
*/
int32_t FMC_Erase_Bank(uint32_t u32BankAddr)
{
int32_t ret = 0;
FMC->ISPCMD = FMC_ISPCMD_BANK_ERASE;
FMC->ISPADDR = u32BankAddr;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) {
FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
ret = -1;
}
return ret;
}
/**
* @brief Get the current boot source.
* @return The current boot source.
* @retval 0 Is boot from APROM.
* @retval 1 Is boot from LDROM.
*/
int32_t FMC_GetBootSource (void)
{
int32_t ret = 0;
if (FMC->ISPCTL & FMC_ISPCTL_BS_Msk) {
ret = 1;
}
return ret;
}
/**
* @brief Enable FMC ISP function
* @return None
*/
void FMC_Open(void)
{
FMC->ISPCTL |= FMC_ISPCTL_ISPEN_Msk;
}
/**
* @brief Execute FMC_ISPCMD_READ command to read a word from flash.
* @param[in] u32Addr Address of the flash location to be read.
* It must be a word aligned address.
* @return The word data read from specified flash address.
*/
uint32_t FMC_Read(uint32_t u32Addr)
{
FMC->ISPCMD = FMC_ISPCMD_READ;
FMC->ISPADDR = u32Addr;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
return FMC->ISPDAT;
}
/**
* @brief Execute FMC_ISPCMD_READ_64 command to read a double-word from flash.
* @param[in] u32addr Address of the flash location to be read.
* It must be a double-word aligned address.
* @param[out] u32data0 Place holder of word 0 read from flash address u32addr.
* @param[out] u32data1 Place holder of word 0 read from flash address u32addr+4.
* @return 0 Success
* @return -1 Failed
*/
int32_t FMC_Read_64(uint32_t u32addr, uint32_t * u32data0, uint32_t * u32data1)
{
int32_t ret = 0;
FMC->ISPCMD = FMC_ISPCMD_READ_64;
FMC->ISPADDR = u32addr;
FMC->ISPDAT = 0x0UL;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { }
if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) {
FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
ret = -1;
} else {
*u32data0 = FMC->MPDAT0;
*u32data1 = FMC->MPDAT1;
}
return ret;
}
/**
* @brief Read company ID.
* @retval The company ID.
*/
uint32_t FMC_ReadCID(void)
{
FMC->ISPCMD = FMC_ISPCMD_READ_CID;
FMC->ISPADDR = 0x0UL;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
return FMC->ISPDAT;
}
/**
* @brief Read product ID.
* @retval The product ID.
*/
uint32_t FMC_ReadPID(void)
{
FMC->ISPCMD = FMC_ISPCMD_READ_PID;
FMC->ISPADDR = 0x04UL;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
return FMC->ISPDAT;
}
/**
* @brief This function reads one of the four UCID.
* @param[in] u32Index Index of the UCID to read. u32Index must be 0, 1, 2, or 3.
* @retval The UCID.
*/
uint32_t FMC_ReadUCID(uint32_t u32Index)
{
FMC->ISPCMD = FMC_ISPCMD_READ_UID;
FMC->ISPADDR = (0x04UL * u32Index) + 0x10UL;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
return FMC->ISPDAT;
}
/**
* @brief This function reads one of the three UID.
* @param[in] u32Index Index of the UID to read. u32Index must be 0, 1, or 2.
* @retval The UID.
*/
uint32_t FMC_ReadUID(uint32_t u32Index)
{
FMC->ISPCMD = FMC_ISPCMD_READ_UID;
FMC->ISPADDR = 0x04UL * u32Index;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
return FMC->ISPDAT;
}
/**
* @brief Get the base address of Data Flash if enabled.
* @retval The base address of Data Flash
*/
uint32_t FMC_ReadDataFlashBaseAddr(void)
{
return FMC->DFBA;
}
/**
* @brief This function will force re-map assigned flash page to CPU address 0x0.
* @param[in] u32PageAddr Address of the page to be mapped to CPU address 0x0.
* @return None
*/
void FMC_SetVectorPageAddr(uint32_t u32PageAddr)
{
FMC->ISPCMD = FMC_ISPCMD_VECMAP;
FMC->ISPADDR = u32PageAddr;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
}
/**
* @brief Execute ISP FMC_ISPCMD_PROGRAM to program a word to flash.
* @param[in] u32Addr Address of the flash location to be programmed.
* It must be a word aligned address.
* @param[in] u32Data The word data to be programmed.
* @return None
*/
void FMC_Write(uint32_t u32Addr, uint32_t u32Data)
{
FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
FMC->ISPADDR = u32Addr;
FMC->ISPDAT = u32Data;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
}
/**
* @brief Execute ISP FMC_ISPCMD_PROGRAM_64 to program a double-word to flash.
* @param[in] u32addr Address of the flash location to be programmed.
* It must be a double-word aligned address.
* @param[in] u32data0 The word data to be programmed to flash address u32addr.
* @param[in] u32data1 The word data to be programmed to flash address u32addr+4.
* @return 0 Success
* @return -1 Failed
*/
int32_t FMC_Write_64(uint32_t u32addr, uint32_t u32data0, uint32_t u32data1)
{
int32_t ret = 0;
FMC->ISPCMD = FMC_ISPCMD_PROGRAM_64;
FMC->ISPADDR = u32addr;
FMC->MPDAT0 = u32data0;
FMC->MPDAT1 = u32data1;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { }
if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) {
FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
ret = -1;
}
return ret;
}
/**
* @brief Program a 64-bits data to the specified OTP.
* @param[in] otp_num The OTP number.
* @param[in] low_word Low word of the 64-bits data.
* @param[in] high_word Low word of the 64-bits data.
* @retval 0 Success
* @retval -1 Program failed.
* @retval -2 Invalid OTP number.
*/
int32_t FMC_Write_OTP(uint32_t otp_num, uint32_t low_word, uint32_t high_word)
{
int32_t ret = 0;
if (otp_num > 255UL) {
ret = -2;
}
if (ret == 0) {
FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
FMC->ISPADDR = FMC_OTP_BASE + otp_num * 8UL;
FMC->ISPDAT = low_word;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) {
FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
ret = -1;
}
}
if (ret == 0) {
FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
FMC->ISPADDR = FMC_OTP_BASE + otp_num * 8UL + 4UL;
FMC->ISPDAT = high_word;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) {
FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
ret = -1;
}
}
return ret;
}
/**
* @brief Read the 64-bits data from the specified OTP.
* @param[in] otp_num The OTP number.
* @param[in] low_word Low word of the 64-bits data.
* @param[in] high_word Low word of the 64-bits data.
* @retval 0 Success
* @retval -1 Read failed.
* @retval -2 Invalid OTP number.
*/
int32_t FMC_Read_OTP(uint32_t otp_num, uint32_t *low_word, uint32_t *high_word)
{
int32_t ret = 0;
if (otp_num > 255UL) {
ret = -2;
}
if (ret == 0) {
FMC->ISPCMD = FMC_ISPCMD_READ_64;
FMC->ISPADDR = FMC_OTP_BASE + otp_num * 8UL ;
FMC->ISPDAT = 0x0UL;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { }
if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) {
FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
ret = -1;
} else {
*low_word = FMC->MPDAT0;
*high_word = FMC->MPDAT1;
}
}
return ret;
}
/**
* @brief Lock the specified OTP.
* @param[in] otp_num The OTP number.
* @retval 0 Success
* @retval -1 Failed to write OTP lock bits.
* @retval -2 Invalid OTP number.
*/
int32_t FMC_Lock_OTP(uint32_t otp_num)
{
int32_t ret = 0;
if (otp_num > 255UL) {
ret = -2;
}
if (ret == 0) {
FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
FMC->ISPADDR = FMC_OTP_BASE + 0x800UL + otp_num * 4UL;
FMC->ISPDAT = 0UL;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) {
FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
ret = -1;
}
}
return ret;
}
/**
* @brief Check the OTP is locked or not.
* @param[in] otp_num The OTP number.
* @retval 1 OTP is locked.
* @retval 0 OTP is not locked.
* @retval -1 Failed to read OTP lock bits.
* @retval -2 Invalid OTP number.
*/
int32_t FMC_Is_OTP_Locked(uint32_t otp_num)
{
int32_t ret = 0;
if (otp_num > 255UL) {
ret = -2;
}
if (ret == 0) {
FMC->ISPCMD = FMC_ISPCMD_READ;
FMC->ISPADDR = FMC_OTP_BASE + 0x800UL + otp_num * 4UL;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { }
if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) {
FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk;
ret = -1;
} else {
if (FMC->ISPDAT != 0xFFFFFFFFUL) {
ret = 1; /* Lock work was progrmmed. OTP was locked. */
}
}
}
return ret;
}
/**
* @brief Execute FMC_ISPCMD_READ command to read User Configuration.
* @param[out] u32Config A two-word array.
* u32Config[0] holds CONFIG0, while u32Config[1] holds CONFIG1.
* @param[in] u32Count Available word count in u32Config.
* @return Success or not.
* @retval 0 Success.
* @retval -1 Invalid parameter.
*/
int32_t FMC_ReadConfig(uint32_t u32Config[], uint32_t u32Count)
{
int32_t ret = 0;
u32Config[0] = FMC_Read(FMC_CONFIG_BASE);
if (u32Count < 2UL) {
ret = -1;
} else {
u32Config[1] = FMC_Read(FMC_CONFIG_BASE+4UL);
}
return ret;
}
/**
* @brief Execute ISP commands to erase then write User Configuration.
* @param[in] u32Config A two-word array.
* u32Config[0] holds CONFIG0, while u32Config[1] holds CONFIG1.
* @param[in] u32Count Always be 2 in this BSP.
* @return Success or not.
* @retval 0 Success.
* @retval -1 Invalid parameter.
*/
int32_t FMC_WriteConfig(uint32_t u32Config[], uint32_t u32Count)
{
FMC_ENABLE_CFG_UPDATE();
FMC_Erase(FMC_CONFIG_BASE);
FMC_Write(FMC_CONFIG_BASE, u32Config[0]);
FMC_Write(FMC_CONFIG_BASE+4UL, u32Config[1]);
FMC_DISABLE_CFG_UPDATE();
return 0;
}
/**
* @brief Run CRC32 checksum calculation and get result.
* @param[in] u32addr Starting flash address. It must be a page aligned address.
* @param[in] u32count Byte count of flash to be calculated. It must be multiple of 512 bytes.
* @return Success or not.
* @retval 0 Success.
* @retval 0xFFFFFFFF Invalid parameter.
*/
uint32_t FMC_GetChkSum(uint32_t u32addr, uint32_t u32count)
{
uint32_t ret;
if ((u32addr % 512UL) || (u32count % 512UL)) {
ret = 0xFFFFFFFF;
} else {
FMC->ISPCMD = FMC_ISPCMD_RUN_CKS;
FMC->ISPADDR = u32addr;
FMC->ISPDAT = u32count;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { }
FMC->ISPCMD = FMC_ISPCMD_READ_CKS;
FMC->ISPADDR = u32addr;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { }
ret = FMC->ISPDAT;
}
return ret;
}
/**
* @brief Run flash all one verification and get result.
* @param[in] u32addr Starting flash address. It must be a page aligned address.
* @param[in] u32count Byte count of flash to be calculated. It must be multiple of 512 bytes.
* @retval READ_ALLONE_YES The contents of verified flash area are 0xFFFFFFFF.
* @retval READ_ALLONE_NOT Some contents of verified flash area are not 0xFFFFFFFF.
* @retval READ_ALLONE_CMD_FAIL Unexpected error occurred.
*/
uint32_t FMC_CheckAllOne(uint32_t u32addr, uint32_t u32count)
{
uint32_t ret = READ_ALLONE_CMD_FAIL;
FMC->ISPSTS = 0x80UL; /* clear check all one bit */
FMC->ISPCMD = FMC_ISPCMD_RUN_ALL1;
FMC->ISPADDR = u32addr;
FMC->ISPDAT = u32count;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { }
do {
FMC->ISPCMD = FMC_ISPCMD_READ_ALL1;
FMC->ISPADDR = u32addr;
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { }
} while (FMC->ISPDAT == 0UL);
if (FMC->ISPDAT == READ_ALLONE_YES) {
ret = FMC->ISPDAT;
}
if (FMC->ISPDAT == READ_ALLONE_NOT) {
ret = FMC->ISPDAT;
}
return ret;
}
/**
* @brief Setup security key.
* @param[in] key Key 0~2 to be setup.
* @param[in] kpmax Maximum unmatched power-on counting number.
* @param[in] kemax Maximum unmatched counting number.
* @param[in] lock_CONFIG 1: Security key lock CONFIG to write-protect. 0: Don't lock CONFIG.
* @param[in] lock_SPROM 1: Security key lock SPROM to write-protect. 0: Don't lock SPROM.
* @retval 0 Success.
* @retval -1 Key is locked. Cannot overwrite the current key.
* @retval -2 Failed to erase flash.
* @retval -3 Failed to program key.
* @retval -4 Key lock function failed.
* @retval -5 CONFIG lock function failed.
* @retval -6 SPROM lock function failed.
* @retval -7 KPMAX function failed.
* @retval -8 KEMAX function failed.
*/
int32_t FMC_SKey_Setup(uint32_t key[3], uint32_t kpmax, uint32_t kemax,
const int32_t lock_CONFIG, const int32_t lock_SPROM)
{
uint32_t lock_ctrl = 0UL;
uint32_t u32KeySts;
int32_t ret = 0;
if (FMC->KPKEYSTS != 0x200UL) {
ret = -1;
}
if (FMC_Erase(FMC_KPROM_BASE)) {
ret = -2;
}
if (FMC_Erase(FMC_KPROM_BASE+0x200UL)) {
ret = -3;
}
if (!lock_CONFIG) {
lock_ctrl |= 0x1UL;
}
if (!lock_SPROM) {
lock_ctrl |= 0x2UL;
}
if (ret == 0) {
FMC_Write(FMC_KPROM_BASE, key[0]);
FMC_Write(FMC_KPROM_BASE+0x4UL, key[1]);
FMC_Write(FMC_KPROM_BASE+0x8UL, key[2]);
FMC_Write(FMC_KPROM_BASE+0xCUL, kpmax);
FMC_Write(FMC_KPROM_BASE+0x10UL, kemax);
FMC_Write(FMC_KPROM_BASE+0x14UL, lock_ctrl);
while (FMC->KPKEYSTS & FMC_KPKEYSTS_KEYBUSY_Msk) { }
u32KeySts = FMC->KPKEYSTS;
if (!(u32KeySts & FMC_KPKEYSTS_KEYLOCK_Msk)) {
/* Security key lock failed! */
ret = -4;
} else if ((lock_CONFIG && (!(u32KeySts & FMC_KPKEYSTS_CFGFLAG_Msk))) ||
((!lock_CONFIG) && (u32KeySts & FMC_KPKEYSTS_CFGFLAG_Msk))) {
/* CONFIG lock failed! */
ret = -5;
} else if ((lock_SPROM && (!(u32KeySts & FMC_KPKEYSTS_SPFLAG_Msk))) ||
((!lock_SPROM) && (u32KeySts & FMC_KPKEYSTS_SPFLAG_Msk))) {
/* CONFIG lock failed! */
ret = -6;
} else if (((FMC->KPCNT & FMC_KPCNT_KPMAX_Msk) >> FMC_KPCNT_KPMAX_Pos) != kpmax) {
/* KPMAX failed! */
ret = -7;
} else if (((FMC->KPKEYCNT & FMC_KPKEYCNT_KPKEMAX_Msk) >> FMC_KPKEYCNT_KPKEMAX_Pos) != kemax) {
/* KEMAX failed! */
ret = -8;
}
}
return ret;
}
/**
* @brief Execute security key comparison.
* @param[in] key Key 0~2 to be compared.
* @retval 0 Key matched.
* @retval -1 Forbidden. Times of key comparison mismatch reach the maximum count.
* @retval -2 Key mismatched.
* @retval -3 No security key lock. Key comparison is not required.
*/
int32_t FMC_SKey_Compare(uint32_t key[3])
{
uint32_t u32KeySts;
int32_t ret = 0;
if (FMC->KPKEYSTS & FMC_KPKEYSTS_FORBID_Msk) {
/* FMC_SKey_Compare - FORBID! */
ret = -1;
}
if (!(FMC->KPKEYSTS & FMC_KPKEYSTS_KEYLOCK_Msk)) {
/* FMC_SKey_Compare - key is not locked! */
ret = -3;
}
if (ret == 0) {
FMC->KPKEY0 = key[0];
FMC->KPKEY1 = key[1];
FMC->KPKEY2 = key[2];
FMC->KPKEYTRG = FMC_KPKEYTRG_KPKEYGO_Msk | FMC_KPKEYTRG_TCEN_Msk;
while (FMC->KPKEYSTS & FMC_KPKEYSTS_KEYBUSY_Msk) { }
u32KeySts = FMC->KPKEYSTS;
if (!(u32KeySts & FMC_KPKEYSTS_KEYMATCH_Msk)) {
/* Key mismatched! */
ret = -2;
} else if (u32KeySts & FMC_KPKEYSTS_KEYLOCK_Msk) {
/* Key matched, but still be locked! */
ret = -2;
}
}
return ret;
}
/*@}*/ /* end of group M480_FMC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_FMC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,159 @@
/**************************************************************************//**
* @file fmc.h
* @version V1.00
* @brief M480 Series Flash Memory Controller Driver Header File
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#ifndef __FMC_H__
#define __FMC_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_FMC_Driver FMC Driver
@{
*/
/** @addtogroup M480_FMC_EXPORTED_CONSTANTS FMC Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* Define Base Address */
/*---------------------------------------------------------------------------------------------------------*/
#define FMC_APROM_BASE 0x00000000UL /*!< APROM base address \hideinitializer */
#define FMC_APROM_END 0x00080000UL /*!< APROM end address \hideinitializer */
#define FMC_APROM_BANK0_END (FMC_APROM_END/2UL) /*!< APROM bank0 end address \hideinitializer */
#define FMC_LDROM_BASE 0x00100000UL /*!< LDROM base address \hideinitializer */
#define FMC_LDROM_END 0x00101000UL /*!< LDROM end address \hideinitializer */
#define FMC_SPROM_BASE 0x00200000UL /*!< SPROM base address \hideinitializer */
#define FMC_SPROM_END 0x00201000UL /*!< SPROM end address \hideinitializer */
#define FMC_CONFIG_BASE 0x00300000UL /*!< User Configuration address \hideinitializer */
#define FMC_USER_CONFIG_0 0x00300000UL /*!< User Config 0 address \hideinitializer */
#define FMC_USER_CONFIG_1 0x00300004UL /*!< User Config 1 address \hideinitializer */
#define FMC_USER_CONFIG_2 0x00300008UL /*!< User Config 2 address \hideinitializer */
#define FMC_KPROM_BASE 0x00301000UL /*!< Security ROM base address \hideinitializer */
#define FMC_OTP_BASE 0x00310000UL /*!< OTP flash base address \hideinitializer */
#define FMC_FLASH_PAGE_SIZE 0x1000UL /*!< Flash Page Size (4K bytes) \hideinitializer */
#define FMC_PAGE_ADDR_MASK 0xFFFFF000UL /*!< Flash page address mask \hideinitializer */
#define FMC_APROM_SIZE FMC_APROM_END /*!< APROM Size \hideinitializer */
#define FMC_BANK_SIZE (FMC_APROM_SIZE/2UL) /*!< APROM Bank Size \hideinitializer */
#define FMC_LDROM_SIZE 0x1000UL /*!< LDROM Size (4 Kbytes) \hideinitializer */
#define FMC_SPROM_SIZE 0x1000UL /*!< SPROM Size (4 Kbytes) \hideinitializer */
#define FMC_OTP_ENTRY_CNT 256UL /*!< OTP entry number \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* ISPCMD constant definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define FMC_ISPCMD_READ 0x00UL /*!< ISP Command: Read flash word \hideinitializer */
#define FMC_ISPCMD_READ_UID 0x04UL /*!< ISP Command: Read Unique ID \hideinitializer */
#define FMC_ISPCMD_READ_ALL1 0x08UL /*!< ISP Command: Read all-one result \hideinitializer */
#define FMC_ISPCMD_READ_CID 0x0BUL /*!< ISP Command: Read Company ID \hideinitializer */
#define FMC_ISPCMD_READ_PID 0x0CUL /*!< ISP Command: Read Product ID \hideinitializer */
#define FMC_ISPCMD_READ_CKS 0x0DUL /*!< ISP Command: Read checksum \hideinitializer */
#define FMC_ISPCMD_PROGRAM 0x21UL /*!< ISP Command: Write flash word \hideinitializer */
#define FMC_ISPCMD_PAGE_ERASE 0x22UL /*!< ISP Command: Page Erase Flash \hideinitializer */
#define FMC_ISPCMD_BANK_ERASE 0x23UL /*!< ISP Command: Erase Flash bank 0 or 1 \hideinitializer */
#define FMC_ISPCMD_BLOCK_ERASE 0x25UL /*!< ISP Command: Erase 4 pages alignment of APROM in bank 0 or 1 \hideinitializer */
#define FMC_ISPCMD_PROGRAM_MUL 0x27UL /*!< ISP Command: Multuple word program \hideinitializer */
#define FMC_ISPCMD_RUN_ALL1 0x28UL /*!< ISP Command: Run all-one verification \hideinitializer */
#define FMC_ISPCMD_RUN_CKS 0x2DUL /*!< ISP Command: Run checksum calculation \hideinitializer */
#define FMC_ISPCMD_VECMAP 0x2EUL /*!< ISP Command: Vector Page Remap \hideinitializer */
#define FMC_ISPCMD_READ_64 0x40UL /*!< ISP Command: Read double flash word \hideinitializer */
#define FMC_ISPCMD_PROGRAM_64 0x61UL /*!< ISP Command: Write double flash word \hideinitializer */
#define IS_BOOT_FROM_APROM 0UL /*!< Is booting from APROM \hideinitializer */
#define IS_BOOT_FROM_LDROM 1UL /*!< Is booting from LDROM \hideinitializer */
#define READ_ALLONE_YES 0xA11FFFFFUL /*!< Check-all-one result is all one. \hideinitializer */
#define READ_ALLONE_NOT 0xA1100000UL /*!< Check-all-one result is not all one. \hideinitializer */
#define READ_ALLONE_CMD_FAIL 0xFFFFFFFFUL /*!< Check-all-one command failed. \hideinitializer */
/*@}*/ /* end of group M480_FMC_EXPORTED_CONSTANTS */
/** @addtogroup M480_FMC_EXPORTED_FUNCTIONS FMC Exported Functions
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* Macros */
/*---------------------------------------------------------------------------------------------------------*/
#define FMC_SET_APROM_BOOT() (FMC->ISPCTL &= ~FMC_ISPCTL_BS_Msk) /*!< Select booting from APROM \hideinitializer */
#define FMC_SET_LDROM_BOOT() (FMC->ISPCTL |= FMC_ISPCTL_BS_Msk) /*!< Select booting from LDROM \hideinitializer */
#define FMC_ENABLE_AP_UPDATE() (FMC->ISPCTL |= FMC_ISPCTL_APUEN_Msk) /*!< Enable APROM update \hideinitializer */
#define FMC_DISABLE_AP_UPDATE() (FMC->ISPCTL &= ~FMC_ISPCTL_APUEN_Msk) /*!< Disable APROM update \hideinitializer */
#define FMC_ENABLE_CFG_UPDATE() (FMC->ISPCTL |= FMC_ISPCTL_CFGUEN_Msk) /*!< Enable User Config update \hideinitializer */
#define FMC_DISABLE_CFG_UPDATE() (FMC->ISPCTL &= ~FMC_ISPCTL_CFGUEN_Msk) /*!< Disable User Config update \hideinitializer */
#define FMC_ENABLE_LD_UPDATE() (FMC->ISPCTL |= FMC_ISPCTL_LDUEN_Msk) /*!< Enable LDROM update \hideinitializer */
#define FMC_DISABLE_LD_UPDATE() (FMC->ISPCTL &= ~FMC_ISPCTL_LDUEN_Msk) /*!< Disable LDROM update \hideinitializer */
#define FMC_ENABLE_SP_UPDATE() (FMC->ISPCTL |= FMC_ISPCTL_SPUEN_Msk) /*!< Enable SPROM update \hideinitializer */
#define FMC_DISABLE_SP_UPDATE() (FMC->ISPCTL &= ~FMC_ISPCTL_SPUEN_Msk) /*!< Disable SPROM update \hideinitializer */
#define FMC_DISABLE_ISP() (FMC->ISPCTL &= ~FMC_ISPCTL_ISPEN_Msk) /*!< Disable ISP function \hideinitializer */
#define FMC_ENABLE_ISP() (FMC->ISPCTL |= FMC_ISPCTL_ISPEN_Msk) /*!< Enable ISP function \hideinitializer */
#define FMC_GET_FAIL_FLAG() ((FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) ? 1UL : 0UL) /*!< Get ISP fail flag \hideinitializer */
#define FMC_CLR_FAIL_FLAG() (FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk) /*!< Clear ISP fail flag \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Functions */
/*---------------------------------------------------------------------------------------------------------*/
extern void FMC_Close(void);
extern int32_t FMC_Erase(uint32_t u32PageAddr);
extern int32_t FMC_Erase_SPROM(void);
extern int32_t FMC_Erase_Block(uint32_t u32BlockAddr);
extern int32_t FMC_Erase_Bank(uint32_t u32BankAddr);
extern int32_t FMC_GetBootSource(void);
extern void FMC_Open(void);
extern uint32_t FMC_Read(uint32_t u32Addr);
extern int32_t FMC_Read_64(uint32_t u32addr, uint32_t * u32data0, uint32_t * u32data1);
extern uint32_t FMC_ReadCID(void);
extern uint32_t FMC_ReadPID(void);
extern uint32_t FMC_ReadUCID(uint32_t u32Index);
extern uint32_t FMC_ReadUID(uint32_t u32Index);
extern uint32_t FMC_ReadDataFlashBaseAddr(void);
extern void FMC_SetVectorPageAddr(uint32_t u32PageAddr);
extern void FMC_Write(uint32_t u32Addr, uint32_t u32Data);
extern int32_t FMC_Write_64(uint32_t u32addr, uint32_t u32data0, uint32_t u32data1);
extern int32_t FMC_Write_OTP(uint32_t otp_num, uint32_t low_word, uint32_t high_word);
extern int32_t FMC_Read_OTP(uint32_t otp_num, uint32_t *low_word, uint32_t *high_word);
extern int32_t FMC_Lock_OTP(uint32_t otp_num);
extern int32_t FMC_Is_OTP_Locked(uint32_t otp_num);
extern int32_t FMC_ReadConfig(uint32_t u32Config[], uint32_t u32Count);
extern int32_t FMC_WriteConfig(uint32_t u32Config[], uint32_t u32Count);
extern uint32_t FMC_GetChkSum(uint32_t u32addr, uint32_t u32count);
extern uint32_t FMC_CheckAllOne(uint32_t u32addr, uint32_t u32count);
extern int32_t FMC_SKey_Setup(uint32_t key[3], uint32_t kpmax, uint32_t kemax, const int32_t lock_CONFIG, const int32_t lock_SPROM);
extern int32_t FMC_SKey_Compare(uint32_t key[3]);
/*@}*/ /* end of group M480_FMC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_FMC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __FMC_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,146 @@
/**************************************************************************//**
* @file gpio.c
* @version V3.00
* @brief M480 series GPIO driver source file
*
* @copyright (C) 2011~2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup GPIO_Driver GPIO Driver
@{
*/
/** @addtogroup GPIO_EXPORTED_FUNCTIONS GPIO Exported Functions
@{
*/
/**
* @brief Set GPIO operation mode
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32PinMask The single or multiple pins of specified GPIO port.
* It could be BIT0 ~ BIT15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be BIT0 ~ BIT13 for PE GPIO port.
* It could be BIT0 ~ BIT11 for PG GPIO port.
* @param[in] u32Mode Operation mode. It could be \n
* GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_OPEN_DRAIN, GPIO_MODE_QUASI.
*
* @return None
*
* @details This function is used to set specified GPIO operation mode.
*/
void GPIO_SetMode(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode)
{
uint32_t i;
for(i = 0ul; i < GPIO_PIN_MAX; i++) {
if((u32PinMask & (1ul << i))==(1ul << i)) {
port->MODE = (port->MODE & ~(0x3ul << (i << 1))) | (u32Mode << (i << 1));
}
}
}
/**
* @brief Enable GPIO interrupt
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32Pin The pin of specified GPIO port.
* It could be 0 ~ 15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be 0 ~ 13 for PE GPIO port.
* It could be 0 ~ 11 for PG GPIO port.
* @param[in] u32IntAttribs The interrupt attribute of specified GPIO pin. It could be \n
* GPIO_INT_RISING, GPIO_INT_FALLING, GPIO_INT_BOTH_EDGE, GPIO_INT_HIGH, GPIO_INT_LOW.
*
* @return None
*
* @details This function is used to enable specified GPIO pin interrupt.
*/
void GPIO_EnableInt(GPIO_T *port, uint32_t u32Pin, uint32_t u32IntAttribs)
{
port->INTTYPE |= (((u32IntAttribs >> 24) & 0xFFUL) << u32Pin);
port->INTEN |= ((u32IntAttribs & 0xFFFFFFUL) << u32Pin);
}
/**
* @brief Disable GPIO interrupt
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32Pin The pin of specified GPIO port.
* It could be 0 ~ 15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be 0 ~ 13 for PE GPIO port.
* It could be 0 ~ 11 for PG GPIO port.
*
* @return None
*
* @details This function is used to enable specified GPIO pin interrupt.
*/
void GPIO_DisableInt(GPIO_T *port, uint32_t u32Pin)
{
port->INTTYPE &= ~(1UL << u32Pin);
port->INTEN &= ~((0x00010001UL) << u32Pin);
}
/**
* @brief Set GPIO slew rate control
*
* @param[in] port GPIO port. It could be \ref PA, \ref PB, ... or \ref GPH
* @param[in] u32PinMask The single or multiple pins of specified GPIO port.
* @param[in] u32Mode Slew rate mode. \ref GPIO_SLEWCTL_NORMAL (maximum 40 MHz at 2.7V)
* \ref GPIO_SLEWCTL_HIGH (maximum 80 MHz at 2.7V)
* \ref GPIO_SLEWCTL_FAST (maximum 100 MHz at 2.7V)
*
* @return None
*
* @details This function is used to set specified GPIO operation mode.
*/
void GPIO_SetSlewCtl(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode)
{
uint32_t i;
for(i = 0ul; i < GPIO_PIN_MAX; i++) {
if(u32PinMask & (1ul << i)) {
port->SLEWCTL = (port->SLEWCTL & ~(0x3ul << (i << 1))) | (u32Mode << (i << 1));
}
}
}
/**
* @brief Set GPIO Pull-up and Pull-down control
*
* @param[in] port GPIO port. It could be \ref PA, \ref PB, ... or \ref GPH
* @param[in] u32PinMask The pin of specified GPIO port. It could be 0 ~ 15.
* @param[in] u32Mode The pin mode of specified GPIO pin. It could be
* \ref GPIO_PUSEL_DISABLE
* \ref GPIO_PUSEL_PULL_UP
* \ref GPIO_PUSEL_PULL_DOWN
*
* @return None
*
* @details Set the pin mode of specified GPIO pin.
*/
void GPIO_SetPullCtl(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode)
{
uint32_t i;
for(i = 0ul; i < GPIO_PIN_MAX; i++) {
if(u32PinMask & (1ul << i)) {
port->PUSEL = (port->PUSEL & ~(0x3ul << (i << 1))) | (u32Mode << (i << 1));
}
}
}
/*@}*/ /* end of group GPIO_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group GPIO_Driver */
/*@}*/ /* end of group Standard_Driver */
/*** (C) COPYRIGHT 2011~2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,496 @@
/**************************************************************************//**
* @file GPIO.h
* @version V3.00
* @brief M480 series GPIO driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#ifndef __GPIO_H__
#define __GPIO_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup GPIO_Driver GPIO Driver
@{
*/
/** @addtogroup GPIO_EXPORTED_CONSTANTS GPIO Exported Constants
@{
*/
#define GPIO_PIN_MAX 16UL /*!< Specify Maximum Pins of Each GPIO Port \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* GPIO_MODE Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define GPIO_MODE_INPUT 0x0UL /*!< Input Mode \hideinitializer */
#define GPIO_MODE_OUTPUT 0x1UL /*!< Output Mode \hideinitializer */
#define GPIO_MODE_OPEN_DRAIN 0x2UL /*!< Open-Drain Mode \hideinitializer */
#define GPIO_MODE_QUASI 0x3UL /*!< Quasi-bidirectional Mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* GPIO Interrupt Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define GPIO_INT_RISING 0x00010000UL /*!< Interrupt enable by Input Rising Edge \hideinitializer */
#define GPIO_INT_FALLING 0x00000001UL /*!< Interrupt enable by Input Falling Edge \hideinitializer */
#define GPIO_INT_BOTH_EDGE 0x00010001UL /*!< Interrupt enable by both Rising Edge and Falling Edge \hideinitializer */
#define GPIO_INT_HIGH 0x01010000UL /*!< Interrupt enable by Level-High \hideinitializer */
#define GPIO_INT_LOW 0x01000001UL /*!< Interrupt enable by Level-Level \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* GPIO_INTTYPE Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define GPIO_INTTYPE_EDGE 0UL /*!< GPIO_INTTYPE Setting for Edge Trigger Mode \hideinitializer */
#define GPIO_INTTYPE_LEVEL 1UL /*!< GPIO_INTTYPE Setting for Edge Level Mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* GPIO Slew Rate Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define GPIO_SLEWCTL_NORMAL 0x0UL /*!< GPIO slew setting for nornal Mode \hideinitializer */
#define GPIO_SLEWCTL_HIGH 0x1UL /*!< GPIO slew setting for high Mode \hideinitializer */
#define GPIO_SLEWCTL_FAST 0x2UL /*!< GPIO slew setting for fast Mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* GPIO Pull-up And Pull-down Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define GPIO_PUSEL_DISABLE 0x0UL /*!< GPIO PUSEL setting for Disable Mode \hideinitializer */
#define GPIO_PUSEL_PULL_UP 0x1UL /*!< GPIO PUSEL setting for Pull-up Mode \hideinitializer */
#define GPIO_PUSEL_PULL_DOWN 0x2UL /*!< GPIO PUSEL setting for Pull-down Mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* GPIO_DBCTL Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define GPIO_DBCTL_ICLK_ON 0x00000020UL /*!< GPIO_DBCTL setting for all IO pins edge detection circuit is always active after reset \hideinitializer */
#define GPIO_DBCTL_ICLK_OFF 0x00000000UL /*!< GPIO_DBCTL setting for edge detection circuit is active only if IO pin corresponding GPIOx_IEN bit is set to 1 \hideinitializer */
#define GPIO_DBCTL_DBCLKSRC_LIRC 0x00000010UL /*!< GPIO_DBCTL setting for de-bounce counter clock source is the internal 10 kHz \hideinitializer */
#define GPIO_DBCTL_DBCLKSRC_HCLK 0x00000000UL /*!< GPIO_DBCTL setting for de-bounce counter clock source is the HCLK \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_1 0x00000000UL /*!< GPIO_DBCTL setting for sampling cycle = 1 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_2 0x00000001UL /*!< GPIO_DBCTL setting for sampling cycle = 2 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_4 0x00000002UL /*!< GPIO_DBCTL setting for sampling cycle = 4 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_8 0x00000003UL /*!< GPIO_DBCTL setting for sampling cycle = 8 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_16 0x00000004UL /*!< GPIO_DBCTL setting for sampling cycle = 16 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_32 0x00000005UL /*!< GPIO_DBCTL setting for sampling cycle = 32 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_64 0x00000006UL /*!< GPIO_DBCTL setting for sampling cycle = 64 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_128 0x00000007UL /*!< GPIO_DBCTL setting for sampling cycle = 128 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_256 0x00000008UL /*!< GPIO_DBCTL setting for sampling cycle = 256 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_512 0x00000009UL /*!< GPIO_DBCTL setting for sampling cycle = 512 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_1024 0x0000000AUL /*!< GPIO_DBCTL setting for sampling cycle = 1024 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_2048 0x0000000BUL /*!< GPIO_DBCTL setting for sampling cycle = 2048 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_4096 0x0000000CUL /*!< GPIO_DBCTL setting for sampling cycle = 4096 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_8192 0x0000000DUL /*!< GPIO_DBCTL setting for sampling cycle = 8192 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_16384 0x0000000EUL /*!< GPIO_DBCTL setting for sampling cycle = 16384 clocks \hideinitializer */
#define GPIO_DBCTL_DBCLKSEL_32768 0x0000000FUL /*!< GPIO_DBCTL setting for sampling cycle = 32768 clocks \hideinitializer */
/* Define GPIO Pin Data Input/Output. It could be used to control each I/O pin by pin address mapping.
Example 1:
PA0 = 1;
It is used to set GPIO PA.0 to high;
Example 2:
if (PA0)
PA0 = 0;
If GPIO PA.0 pin status is high, then set GPIO PA.0 data output to low.
*/
#define GPIO_PIN_DATA(port, pin) (*((volatile uint32_t *)((GPIO_PIN_DATA_BASE+(0x40*(port))) + ((pin)<<2)))) /*!< Pin Data Input/Output \hideinitializer */
#define PA0 GPIO_PIN_DATA(0, 0 ) /*!< Specify PA.0 Pin Data Input/Output \hideinitializer */
#define PA1 GPIO_PIN_DATA(0, 1 ) /*!< Specify PA.1 Pin Data Input/Output \hideinitializer */
#define PA2 GPIO_PIN_DATA(0, 2 ) /*!< Specify PA.2 Pin Data Input/Output \hideinitializer */
#define PA3 GPIO_PIN_DATA(0, 3 ) /*!< Specify PA.3 Pin Data Input/Output \hideinitializer */
#define PA4 GPIO_PIN_DATA(0, 4 ) /*!< Specify PA.4 Pin Data Input/Output \hideinitializer */
#define PA5 GPIO_PIN_DATA(0, 5 ) /*!< Specify PA.5 Pin Data Input/Output \hideinitializer */
#define PA6 GPIO_PIN_DATA(0, 6 ) /*!< Specify PA.6 Pin Data Input/Output \hideinitializer */
#define PA7 GPIO_PIN_DATA(0, 7 ) /*!< Specify PA.7 Pin Data Input/Output \hideinitializer */
#define PA8 GPIO_PIN_DATA(0, 8 ) /*!< Specify PA.8 Pin Data Input/Output \hideinitializer */
#define PA9 GPIO_PIN_DATA(0, 9 ) /*!< Specify PA.9 Pin Data Input/Output \hideinitializer */
#define PA10 GPIO_PIN_DATA(0, 10) /*!< Specify PA.10 Pin Data Input/Output \hideinitializer */
#define PA11 GPIO_PIN_DATA(0, 11) /*!< Specify PA.11 Pin Data Input/Output \hideinitializer */
#define PA12 GPIO_PIN_DATA(0, 12) /*!< Specify PA.12 Pin Data Input/Output \hideinitializer */
#define PA13 GPIO_PIN_DATA(0, 13) /*!< Specify PA.13 Pin Data Input/Output \hideinitializer */
#define PA14 GPIO_PIN_DATA(0, 14) /*!< Specify PA.14 Pin Data Input/Output \hideinitializer */
#define PA15 GPIO_PIN_DATA(0, 15) /*!< Specify PA.15 Pin Data Input/Output \hideinitializer */
#define PB0 GPIO_PIN_DATA(1, 0 ) /*!< Specify PB.0 Pin Data Input/Output \hideinitializer */
#define PB1 GPIO_PIN_DATA(1, 1 ) /*!< Specify PB.1 Pin Data Input/Output \hideinitializer */
#define PB2 GPIO_PIN_DATA(1, 2 ) /*!< Specify PB.2 Pin Data Input/Output \hideinitializer */
#define PB3 GPIO_PIN_DATA(1, 3 ) /*!< Specify PB.3 Pin Data Input/Output \hideinitializer */
#define PB4 GPIO_PIN_DATA(1, 4 ) /*!< Specify PB.4 Pin Data Input/Output \hideinitializer */
#define PB5 GPIO_PIN_DATA(1, 5 ) /*!< Specify PB.5 Pin Data Input/Output \hideinitializer */
#define PB6 GPIO_PIN_DATA(1, 6 ) /*!< Specify PB.6 Pin Data Input/Output \hideinitializer */
#define PB7 GPIO_PIN_DATA(1, 7 ) /*!< Specify PB.7 Pin Data Input/Output \hideinitializer */
#define PB8 GPIO_PIN_DATA(1, 8 ) /*!< Specify PB.8 Pin Data Input/Output \hideinitializer */
#define PB9 GPIO_PIN_DATA(1, 9 ) /*!< Specify PB.9 Pin Data Input/Output \hideinitializer */
#define PB10 GPIO_PIN_DATA(1, 10) /*!< Specify PB.10 Pin Data Input/Output \hideinitializer */
#define PB11 GPIO_PIN_DATA(1, 11) /*!< Specify PB.11 Pin Data Input/Output \hideinitializer */
#define PB12 GPIO_PIN_DATA(1, 12) /*!< Specify PB.12 Pin Data Input/Output \hideinitializer */
#define PB13 GPIO_PIN_DATA(1, 13) /*!< Specify PB.13 Pin Data Input/Output \hideinitializer */
#define PB14 GPIO_PIN_DATA(1, 14) /*!< Specify PB.14 Pin Data Input/Output \hideinitializer */
#define PB15 GPIO_PIN_DATA(1, 15) /*!< Specify PB.15 Pin Data Input/Output \hideinitializer */
#define PC0 GPIO_PIN_DATA(2, 0 ) /*!< Specify PC.0 Pin Data Input/Output \hideinitializer */
#define PC1 GPIO_PIN_DATA(2, 1 ) /*!< Specify PC.1 Pin Data Input/Output \hideinitializer */
#define PC2 GPIO_PIN_DATA(2, 2 ) /*!< Specify PC.2 Pin Data Input/Output \hideinitializer */
#define PC3 GPIO_PIN_DATA(2, 3 ) /*!< Specify PC.3 Pin Data Input/Output \hideinitializer */
#define PC4 GPIO_PIN_DATA(2, 4 ) /*!< Specify PC.4 Pin Data Input/Output \hideinitializer */
#define PC5 GPIO_PIN_DATA(2, 5 ) /*!< Specify PC.5 Pin Data Input/Output \hideinitializer */
#define PC6 GPIO_PIN_DATA(2, 6 ) /*!< Specify PC.6 Pin Data Input/Output \hideinitializer */
#define PC7 GPIO_PIN_DATA(2, 7 ) /*!< Specify PC.7 Pin Data Input/Output \hideinitializer */
#define PC8 GPIO_PIN_DATA(2, 8 ) /*!< Specify PC.8 Pin Data Input/Output \hideinitializer */
#define PC9 GPIO_PIN_DATA(2, 9 ) /*!< Specify PC.9 Pin Data Input/Output \hideinitializer */
#define PC10 GPIO_PIN_DATA(2, 10) /*!< Specify PC.10 Pin Data Input/Output \hideinitializer */
#define PC11 GPIO_PIN_DATA(2, 11) /*!< Specify PC.11 Pin Data Input/Output \hideinitializer */
#define PC12 GPIO_PIN_DATA(2, 12) /*!< Specify PC.12 Pin Data Input/Output \hideinitializer */
#define PC13 GPIO_PIN_DATA(2, 13) /*!< Specify PC.13 Pin Data Input/Output \hideinitializer */
#define PC14 GPIO_PIN_DATA(2, 14) /*!< Specify PC.14 Pin Data Input/Output \hideinitializer */
#define PD0 GPIO_PIN_DATA(3, 0 ) /*!< Specify PD.0 Pin Data Input/Output \hideinitializer */
#define PD1 GPIO_PIN_DATA(3, 1 ) /*!< Specify PD.1 Pin Data Input/Output \hideinitializer */
#define PD2 GPIO_PIN_DATA(3, 2 ) /*!< Specify PD.2 Pin Data Input/Output \hideinitializer */
#define PD3 GPIO_PIN_DATA(3, 3 ) /*!< Specify PD.3 Pin Data Input/Output \hideinitializer */
#define PD4 GPIO_PIN_DATA(3, 4 ) /*!< Specify PD.4 Pin Data Input/Output \hideinitializer */
#define PD5 GPIO_PIN_DATA(3, 5 ) /*!< Specify PD.5 Pin Data Input/Output \hideinitializer */
#define PD6 GPIO_PIN_DATA(3, 6 ) /*!< Specify PD.6 Pin Data Input/Output \hideinitializer */
#define PD7 GPIO_PIN_DATA(3, 7 ) /*!< Specify PD.7 Pin Data Input/Output \hideinitializer */
#define PD8 GPIO_PIN_DATA(3, 8 ) /*!< Specify PD.8 Pin Data Input/Output \hideinitializer */
#define PD9 GPIO_PIN_DATA(3, 9 ) /*!< Specify PD.9 Pin Data Input/Output \hideinitializer */
#define PD10 GPIO_PIN_DATA(3, 10) /*!< Specify PD.10 Pin Data Input/Output \hideinitializer */
#define PD11 GPIO_PIN_DATA(3, 11) /*!< Specify PD.11 Pin Data Input/Output \hideinitializer */
#define PD12 GPIO_PIN_DATA(3, 12) /*!< Specify PD.12 Pin Data Input/Output \hideinitializer */
#define PD13 GPIO_PIN_DATA(3, 13) /*!< Specify PD.13 Pin Data Input/Output \hideinitializer */
#define PD14 GPIO_PIN_DATA(3, 14) /*!< Specify PD.14 Pin Data Input/Output \hideinitializer */
#define PE0 GPIO_PIN_DATA(4, 0 ) /*!< Specify PE.0 Pin Data Input/Output \hideinitializer */
#define PE1 GPIO_PIN_DATA(4, 1 ) /*!< Specify PE.1 Pin Data Input/Output \hideinitializer */
#define PE2 GPIO_PIN_DATA(4, 2 ) /*!< Specify PE.2 Pin Data Input/Output \hideinitializer */
#define PE3 GPIO_PIN_DATA(4, 3 ) /*!< Specify PE.3 Pin Data Input/Output \hideinitializer */
#define PE4 GPIO_PIN_DATA(4, 4 ) /*!< Specify PE.4 Pin Data Input/Output \hideinitializer */
#define PE5 GPIO_PIN_DATA(4, 5 ) /*!< Specify PE.5 Pin Data Input/Output \hideinitializer */
#define PE6 GPIO_PIN_DATA(4, 6 ) /*!< Specify PE.6 Pin Data Input/Output \hideinitializer */
#define PE7 GPIO_PIN_DATA(4, 7 ) /*!< Specify PE.7 Pin Data Input/Output \hideinitializer */
#define PE8 GPIO_PIN_DATA(4, 8 ) /*!< Specify PE.8 Pin Data Input/Output \hideinitializer */
#define PE9 GPIO_PIN_DATA(4, 9 ) /*!< Specify PE.9 Pin Data Input/Output \hideinitializer */
#define PE10 GPIO_PIN_DATA(4, 10) /*!< Specify PE.10 Pin Data Input/Output \hideinitializer */
#define PE11 GPIO_PIN_DATA(4, 11) /*!< Specify PE.11 Pin Data Input/Output \hideinitializer */
#define PE12 GPIO_PIN_DATA(4, 12) /*!< Specify PE.12 Pin Data Input/Output \hideinitializer */
#define PE13 GPIO_PIN_DATA(4, 13) /*!< Specify PE.13 Pin Data Input/Output \hideinitializer */
#define PE14 GPIO_PIN_DATA(4, 14) /*!< Specify PE.14 Pin Data Input/Output \hideinitializer */
#define PE15 GPIO_PIN_DATA(4, 15) /*!< Specify PE.15 Pin Data Input/Output \hideinitializer */
#define PF0 GPIO_PIN_DATA(5, 0 ) /*!< Specify PF.0 Pin Data Input/Output \hideinitializer */
#define PF1 GPIO_PIN_DATA(5, 1 ) /*!< Specify PF.1 Pin Data Input/Output \hideinitializer */
#define PF2 GPIO_PIN_DATA(5, 2 ) /*!< Specify PF.2 Pin Data Input/Output \hideinitializer */
#define PF3 GPIO_PIN_DATA(5, 3 ) /*!< Specify PF.3 Pin Data Input/Output \hideinitializer */
#define PF4 GPIO_PIN_DATA(5, 4 ) /*!< Specify PF.4 Pin Data Input/Output \hideinitializer */
#define PF5 GPIO_PIN_DATA(5, 5 ) /*!< Specify PF.5 Pin Data Input/Output \hideinitializer */
#define PF6 GPIO_PIN_DATA(5, 6 ) /*!< Specify PF.6 Pin Data Input/Output \hideinitializer */
#define PF7 GPIO_PIN_DATA(5, 7 ) /*!< Specify PF.7 Pin Data Input/Output \hideinitializer */
#define PF8 GPIO_PIN_DATA(5, 8 ) /*!< Specify PF.8 Pin Data Input/Output \hideinitializer */
#define PF9 GPIO_PIN_DATA(5, 9 ) /*!< Specify PF.9 Pin Data Input/Output \hideinitializer */
#define PF10 GPIO_PIN_DATA(5, 10) /*!< Specify PF.10 Pin Data Input/Output \hideinitializer */
#define PF11 GPIO_PIN_DATA(5, 11) /*!< Specify PF.11 Pin Data Input/Output \hideinitializer */
#define PG0 GPIO_PIN_DATA(6, 0 ) /*!< Specify PG.0 Pin Data Input/Output \hideinitializer */
#define PG1 GPIO_PIN_DATA(6, 1 ) /*!< Specify PG.1 Pin Data Input/Output \hideinitializer */
#define PG2 GPIO_PIN_DATA(6, 2 ) /*!< Specify PG.2 Pin Data Input/Output \hideinitializer */
#define PG3 GPIO_PIN_DATA(6, 3 ) /*!< Specify PG.3 Pin Data Input/Output \hideinitializer */
#define PG4 GPIO_PIN_DATA(6, 4 ) /*!< Specify PG.4 Pin Data Input/Output \hideinitializer */
#define PG5 GPIO_PIN_DATA(6, 5 ) /*!< Specify PG.5 Pin Data Input/Output \hideinitializer */
#define PG6 GPIO_PIN_DATA(6, 6 ) /*!< Specify PG.6 Pin Data Input/Output \hideinitializer */
#define PG7 GPIO_PIN_DATA(6, 7 ) /*!< Specify PG.7 Pin Data Input/Output \hideinitializer */
#define PG8 GPIO_PIN_DATA(6, 8 ) /*!< Specify PG.8 Pin Data Input/Output \hideinitializer */
#define PG9 GPIO_PIN_DATA(6, 9 ) /*!< Specify PG.9 Pin Data Input/Output \hideinitializer */
#define PG10 GPIO_PIN_DATA(6, 10) /*!< Specify PG.10 Pin Data Input/Output \hideinitializer */
#define PG11 GPIO_PIN_DATA(6, 11) /*!< Specify PG.11 Pin Data Input/Output \hideinitializer */
#define PG12 GPIO_PIN_DATA(6, 12) /*!< Specify PG.12 Pin Data Input/Output \hideinitializer */
#define PG13 GPIO_PIN_DATA(6, 13) /*!< Specify PG.13 Pin Data Input/Output \hideinitializer */
#define PG14 GPIO_PIN_DATA(6, 14) /*!< Specify PG.14 Pin Data Input/Output \hideinitializer */
#define PG15 GPIO_PIN_DATA(6, 15) /*!< Specify PG.15 Pin Data Input/Output \hideinitializer */
#define PH0 GPIO_PIN_DATA(7, 0 ) /*!< Specify PH.0 Pin Data Input/Output \hideinitializer */
#define PH1 GPIO_PIN_DATA(7, 1 ) /*!< Specify PH.1 Pin Data Input/Output \hideinitializer */
#define PH2 GPIO_PIN_DATA(7, 2 ) /*!< Specify PH.2 Pin Data Input/Output \hideinitializer */
#define PH3 GPIO_PIN_DATA(7, 3 ) /*!< Specify PH.3 Pin Data Input/Output \hideinitializer */
#define PH4 GPIO_PIN_DATA(7, 4 ) /*!< Specify PH.4 Pin Data Input/Output \hideinitializer */
#define PH5 GPIO_PIN_DATA(7, 5 ) /*!< Specify PH.5 Pin Data Input/Output \hideinitializer */
#define PH6 GPIO_PIN_DATA(7, 6 ) /*!< Specify PH.6 Pin Data Input/Output \hideinitializer */
#define PH7 GPIO_PIN_DATA(7, 7 ) /*!< Specify PH.7 Pin Data Input/Output \hideinitializer */
#define PH8 GPIO_PIN_DATA(7, 8 ) /*!< Specify PH.8 Pin Data Input/Output \hideinitializer */
#define PH9 GPIO_PIN_DATA(7, 9 ) /*!< Specify PH.9 Pin Data Input/Output \hideinitializer */
#define PH10 GPIO_PIN_DATA(7, 10) /*!< Specify PH.10 Pin Data Input/Output \hideinitializer */
#define PH11 GPIO_PIN_DATA(7, 11) /*!< Specify PH.11 Pin Data Input/Output \hideinitializer */
/*@}*/ /* end of group GPIO_EXPORTED_CONSTANTS */
/** @addtogroup GPIO_EXPORTED_FUNCTIONS GPIO Exported Functions
@{
*/
/**
* @brief Clear GPIO Pin Interrupt Flag
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32PinMask The single or multiple pins of specified GPIO port.
* It could be BIT0 ~ BIT15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be BIT0 ~ BIT13 for PE GPIO port.
* It could be BIT0 ~ BIT11 for PG GPIO port.
*
* @return None
*
* @details Clear the interrupt status of specified GPIO pin.
* \hideinitializer
*/
#define GPIO_CLR_INT_FLAG(port, u32PinMask) ((port)->INTSRC = (u32PinMask))
/**
* @brief Disable Pin De-bounce Function
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32PinMask The single or multiple pins of specified GPIO port.
* It could be BIT0 ~ BIT15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be BIT0 ~ BIT13 for PE GPIO port.
* It could be BIT0 ~ BIT11 for PG GPIO port.
*
* @return None
*
* @details Disable the interrupt de-bounce function of specified GPIO pin.
* \hideinitializer
*/
#define GPIO_DISABLE_DEBOUNCE(port, u32PinMask) ((port)->DBEN &= ~(u32PinMask))
/**
* @brief Enable Pin De-bounce Function
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32PinMask The single or multiple pins of specified GPIO port.
* It could be BIT0 ~ BIT15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be BIT0 ~ BIT13 for PE GPIO port.
* It could be BIT0 ~ BIT11 for PG GPIO port.
* @return None
*
* @details Enable the interrupt de-bounce function of specified GPIO pin.
* \hideinitializer
*/
#define GPIO_ENABLE_DEBOUNCE(port, u32PinMask) ((port)->DBEN |= (u32PinMask))
/**
* @brief Disable I/O Digital Input Path
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32PinMask The single or multiple pins of specified GPIO port.
* It could be BIT0 ~ BIT15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be BIT0 ~ BIT13 for PE GPIO port.
* It could be BIT0 ~ BIT11 for PG GPIO port.
*
* @return None
*
* @details Disable I/O digital input path of specified GPIO pin.
* \hideinitializer
*/
#define GPIO_DISABLE_DIGITAL_PATH(port, u32PinMask) ((port)->DINOFF |= ((u32PinMask)<<16))
/**
* @brief Enable I/O Digital Input Path
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32PinMask The single or multiple pins of specified GPIO port.
* It could be BIT0 ~ BIT15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be BIT0 ~ BIT13 for PE GPIO port.
* It could be BIT0 ~ BIT11 for PG GPIO port.
*
* @return None
*
* @details Enable I/O digital input path of specified GPIO pin.
* \hideinitializer
*/
#define GPIO_ENABLE_DIGITAL_PATH(port, u32PinMask) ((port)->DINOFF &= ~((u32PinMask)<<16))
/**
* @brief Disable I/O DOUT mask
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32PinMask The single or multiple pins of specified GPIO port.
* It could be BIT0 ~ BIT15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be BIT0 ~ BIT13 for PE GPIO port.
* It could be BIT0 ~ BIT11 for PG GPIO port.
*
* @return None
*
* @details Disable I/O DOUT mask of specified GPIO pin.
* \hideinitializer
*/
#define GPIO_DISABLE_DOUT_MASK(port, u32PinMask) ((port)->DATMSK &= ~(u32PinMask))
/**
* @brief Enable I/O DOUT mask
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32PinMask The single or multiple pins of specified GPIO port.
* It could be BIT0 ~ BIT15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be BIT0 ~ BIT13 for PE GPIO port.
* It could be BIT0 ~ BIT11 for PG GPIO port.
*
* @return None
*
* @details Enable I/O DOUT mask of specified GPIO pin.
* \hideinitializer
*/
#define GPIO_ENABLE_DOUT_MASK(port, u32PinMask) ((port)->DATMSK |= (u32PinMask))
/**
* @brief Get GPIO Pin Interrupt Flag
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32PinMask The single or multiple pins of specified GPIO port.
* It could be BIT0 ~ BIT15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be BIT0 ~ BIT13 for PE GPIO port.
* It could be BIT0 ~ BIT11 for PG GPIO port.
*
* @retval 0 No interrupt at specified GPIO pin
* @retval 1 The specified GPIO pin generate an interrupt
*
* @details Get the interrupt status of specified GPIO pin.
* \hideinitializer
*/
#define GPIO_GET_INT_FLAG(port, u32PinMask) ((port)->INTSRC & (u32PinMask))
/**
* @brief Set De-bounce Sampling Cycle Time
*
* @param[in] u32ClkSrc The de-bounce counter clock source. It could be GPIO_DBCTL_DBCLKSRC_HCLK or GPIO_DBCTL_DBCLKSRC_LIRC.
* @param[in] u32ClkSel The de-bounce sampling cycle selection. It could be
* - \ref GPIO_DBCTL_DBCLKSEL_1
* - \ref GPIO_DBCTL_DBCLKSEL_2
* - \ref GPIO_DBCTL_DBCLKSEL_4
* - \ref GPIO_DBCTL_DBCLKSEL_8
* - \ref GPIO_DBCTL_DBCLKSEL_16
* - \ref GPIO_DBCTL_DBCLKSEL_32
* - \ref GPIO_DBCTL_DBCLKSEL_64
* - \ref GPIO_DBCTL_DBCLKSEL_128
* - \ref GPIO_DBCTL_DBCLKSEL_256
* - \ref GPIO_DBCTL_DBCLKSEL_512
* - \ref GPIO_DBCTL_DBCLKSEL_1024
* - \ref GPIO_DBCTL_DBCLKSEL_2048
* - \ref GPIO_DBCTL_DBCLKSEL_4096
* - \ref GPIO_DBCTL_DBCLKSEL_8192
* - \ref GPIO_DBCTL_DBCLKSEL_16384
* - \ref GPIO_DBCTL_DBCLKSEL_32768
*
* @return None
*
* @details Set the interrupt de-bounce sampling cycle time based on the debounce counter clock source. \n
* Example: _GPIO_SET_DEBOUNCE_TIME(GPIO_DBCTL_DBCLKSRC_LIRC, GPIO_DBCTL_DBCLKSEL_4). \n
* It's meaning the De-debounce counter clock source is internal 10 KHz and sampling cycle selection is 4. \n
* Then the target de-bounce sampling cycle time is (4)*(1/(10*1000)) s = 4*0.0001 s = 400 us,
* and system will sampling interrupt input once per 00 us.
* \hideinitializer
*/
#define GPIO_SET_DEBOUNCE_TIME(u32ClkSrc, u32ClkSel) (GPIO->DBCTL = (GPIO_DBCTL_ICLKON_Msk | (u32ClkSrc) | (u32ClkSel)))
/**
* @brief Get GPIO Port IN Data
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
*
* @return The specified port data
*
* @details Get the PIN register of specified GPIO port.
* \hideinitializer
*/
#define GPIO_GET_IN_DATA(port) ((port)->PIN)
/**
* @brief Set GPIO Port OUT Data
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32Data GPIO port data.
*
* @return None
*
* @details Set the Data into specified GPIO port.
* \hideinitializer
*/
#define GPIO_SET_OUT_DATA(port, u32Data) ((port)->DOUT = (u32Data))
/**
* @brief Toggle Specified GPIO pin
*
* @param[in] u32Pin Pxy
*
* @return None
*
* @details Toggle the specified GPIO pint.
* \hideinitializer
*/
#define GPIO_TOGGLE(u32Pin) ((u32Pin) ^= 1)
/**
* @brief Enable External GPIO interrupt
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32Pin The pin of specified GPIO port.
* It could be 0 ~ 15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be 0 ~ 13 for PE GPIO port.
* It could be 0 ~ 11 for PG GPIO port.
* @param[in] u32IntAttribs The interrupt attribute of specified GPIO pin. It could be \n
* GPIO_INT_RISING, GPIO_INT_FALLING, GPIO_INT_BOTH_EDGE, GPIO_INT_HIGH, GPIO_INT_LOW.
*
* @return None
*
* @details This function is used to enable specified GPIO pin interrupt.
* \hideinitializer
*/
#define GPIO_EnableEINT GPIO_EnableInt
/**
* @brief Disable External GPIO interrupt
*
* @param[in] port GPIO port. It could be It could be PA, PB, PC, PD, PE, PF, PG or PH.
* @param[in] u32Pin The pin of specified GPIO port.
* It could be 0 ~ 15 for PA, PB, PC, PD, PF and PH GPIO port.
* It could be 0 ~ 13 for PE GPIO port.
* It could be 0 ~ 11 for PG GPIO port.
*
* @return None
*
* @details This function is used to enable specified GPIO pin interrupt.
* \hideinitializer
*/
#define GPIO_DisableEINT GPIO_DisableInt
void GPIO_SetMode(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode);
void GPIO_EnableInt(GPIO_T *port, uint32_t u32Pin, uint32_t u32IntAttribs);
void GPIO_DisableInt(GPIO_T *port, uint32_t u32Pin);
void GPIO_SetSlewCtl(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode);
void GPIO_SetPullCtl(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode);
/*@}*/ /* end of group GPIO_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group GPIO_Driver */
/*@}*/ /* end of group Standard_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __GPIO_H__ */
/*** (C) COPYRIGHT 2013~2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,268 @@
/**************************************************************************//**
* @file hsotg.h
* @version V0.10
* @brief M480 Series HSOTG Driver Header File
*
* @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#ifndef __HSOTG_H__
#define __HSOTG_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_HSOTG_Driver HSOTG Driver
@{
*/
/** @addtogroup M480_HSOTG_EXPORTED_CONSTANTS HSOTG Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* HSOTG constant definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define HSOTG_VBUS_EN_ACTIVE_HIGH (0UL) /*!< USB VBUS power switch enable signal is active high. \hideinitializer */
#define HSOTG_VBUS_EN_ACTIVE_LOW (1UL) /*!< USB VBUS power switch enable signal is active low. \hideinitializer */
#define HSOTG_VBUS_ST_VALID_HIGH (0UL) /*!< USB VBUS power switch valid status is high. \hideinitializer */
#define HSOTG_VBUS_ST_VALID_LOW (1UL) /*!< USB VBUS power switch valid status is low. \hideinitializer */
/*@}*/ /* end of group M480_HSOTG_EXPORTED_CONSTANTS */
/** @addtogroup M480_HSOTG_EXPORTED_FUNCTIONS HSOTG Exported Functions
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* Define Macros and functions */
/*---------------------------------------------------------------------------------------------------------*/
/**
* @brief This macro is used to enable HSOTG function
* @param None
* @return None
* @details This macro will set OTGEN bit of HSOTG_CTL register to enable HSOTG function.
* \hideinitializer
*/
#define HSOTG_ENABLE() (HSOTG->CTL |= HSOTG_CTL_OTGEN_Msk)
/**
* @brief This macro is used to disable HSOTG function
* @param None
* @return None
* @details This macro will clear OTGEN bit of HSOTG_CTL register to disable HSOTG function.
* \hideinitializer
*/
#define HSOTG_DISABLE() (HSOTG->CTL &= ~HSOTG_CTL_OTGEN_Msk)
/**
* @brief This macro is used to enable USB PHY
* @param None
* @return None
* @details When the USB role is selected as HSOTG device, use this macro to enable USB PHY.
* This macro will set OTGPHYEN bit of HSOTG_PHYCTL register to enable USB PHY.
* \hideinitializer
*/
#define HSOTG_ENABLE_PHY() (HSOTG->PHYCTL |= HSOTG_PHYCTL_OTGPHYEN_Msk)
/**
* @brief This macro is used to disable USB PHY
* @param None
* @return None
* @details This macro will clear OTGPHYEN bit of HSOTG_PHYCTL register to disable USB PHY.
* \hideinitializer
*/
#define HSOTG_DISABLE_PHY() (HSOTG->PHYCTL &= ~HSOTG_PHYCTL_OTGPHYEN_Msk)
/**
* @brief This macro is used to enable ID detection function
* @param None
* @return None
* @details This macro will set IDDETEN bit of HSOTG_PHYCTL register to enable ID detection function.
* \hideinitializer
*/
#define HSOTG_ENABLE_ID_DETECT() (HSOTG->PHYCTL |= HSOTG_PHYCTL_IDDETEN_Msk)
/**
* @brief This macro is used to disable ID detection function
* @param None
* @return None
* @details This macro will clear IDDETEN bit of HSOTG_PHYCTL register to disable ID detection function.
* \hideinitializer
*/
#define HSOTG_DISABLE_ID_DETECT() (HSOTG->PHYCTL &= ~HSOTG_PHYCTL_IDDETEN_Msk)
/**
* @brief This macro is used to enable HSOTG wake-up function
* @param None
* @return None
* @details This macro will set WKEN bit of HSOTG_CTL register to enable HSOTG wake-up function.
* \hideinitializer
*/
#define HSOTG_ENABLE_WAKEUP() (HSOTG->CTL |= HSOTG_CTL_WKEN_Msk)
/**
* @brief This macro is used to disable HSOTG wake-up function
* @param None
* @return None
* @details This macro will clear WKEN bit of HSOTG_CTL register to disable HSOTG wake-up function.
* \hideinitializer
*/
#define HSOTG_DISABLE_WAKEUP() (HSOTG->CTL &= ~HSOTG_CTL_WKEN_Msk)
/**
* @brief This macro is used to set the polarity of USB_VBUS_EN pin
* @param[in] u32Pol The polarity selection. Valid values are listed below.
* - \ref HSOTG_VBUS_EN_ACTIVE_HIGH
* - \ref HSOTG_VBUS_EN_ACTIVE_LOW
* @return None
* @details This macro is used to set the polarity of external USB VBUS power switch enable signal.
* \hideinitializer
*/
#define HSOTG_SET_VBUS_EN_POL(u32Pol) (HSOTG->PHYCTL = (HSOTG->PHYCTL & (~HSOTG_PHYCTL_VBENPOL_Msk)) | ((u32Pol)<<HSOTG_PHYCTL_VBENPOL_Pos))
/**
* @brief This macro is used to set the polarity of USB_VBUS_ST pin
* @param[in] u32Pol The polarity selection. Valid values are listed below.
* - \ref HSOTG_VBUS_ST_VALID_HIGH
* - \ref HSOTG_VBUS_ST_VALID_LOW
* @return None
* @details This macro is used to set the polarity of external USB VBUS power switch status signal.
* \hideinitializer
*/
#define HSOTG_SET_VBUS_STS_POL(u32Pol) (HSOTG->PHYCTL = (HSOTG->PHYCTL & (~HSOTG_PHYCTL_VBSTSPOL_Msk)) | ((u32Pol)<<HSOTG_PHYCTL_VBSTSPOL_Pos))
/**
* @brief This macro is used to enable HSOTG related interrupts
* @param[in] u32Mask The combination of interrupt source. Each bit corresponds to a interrupt source. Valid values are listed below.
* - \ref HSOTG_INTEN_ROLECHGIEN_Msk
* - \ref HSOTG_INTEN_VBEIEN_Msk
* - \ref HSOTG_INTEN_SRPFIEN_Msk
* - \ref HSOTG_INTEN_HNPFIEN_Msk
* - \ref HSOTG_INTEN_GOIDLEIEN_Msk
* - \ref HSOTG_INTEN_IDCHGIEN_Msk
* - \ref HSOTG_INTEN_PDEVIEN_Msk
* - \ref HSOTG_INTEN_HOSTIEN_Msk
* - \ref HSOTG_INTEN_BVLDCHGIEN_Msk
* - \ref HSOTG_INTEN_AVLDCHGIEN_Msk
* - \ref HSOTG_INTEN_VBCHGIEN_Msk
* - \ref HSOTG_INTEN_SECHGIEN_Msk
* - \ref HSOTG_INTEN_SRPDETIEN_Msk
* @return None
* @details This macro will enable HSOTG related interrupts specified by u32Mask parameter.
* \hideinitializer
*/
#define HSOTG_ENABLE_INT(u32Mask) (HSOTG->INTEN |= (u32Mask))
/**
* @brief This macro is used to disable HSOTG related interrupts
* @param[in] u32Mask The combination of interrupt source. Each bit corresponds to a interrupt source. Valid values are listed below.
* - \ref HSOTG_INTEN_ROLECHGIEN_Msk
* - \ref HSOTG_INTEN_VBEIEN_Msk
* - \ref HSOTG_INTEN_SRPFIEN_Msk
* - \ref HSOTG_INTEN_HNPFIEN_Msk
* - \ref HSOTG_INTEN_GOIDLEIEN_Msk
* - \ref HSOTG_INTEN_IDCHGIEN_Msk
* - \ref HSOTG_INTEN_PDEVIEN_Msk
* - \ref HSOTG_INTEN_HOSTIEN_Msk
* - \ref HSOTG_INTEN_BVLDCHGIEN_Msk
* - \ref HSOTG_INTEN_AVLDCHGIEN_Msk
* - \ref HSOTG_INTEN_VBCHGIEN_Msk
* - \ref HSOTG_INTEN_SECHGIEN_Msk
* - \ref HSOTG_INTEN_SRPDETIEN_Msk
* @return None
* @details This macro will disable HSOTG related interrupts specified by u32Mask parameter.
* \hideinitializer
*/
#define HSOTG_DISABLE_INT(u32Mask) (HSOTG->INTEN &= ~(u32Mask))
/**
* @brief This macro is used to get HSOTG related interrupt flags
* @param[in] u32Mask The combination of interrupt source. Each bit corresponds to a interrupt source. Valid values are listed below.
* - \ref HSOTG_INTSTS_ROLECHGIF_Msk
* - \ref HSOTG_INTSTS_VBEIF_Msk
* - \ref HSOTG_INTSTS_SRPFIF_Msk
* - \ref HSOTG_INTSTS_HNPFIF_Msk
* - \ref HSOTG_INTSTS_GOIDLEIF_Msk
* - \ref HSOTG_INTSTS_IDCHGIF_Msk
* - \ref HSOTG_INTSTS_PDEVIF_Msk
* - \ref HSOTG_INTSTS_HOSTIF_Msk
* - \ref HSOTG_INTSTS_BVLDCHGIF_Msk
* - \ref HSOTG_INTSTS_AVLDCHGIF_Msk
* - \ref HSOTG_INTSTS_VBCHGIF_Msk
* - \ref HSOTG_INTSTS_SECHGIF_Msk
* - \ref HSOTG_INTSTS_SRPDETIF_Msk
* @return Interrupt flags of selected sources.
* @details This macro will return HSOTG related interrupt flags specified by u32Mask parameter.
* \hideinitializer
*/
#define HSOTG_GET_INT_FLAG(u32Mask) (HSOTG->INTSTS & (u32Mask))
/**
* @brief This macro is used to clear HSOTG related interrupt flags
* @param[in] u32Mask The combination of interrupt source. Each bit corresponds to a interrupt source. Valid values are listed below.
* - \ref HSOTG_INTSTS_ROLECHGIF_Msk
* - \ref HSOTG_INTSTS_VBEIF_Msk
* - \ref HSOTG_INTSTS_SRPFIF_Msk
* - \ref HSOTG_INTSTS_HNPFIF_Msk
* - \ref HSOTG_INTSTS_GOIDLEIF_Msk
* - \ref HSOTG_INTSTS_IDCHGIF_Msk
* - \ref HSOTG_INTSTS_PDEVIF_Msk
* - \ref HSOTG_INTSTS_HOSTIF_Msk
* - \ref HSOTG_INTSTS_BVLDCHGIF_Msk
* - \ref HSOTG_INTSTS_AVLDCHGIF_Msk
* - \ref HSOTG_INTSTS_VBCHGIF_Msk
* - \ref HSOTG_INTSTS_SECHGIF_Msk
* - \ref HSOTG_INTSTS_SRPDETIF_Msk
* @return None
* @details This macro will clear HSOTG related interrupt flags specified by u32Mask parameter.
* \hideinitializer
*/
#define HSOTG_CLR_INT_FLAG(u32Mask) (HSOTG->INTSTS = (u32Mask))
/**
* @brief This macro is used to get HSOTG related status
* @param[in] u32Mask The combination of user specified source. Valid values are listed below.
* - \ref HSOTG_STATUS_OVERCUR_Msk
* - \ref HSOTG_STATUS_IDSTS_Msk
* - \ref HSOTG_STATUS_SESSEND_Msk
* - \ref HSOTG_STATUS_BVLD_Msk
* - \ref HSOTG_STATUS_AVLD_Msk
* - \ref HSOTG_STATUS_VBUSVLD_Msk
* @return The user specified status.
* @details This macro will return HSOTG related status specified by u32Mask parameter.
* \hideinitializer
*/
#define HSOTG_GET_STATUS(u32Mask) (HSOTG->STATUS & (u32Mask))
/*@}*/ /* end of group M480_HSOTG_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_HSOTG_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __HSOTG_H__ */
/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,621 @@
/**************************************************************************//**
* @file hsusbd.c
* @version V1.00
* @brief M480 HSUSBD driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_HSUSBD_Driver HSUSBD Driver
@{
*/
/** @addtogroup M480_HSUSBD_EXPORTED_FUNCTIONS HSUSBD Exported Functions
@{
*/
/*--------------------------------------------------------------------------*/
/** @cond HIDDEN_SYMBOLS */
/* Global variables for Control Pipe */
S_HSUSBD_CMD_T gUsbCmd;
S_HSUSBD_INFO_T *g_hsusbd_sInfo;
HSUSBD_VENDOR_REQ g_hsusbd_pfnVendorRequest = NULL;
HSUSBD_CLASS_REQ g_hsusbd_pfnClassRequest = NULL;
HSUSBD_SET_INTERFACE_REQ g_hsusbd_pfnSetInterface = NULL;
uint32_t g_u32HsEpStallLock = 0ul; /* Bit map flag to lock specified EP when SET_FEATURE */
static uint8_t *g_hsusbd_CtrlInPointer = 0;
static uint32_t g_hsusbd_CtrlMaxPktSize = 64ul;
static uint8_t g_hsusbd_UsbConfig = 0ul;
static uint8_t g_hsusbd_UsbAltInterface = 0ul;
static uint8_t g_hsusbd_EnableTestMode = 0ul;
static uint8_t g_hsusbd_TestSelector = 0ul;
#ifdef __ICCARM__
#pragma data_alignment=4
static uint8_t g_hsusbd_buf[12];
#elif defined (__CC_ARM)
__align(4) static uint8_t g_hsusbd_buf[12];
#elif defined ( __GNUC__ )
static uint8_t g_hsusbd_buf[12] __attribute__((aligned (4)));
#endif
uint8_t g_hsusbd_Configured = 0ul;
uint8_t g_hsusbd_CtrlZero = 0ul;
uint8_t g_hsusbd_UsbAddr = 0ul;
uint8_t g_hsusbd_ShortPacket = 0ul;
uint32_t volatile g_hsusbd_DmaDone = 0ul;
uint32_t g_hsusbd_CtrlInSize = 0ul;
/** @endcond HIDDEN_SYMBOLS */
/**
* @brief HSUSBD Initial
*
* @param[in] param Descriptor
* @param[in] pfnClassReq Class Request Callback Function
* @param[in] pfnSetInterface SetInterface Request Callback Function
*
* @return None
*
* @details This function is used to initial HSUSBD.
*/
void HSUSBD_Open(S_HSUSBD_INFO_T *param, HSUSBD_CLASS_REQ pfnClassReq, HSUSBD_SET_INTERFACE_REQ pfnSetInterface)
{
g_hsusbd_sInfo = param;
g_hsusbd_pfnClassRequest = pfnClassReq;
g_hsusbd_pfnSetInterface = pfnSetInterface;
/* get EP0 maximum packet size */
g_hsusbd_CtrlMaxPktSize = g_hsusbd_sInfo->gu8DevDesc[7];
/* Initial USB engine */
/* Enable PHY */
HSUSBD_ENABLE_PHY();
/* wait PHY clock ready */
while (1) {
HSUSBD->EP[EPA].EPMPS = 0x20ul;
if (HSUSBD->EP[EPA].EPMPS == 0x20ul) {
break;
}
}
/* Force SE0, and then clear it to connect*/
HSUSBD_SET_SE0();
}
/**
* @brief HSUSBD Start
*
* @param[in] None
*
* @return None
*
* @details This function is used to start transfer
*/
void HSUSBD_Start(void)
{
HSUSBD_CLR_SE0();
}
/**
* @brief Process Setup Packet
*
* @param[in] None
*
* @return None
*
* @details This function is used to process Setup packet.
*/
void HSUSBD_ProcessSetupPacket(void)
{
/* Setup packet process */
gUsbCmd.bmRequestType = (uint8_t)(HSUSBD->SETUP1_0 & 0xfful);
gUsbCmd.bRequest = (uint8_t)((HSUSBD->SETUP1_0 >> 8) & 0xfful);
gUsbCmd.wValue = (uint16_t)HSUSBD->SETUP3_2;
gUsbCmd.wIndex = (uint16_t)HSUSBD->SETUP5_4;
gUsbCmd.wLength = (uint16_t)HSUSBD->SETUP7_6;
/* USB device request in setup packet: offset 0, D[6..5]: 0=Standard, 1=Class, 2=Vendor, 3=Reserved */
switch (gUsbCmd.bmRequestType & 0x60ul) {
case REQ_STANDARD: {
HSUSBD_StandardRequest();
break;
}
case REQ_CLASS: {
if (g_hsusbd_pfnClassRequest != NULL) {
g_hsusbd_pfnClassRequest();
}
break;
}
case REQ_VENDOR: {
if (g_hsusbd_pfnVendorRequest != NULL) {
g_hsusbd_pfnVendorRequest();
}
break;
}
default: {
/* Setup error, stall the device */
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
break;
}
}
}
/**
* @brief Get Descriptor request
*
* @param[in] None
*
* @return None
*
* @details This function is used to process GetDescriptor request.
*/
int HSUSBD_GetDescriptor(void)
{
uint32_t u32Len;
int val = 0;
u32Len = gUsbCmd.wLength;
g_hsusbd_CtrlZero = (uint8_t)0ul;
switch ((gUsbCmd.wValue & 0xff00ul) >> 8) {
/* Get Device Descriptor */
case DESC_DEVICE: {
u32Len = Minimum(u32Len, LEN_DEVICE);
HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8DevDesc, u32Len);
break;
}
/* Get Configuration Descriptor */
case DESC_CONFIG: {
uint32_t u32TotalLen;
if ((HSUSBD->OPER & 0x04ul) == 0x04ul) {
u32TotalLen = g_hsusbd_sInfo->gu8ConfigDesc[3];
u32TotalLen = g_hsusbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8);
u32Len = Minimum(u32Len, u32TotalLen);
if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul) {
g_hsusbd_CtrlZero = (uint8_t)1ul;
}
HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8ConfigDesc, u32Len);
} else {
u32TotalLen = g_hsusbd_sInfo->gu8FullConfigDesc[3];
u32TotalLen = g_hsusbd_sInfo->gu8FullConfigDesc[2] + (u32TotalLen << 8);
u32Len = Minimum(u32Len, u32TotalLen);
if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul) {
g_hsusbd_CtrlZero = (uint8_t)1ul;
}
HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8FullConfigDesc, u32Len);
}
break;
}
/* Get Qualifier Descriptor */
case DESC_QUALIFIER: {
u32Len = Minimum(u32Len, LEN_QUALIFIER);
HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8QualDesc, u32Len);
break;
}
/* Get Other Speed Descriptor - Full speed */
case DESC_OTHERSPEED: {
uint32_t u32TotalLen;
if ((HSUSBD->OPER & 0x04ul) == 0x04ul) {
u32TotalLen = g_hsusbd_sInfo->gu8HSOtherConfigDesc[3];
u32TotalLen = g_hsusbd_sInfo->gu8HSOtherConfigDesc[2] + (u32TotalLen << 8);
u32Len = Minimum(u32Len, u32TotalLen);
if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul) {
g_hsusbd_CtrlZero = (uint8_t)1ul;
}
HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8HSOtherConfigDesc, u32Len);
} else {
u32TotalLen = g_hsusbd_sInfo->gu8FSOtherConfigDesc[3];
u32TotalLen = g_hsusbd_sInfo->gu8FSOtherConfigDesc[2] + (u32TotalLen << 8);
u32Len = Minimum(u32Len, u32TotalLen);
if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul) {
g_hsusbd_CtrlZero = (uint8_t)1ul;
}
HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8FSOtherConfigDesc, u32Len);
}
break;
}
/* Get HID Descriptor */
case DESC_HID: {
u32Len = Minimum(u32Len, LEN_HID);
HSUSBD_MemCopy(g_hsusbd_buf, &g_hsusbd_sInfo->gu8ConfigDesc[LEN_CONFIG+LEN_INTERFACE], u32Len);
HSUSBD_PrepareCtrlIn(g_hsusbd_buf, u32Len);
break;
}
/* Get Report Descriptor */
case DESC_HID_RPT: {
if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul) {
g_hsusbd_CtrlZero = (uint8_t)1ul;
}
if ((HSUSBD->OPER & 0x04ul) == 0x04ul) {
u32Len = Minimum(u32Len, g_hsusbd_sInfo->gu32HidReportSize[gUsbCmd.wIndex & 0xfful]);
HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8HidReportDesc[gUsbCmd.wIndex & 0xfful], u32Len);
} else {
u32Len = Minimum(u32Len, g_hsusbd_sInfo->gu32FSHidReportSize[gUsbCmd.wIndex & 0xfful]);
HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8FSHidReportDesc[gUsbCmd.wIndex & 0xfful], u32Len);
}
break;
}
/* Get String Descriptor */
case DESC_STRING: {
if((gUsbCmd.wValue & 0xfful) < 8ul) {
u32Len = Minimum(u32Len, g_hsusbd_sInfo->gu8StringDesc[gUsbCmd.wValue & 0xfful][0]);
if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul) {
g_hsusbd_CtrlZero = (uint8_t)1ul;
}
HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8StringDesc[gUsbCmd.wValue & 0xfful], u32Len);
} else {
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
val = 1;
}
break;
}
default:
/* Not support. Reply STALL. */
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
val = 1;
break;
}
return val;
}
/**
* @brief Process USB standard request
*
* @param[in] None
*
* @return None
*
* @details This function is used to process USB Standard Request.
*/
void HSUSBD_StandardRequest(void)
{
/* clear global variables for new request */
g_hsusbd_CtrlInPointer = 0;
g_hsusbd_CtrlInSize = 0ul;
if ((gUsbCmd.bmRequestType & 0x80ul) == 0x80ul) { /* request data transfer direction */
/* Device to host */
switch (gUsbCmd.bRequest) {
case GET_CONFIGURATION: {
/* Return current configuration setting */
HSUSBD_PrepareCtrlIn((uint8_t *)&g_hsusbd_UsbConfig, 1ul);
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk);
break;
}
case GET_DESCRIPTOR: {
if (!HSUSBD_GetDescriptor()) {
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk);
}
break;
}
case GET_INTERFACE: {
/* Return current interface setting */
HSUSBD_PrepareCtrlIn((uint8_t *)&g_hsusbd_UsbAltInterface, 1ul);
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk);
break;
}
case GET_STATUS: {
/* Device */
if (gUsbCmd.bmRequestType == 0x80ul) {
if ((g_hsusbd_sInfo->gu8ConfigDesc[7] & 0x40ul) == 0x40ul) {
g_hsusbd_buf[0] = (uint8_t)1ul; /* Self-Powered */
} else {
g_hsusbd_buf[0] = (uint8_t)0ul; /* bus-Powered */
}
}
/* Interface */
else if (gUsbCmd.bmRequestType == 0x81ul) {
g_hsusbd_buf[0] = (uint8_t)0ul;
}
/* Endpoint */
else if (gUsbCmd.bmRequestType == 0x82ul) {
uint8_t ep = (uint8_t)(gUsbCmd.wIndex & 0xFul);
g_hsusbd_buf[0] = (uint8_t)HSUSBD_GetStall((uint32_t)ep)? (uint8_t)1 : (uint8_t)0;
}
g_hsusbd_buf[1] = (uint8_t)0ul;
HSUSBD_PrepareCtrlIn(g_hsusbd_buf, 2ul);
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk);
break;
}
default: {
/* Setup error, stall the device */
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
break;
}
}
} else {
/* Host to device */
switch (gUsbCmd.bRequest) {
case CLEAR_FEATURE: {
if((gUsbCmd.wValue & 0xfful) == FEATURE_ENDPOINT_HALT) {
uint32_t epNum, i;
/* EP number stall is not allow to be clear in MSC class "Error Recovery Test".
a flag: g_u32HsEpStallLock is added to support it */
epNum = (uint32_t)(gUsbCmd.wIndex & 0xFul);
for (i=0ul; i<HSUSBD_MAX_EP; i++) {
if ((((HSUSBD->EP[i].EPCFG & 0xf0ul) >> 4) == epNum) && ((g_u32HsEpStallLock & (1ul << i)) == 0ul)) {
HSUSBD->EP[i].EPRSPCTL = (HSUSBD->EP[i].EPRSPCTL & 0xeful) | HSUSBD_EP_RSPCTL_TOGGLE;
}
}
}
/* Status stage */
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
break;
}
case SET_ADDRESS: {
g_hsusbd_UsbAddr = (uint8_t)gUsbCmd.wValue;
/* Status Stage */
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
break;
}
case SET_CONFIGURATION: {
g_hsusbd_UsbConfig = (uint8_t)gUsbCmd.wValue;
g_hsusbd_Configured = (uint8_t)1ul;
/* Status stage */
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
break;
}
case SET_FEATURE: {
if ((gUsbCmd.wValue & 0x3ul) == 2ul) { /* TEST_MODE */
g_hsusbd_EnableTestMode = (uint8_t)1ul;
g_hsusbd_TestSelector = (uint8_t)(gUsbCmd.wIndex >> 8);
}
if ((gUsbCmd.wValue & 0x3ul) == 3ul) { /* HNP ebable */
HSOTG->CTL |= (HSOTG_CTL_HNPREQEN_Msk | HSOTG_CTL_BUSREQ_Msk);
}
/* Status stage */
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
break;
}
case SET_INTERFACE: {
g_hsusbd_UsbAltInterface = (uint8_t)gUsbCmd.wValue;
if (g_hsusbd_pfnSetInterface != NULL) {
g_hsusbd_pfnSetInterface((uint32_t)g_hsusbd_UsbAltInterface);
}
/* Status stage */
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
break;
}
default: {
/* Setup error, stall the device */
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
break;
}
}
}
}
/**
* @brief Update Device State
*
* @param[in] None
*
* @return None
*
* @details This function is used to update Device state when Setup packet complete
*/
/** @cond HIDDEN_SYMBOLS */
#define TEST_J 0x01ul
#define TEST_K 0x02ul
#define TEST_SE0_NAK 0x03ul
#define TEST_PACKET 0x04ul
#define TEST_FORCE_ENABLE 0x05ul
/** @endcond HIDDEN_SYMBOLS */
void HSUSBD_UpdateDeviceState(void)
{
switch (gUsbCmd.bRequest) {
case SET_ADDRESS: {
HSUSBD_SET_ADDR(g_hsusbd_UsbAddr);
break;
}
case SET_CONFIGURATION: {
if (g_hsusbd_UsbConfig == 0ul) {
uint32_t volatile i;
/* Reset PID DATA0 */
for (i=0ul; i<HSUSBD_MAX_EP; i++) {
if ((HSUSBD->EP[i].EPCFG & 0x1ul) == 0x1ul) {
HSUSBD->EP[i].EPRSPCTL = HSUSBD_EP_RSPCTL_TOGGLE;
}
}
}
break;
}
case SET_FEATURE: {
if(gUsbCmd.wValue == FEATURE_ENDPOINT_HALT) {
uint32_t idx;
idx = (uint32_t)(gUsbCmd.wIndex & 0xFul);
HSUSBD_SetStall(idx);
} else if (g_hsusbd_EnableTestMode) {
g_hsusbd_EnableTestMode = (uint8_t)0ul;
if (g_hsusbd_TestSelector == TEST_J) {
HSUSBD->TEST = TEST_J;
} else if (g_hsusbd_TestSelector == TEST_K) {
HSUSBD->TEST = TEST_K;
} else if (g_hsusbd_TestSelector == TEST_SE0_NAK) {
HSUSBD->TEST = TEST_SE0_NAK;
} else if (g_hsusbd_TestSelector == TEST_PACKET) {
HSUSBD->TEST = TEST_PACKET;
} else if (g_hsusbd_TestSelector == TEST_FORCE_ENABLE) {
HSUSBD->TEST = TEST_FORCE_ENABLE;
}
}
break;
}
case CLEAR_FEATURE: {
if(gUsbCmd.wValue == FEATURE_ENDPOINT_HALT) {
uint32_t idx;
idx = (uint32_t)(gUsbCmd.wIndex & 0xFul);
HSUSBD_ClearStall(idx);
}
break;
}
default:
break;
}
}
/**
* @brief Prepare Control IN transaction
*
* @param[in] pu8Buf Control IN data pointer
* @param[in] u32Size IN transfer size
*
* @return None
*
* @details This function is used to prepare Control IN transfer
*/
void HSUSBD_PrepareCtrlIn(uint8_t pu8Buf[], uint32_t u32Size)
{
g_hsusbd_CtrlInPointer = pu8Buf;
g_hsusbd_CtrlInSize = u32Size;
}
/**
* @brief Start Control IN transfer
*
* @param[in] None
*
* @return None
*
* @details This function is used to start Control IN
*/
void HSUSBD_CtrlIn(void)
{
uint32_t volatile i, cnt;
uint8_t u8Value;
if(g_hsusbd_CtrlInSize >= g_hsusbd_CtrlMaxPktSize) {
/* Data size > MXPLD */
cnt = g_hsusbd_CtrlMaxPktSize >> 2;
for (i=0ul; i<cnt; i++) {
HSUSBD->CEPDAT = *(uint32_t *)g_hsusbd_CtrlInPointer;
g_hsusbd_CtrlInPointer = (uint8_t *)(g_hsusbd_CtrlInPointer + 4ul);
}
HSUSBD_START_CEP_IN(g_hsusbd_CtrlMaxPktSize);
g_hsusbd_CtrlInSize -= g_hsusbd_CtrlMaxPktSize;
} else {
/* Data size <= MXPLD */
cnt = g_hsusbd_CtrlInSize >> 2;
for (i=0ul; i<cnt; i++) {
HSUSBD->CEPDAT = *(uint32_t *)g_hsusbd_CtrlInPointer;
g_hsusbd_CtrlInPointer += 4ul;
}
for (i=0ul; i<(g_hsusbd_CtrlInSize % 4ul); i++) {
u8Value = *(uint8_t *)(g_hsusbd_CtrlInPointer+i);
outpb(&HSUSBD->CEPDAT, u8Value);
}
HSUSBD_START_CEP_IN(g_hsusbd_CtrlInSize);
g_hsusbd_CtrlInPointer = 0;
g_hsusbd_CtrlInSize = 0ul;
}
}
/**
* @brief Start Control OUT transaction
*
* @param[in] pu8Buf Control OUT data pointer
* @param[in] u32Size OUT transfer size
*
* @return None
*
* @details This function is used to start Control OUT transfer
*/
void HSUSBD_CtrlOut(uint8_t pu8Buf[], uint32_t u32Size)
{
uint32_t volatile i;
while(1) {
if ((HSUSBD->CEPINTSTS & HSUSBD_CEPINTSTS_RXPKIF_Msk) == HSUSBD_CEPINTSTS_RXPKIF_Msk) {
for (i=0ul; i<u32Size; i++) {
pu8Buf[i] = inpb(&HSUSBD->CEPDAT);
}
HSUSBD->CEPINTSTS = HSUSBD_CEPINTSTS_RXPKIF_Msk;
break;
}
}
}
/**
* @brief Clear all software flags
*
* @param[in] None
*
* @return None
*
* @details This function is used to clear all software control flag
*/
void HSUSBD_SwReset(void)
{
/* Reset all variables for protocol */
g_hsusbd_UsbAddr = (uint8_t)0ul;
g_hsusbd_DmaDone = 0ul;
g_hsusbd_ShortPacket = (uint8_t)0ul;
g_hsusbd_Configured = (uint8_t)0ul;
/* Reset USB device address */
HSUSBD_SET_ADDR(0ul);
}
/**
* @brief HSUSBD Set Vendor Request
*
* @param[in] pfnVendorReq Vendor Request Callback Function
*
* @return None
*
* @details This function is used to set HSUSBD vendor request callback function
*/
void HSUSBD_SetVendorRequest(HSUSBD_VENDOR_REQ pfnVendorReq)
{
g_hsusbd_pfnVendorRequest = pfnVendorReq;
}
/*@}*/ /* end of group M480_HSUSBD_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_HSUSBD_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,377 @@
/**************************************************************************//**
* @file hsusbd.h
* @version V1.00
* @brief M480 HSUSBD driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __HSUSBD_H__
#define __HSUSBD_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_HSUSBD_Driver HSUSBD Driver
@{
*/
/** @addtogroup M480_HSUSBD_EXPORTED_CONSTANTS HSUSBD Exported Constants
@{
*/
/** @cond HIDDEN_SYMBOLS */
#define HSUSBD_MAX_EP 12ul
#define Maximum(a,b) (a)>(b) ? (a) : (b)
#define Minimum(a,b) (((a)<(b)) ? (a) : (b))
#define CEP 0xfful /*!< Control Endpoint \hideinitializer */
#define EPA 0ul /*!< Endpoint A \hideinitializer */
#define EPB 1ul /*!< Endpoint B \hideinitializer */
#define EPC 2ul /*!< Endpoint C \hideinitializer */
#define EPD 3ul /*!< Endpoint D \hideinitializer */
#define EPE 4ul /*!< Endpoint E \hideinitializer */
#define EPF 5ul /*!< Endpoint F \hideinitializer */
#define EPG 6ul /*!< Endpoint G \hideinitializer */
#define EPH 7ul /*!< Endpoint H \hideinitializer */
#define EPI 8ul /*!< Endpoint I \hideinitializer */
#define EPJ 9ul /*!< Endpoint J \hideinitializer */
#define EPK 10ul /*!< Endpoint K \hideinitializer */
#define EPL 11ul /*!< Endpoint L \hideinitializer */
/** @endcond HIDDEN_SYMBOLS */
/********************* Bit definition of CEPCTL register **********************/
#define HSUSBD_CEPCTL_NAKCLR ((uint32_t)0x00000000ul) /*!<NAK clear \hideinitializer */
#define HSUSBD_CEPCTL_STALL ((uint32_t)0x00000002ul) /*!<Stall \hideinitializer */
#define HSUSBD_CEPCTL_ZEROLEN ((uint32_t)0x00000004ul) /*!<Zero length packet \hideinitializer */
#define HSUSBD_CEPCTL_FLUSH ((uint32_t)0x00000008ul) /*!<CEP flush \hideinitializer */
/********************* Bit definition of EPxRSPCTL register **********************/
#define HSUSBD_EP_RSPCTL_FLUSH ((uint32_t)0x00000001ul) /*!<Buffer Flush \hideinitializer */
#define HSUSBD_EP_RSPCTL_MODE_AUTO ((uint32_t)0x00000000ul) /*!<Auto-Validate Mode \hideinitializer */
#define HSUSBD_EP_RSPCTL_MODE_MANUAL ((uint32_t)0x00000002ul) /*!<Manual-Validate Mode \hideinitializer */
#define HSUSBD_EP_RSPCTL_MODE_FLY ((uint32_t)0x00000004ul) /*!<Fly Mode \hideinitializer */
#define HSUSBD_EP_RSPCTL_MODE_MASK ((uint32_t)0x00000006ul) /*!<Mode Mask \hideinitializer */
#define HSUSBD_EP_RSPCTL_TOGGLE ((uint32_t)0x00000008ul) /*!<Clear Toggle bit \hideinitializer */
#define HSUSBD_EP_RSPCTL_HALT ((uint32_t)0x00000010ul) /*!<Endpoint halt \hideinitializer */
#define HSUSBD_EP_RSPCTL_ZEROLEN ((uint32_t)0x00000020ul) /*!<Zero length packet IN \hideinitializer */
#define HSUSBD_EP_RSPCTL_SHORTTXEN ((uint32_t)0x00000040ul) /*!<Packet end \hideinitializer */
#define HSUSBD_EP_RSPCTL_DISBUF ((uint32_t)0x00000080ul) /*!<Disable buffer \hideinitializer */
/********************* Bit definition of EPxCFG register **********************/
#define HSUSBD_EP_CFG_VALID ((uint32_t)0x00000001ul) /*!<Endpoint Valid \hideinitializer */
#define HSUSBD_EP_CFG_TYPE_BULK ((uint32_t)0x00000002ul) /*!<Endpoint type - bulk \hideinitializer */
#define HSUSBD_EP_CFG_TYPE_INT ((uint32_t)0x00000004ul) /*!<Endpoint type - interrupt \hideinitializer */
#define HSUSBD_EP_CFG_TYPE_ISO ((uint32_t)0x00000006ul) /*!<Endpoint type - isochronous \hideinitializer */
#define HSUSBD_EP_CFG_TYPE_MASK ((uint32_t)0x00000006ul) /*!<Endpoint type mask \hideinitializer */
#define HSUSBD_EP_CFG_DIR_OUT ((uint32_t)0x00000000ul) /*!<OUT endpoint \hideinitializer */
#define HSUSBD_EP_CFG_DIR_IN ((uint32_t)0x00000008ul) /*!<IN endpoint \hideinitializer */
/*@}*/ /* end of group M480_HSUSBD_EXPORTED_CONSTANTS */
/** @addtogroup M480_HSUSBD_EXPORTED_STRUCT HSUSBD Exported Struct
@{
*/
typedef struct HSUSBD_CMD_STRUCT {
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} S_HSUSBD_CMD_T; /*!<USB Setup Packet Structure */
typedef struct s_hsusbd_info {
uint8_t *gu8DevDesc; /*!< Device descriptor */
uint8_t *gu8ConfigDesc; /*!< Config descriptor */
uint8_t **gu8StringDesc; /*!< Pointer for USB String Descriptor pointers */
uint8_t *gu8QualDesc; /*!< Qualifier descriptor */
uint8_t *gu8FullConfigDesc; /*!< Full Speed Config descriptor */
uint8_t *gu8HSOtherConfigDesc; /*!< Other Speed Config descriptor */
uint8_t *gu8FSOtherConfigDesc; /*!< Other Speed Config descriptor */
uint8_t **gu8HidReportDesc; /*!< Pointer for HID Report descriptor */
uint32_t *gu32HidReportSize; /*!< Pointer for HID Report descriptor Size */
uint8_t **gu8FSHidReportDesc; /*!< Pointer for HID Report descriptor */
uint32_t *gu32FSHidReportSize; /*!< Pointer for HID Report descriptor Size */
} S_HSUSBD_INFO_T; /*!<USB Information Structure */
/*@}*/ /* end of group M480_HSUSBD_EXPORTED_STRUCT */
/** @cond HIDDEN_SYMBOLS */
extern uint32_t g_u32HsEpStallLock;
extern uint8_t g_hsusbd_Configured;
extern uint8_t g_hsusbd_ShortPacket;
extern uint8_t g_hsusbd_CtrlZero;
extern uint8_t g_hsusbd_UsbAddr;
extern uint32_t volatile g_hsusbd_DmaDone;
extern uint32_t g_hsusbd_CtrlInSize;
extern S_HSUSBD_INFO_T gsHSInfo;
extern S_HSUSBD_CMD_T gUsbCmd;
/** @endcond HIDDEN_SYMBOLS */
/** @addtogroup M480_HSUSBD_EXPORTED_FUNCTIONS HSUSBD Exported Functions
@{
*/
#define HSUSBD_ENABLE_USB() ((uint32_t)(HSUSBD->PHYCTL |= (HSUSBD_PHYCTL_PHYEN_Msk|HSUSBD_PHYCTL_DPPUEN_Msk))) /*!<Enable USB \hideinitializer */
#define HSUSBD_DISABLE_USB() ((uint32_t)(HSUSBD->PHYCTL &= ~HSUSBD_PHYCTL_DPPUEN_Msk)) /*!<Disable USB \hideinitializer */
#define HSUSBD_ENABLE_PHY() ((uint32_t)(HSUSBD->PHYCTL |= HSUSBD_PHYCTL_PHYEN_Msk)) /*!<Enable PHY \hideinitializer */
#define HSUSBD_DISABLE_PHY() ((uint32_t)(HSUSBD->PHYCTL &= ~HSUSBD_PHYCTL_PHYEN_Msk)) /*!<Disable PHY \hideinitializer */
#define HSUSBD_SET_SE0() ((uint32_t)(HSUSBD->PHYCTL &= ~HSUSBD_PHYCTL_DPPUEN_Msk)) /*!<Enable SE0, Force USB PHY Transceiver to Drive SE0 \hideinitializer */
#define HSUSBD_CLR_SE0() ((uint32_t)(HSUSBD->PHYCTL |= HSUSBD_PHYCTL_DPPUEN_Msk)) /*!<Disable SE0 \hideinitializer */
#define HSUSBD_SET_ADDR(addr) (HSUSBD->FADDR = (addr)) /*!<Set USB address \hideinitializer */
#define HSUSBD_GET_ADDR() ((uint32_t)(HSUSBD->FADDR)) /*!<Get USB address \hideinitializer */
#define HSUSBD_ENABLE_USB_INT(intr) (HSUSBD->GINTEN = (intr)) /*!<Enable USB Interrupt \hideinitializer */
#define HSUSBD_ENABLE_BUS_INT(intr) (HSUSBD->BUSINTEN = (intr)) /*!<Enable BUS Interrupt \hideinitializer */
#define HSUSBD_GET_BUS_INT_FLAG() (HSUSBD->BUSINTSTS) /*!<Clear Bus interrupt flag \hideinitializer */
#define HSUSBD_CLR_BUS_INT_FLAG(flag) (HSUSBD->BUSINTSTS = (flag)) /*!<Clear Bus interrupt flag \hideinitializer */
#define HSUSBD_ENABLE_CEP_INT(intr) (HSUSBD->CEPINTEN = (intr)) /*!<Enable CEP Interrupt \hideinitializer */
#define HSUSBD_CLR_CEP_INT_FLAG(flag) (HSUSBD->CEPINTSTS = (flag)) /*!<Clear CEP interrupt flag \hideinitializer */
#define HSUSBD_SET_CEP_STATE(flag) (HSUSBD->CEPCTL = (flag)) /*!<Set CEP state \hideinitializer */
#define HSUSBD_START_CEP_IN(size) (HSUSBD->CEPTXCNT = (size)) /*!<Start CEP IN Transfer \hideinitializer */
#define HSUSBD_SET_MAX_PAYLOAD(ep, size) (HSUSBD->EP[(ep)].EPMPS = (size)) /*!<Set EPx Maximum Packet Size \hideinitializer */
#define HSUSBD_ENABLE_EP_INT(ep, intr) (HSUSBD->EP[(ep)].EPINTEN = (intr)) /*!<Enable EPx Interrupt \hideinitializer */
#define HSUSBD_GET_EP_INT_FLAG(ep) (HSUSBD->EP[(ep)].EPINTSTS) /*!<Get EPx interrupt flag \hideinitializer */
#define HSUSBD_CLR_EP_INT_FLAG(ep, flag) (HSUSBD->EP[(ep)].EPINTSTS = (flag)) /*!<Clear EPx interrupt flag \hideinitializer */
#define HSUSBD_SET_DMA_LEN(len) (HSUSBD->DMACNT = (len)) /*!<Set DMA transfer length \hideinitializer */
#define HSUSBD_SET_DMA_ADDR(addr) (HSUSBD->DMAADDR = (addr)) /*!<Set DMA transfer address \hideinitializer */
#define HSUSBD_SET_DMA_READ(epnum) (HSUSBD->DMACTL = (HSUSBD->DMACTL & ~HSUSBD_DMACTL_EPNUM_Msk) | HSUSBD_DMACTL_DMARD_Msk | (epnum) | 0x100) /*!<Set DMA transfer type to read \hideinitializer */
#define HSUSBD_SET_DMA_WRITE(epnum) (HSUSBD->DMACTL = (HSUSBD->DMACTL & ~(HSUSBD_DMACTL_EPNUM_Msk | HSUSBD_DMACTL_DMARD_Msk | 0x100)) | (epnum)) /*!<Set DMA transfer type to write \hideinitializer */
#define HSUSBD_ENABLE_DMA() (HSUSBD->DMACTL |= HSUSBD_DMACTL_DMAEN_Msk) /*!<Enable DMA transfer \hideinitializer */
#define HSUSBD_IS_ATTACHED() ((uint32_t)(HSUSBD->PHYCTL & HSUSBD_PHYCTL_VBUSDET_Msk)) /*!<Check cable connect state \hideinitializer */
/**
* @brief HSUSBD_memcpy, Copy bytes hardware limitation
* @param[in] u8Dst Destination pointer.
* @param[in] u8Src Source pointer.
* @param[in] u32Size Copy size.
* @retval None.
*/
static __INLINE void HSUSBD_MemCopy(uint8_t u8Dst[], uint8_t u8Src[], uint32_t u32Size)
{
uint32_t i = 0ul;
while (u32Size--)
{
u8Dst[i] = u8Src[i];
i++;
}
}
/**
* @brief HSUSBD_ResetDMA
* @param None
* @retval None.
*/
static __INLINE void HSUSBD_ResetDMA(void)
{
HSUSBD->DMACNT = 0ul;
HSUSBD->DMACTL = 0x80ul;
HSUSBD->DMACTL = 0x00ul;
}
/**
* @brief HSUSBD_SetEpBufAddr, Set Endpoint buffer address
* @param[in] u32Ep Endpoint Number
* @param[in] u32Base Buffer Start Address
* @param[in] u32Len Buffer length
* @retval None.
*/
static __INLINE void HSUSBD_SetEpBufAddr(uint32_t u32Ep, uint32_t u32Base, uint32_t u32Len)
{
if (u32Ep == CEP) {
HSUSBD->CEPBUFST = u32Base;
HSUSBD->CEPBUFEND = u32Base + u32Len - 1ul;
} else {
HSUSBD->EP[u32Ep].EPBUFST = u32Base;
HSUSBD->EP[u32Ep].EPBUFEND = u32Base + u32Len - 1ul;
}
}
/**
* @brief HSUSBD_ConfigEp, Config Endpoint
* @param[in] u32Ep USB endpoint
* @param[in] u32EpNum Endpoint number
* @param[in] u32EpType Endpoint type
* @param[in] u32EpDir Endpoint direction
* @retval None.
*/
static __INLINE void HSUSBD_ConfigEp(uint32_t u32Ep, uint32_t u32EpNum, uint32_t u32EpType, uint32_t u32EpDir)
{
if (u32EpType == HSUSBD_EP_CFG_TYPE_BULK)
{
HSUSBD->EP[u32Ep].EPRSPCTL = (HSUSBD_EP_RSPCTL_FLUSH|HSUSBD_EP_RSPCTL_MODE_AUTO);
}
else if (u32EpType == HSUSBD_EP_CFG_TYPE_INT)
{
HSUSBD->EP[u32Ep].EPRSPCTL = (HSUSBD_EP_RSPCTL_FLUSH|HSUSBD_EP_RSPCTL_MODE_MANUAL);
}
else if (u32EpType == HSUSBD_EP_CFG_TYPE_ISO)
{
HSUSBD->EP[u32Ep].EPRSPCTL = (HSUSBD_EP_RSPCTL_FLUSH|HSUSBD_EP_RSPCTL_MODE_FLY);
}
HSUSBD->EP[u32Ep].EPCFG = (u32EpType|u32EpDir|HSUSBD_EP_CFG_VALID|(u32EpNum << 4));
}
/**
* @brief Set USB endpoint stall state
* @param[in] u32Ep The USB endpoint ID.
* @return None
* @details Set USB endpoint stall state for the specified endpoint ID. Endpoint will respond STALL token automatically.
*/
static __INLINE void HSUSBD_SetEpStall(uint32_t u32Ep)
{
if (u32Ep == CEP)
{
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALL);
}
else
{
HSUSBD->EP[u32Ep].EPRSPCTL = (HSUSBD->EP[u32Ep].EPRSPCTL & 0xf7ul) | HSUSBD_EP_RSPCTL_HALT;
}
}
/**
* @brief Set USB endpoint stall state
*
* @param[in] u32EpNum USB endpoint
* @return None
*
* @details Set USB endpoint stall state, endpoint will return STALL token.
*/
static __INLINE void HSUSBD_SetStall(uint32_t u32EpNum)
{
uint32_t i;
if (u32EpNum == 0ul)
{
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALL);
}
else
{
for (i=0ul; i<HSUSBD_MAX_EP; i++)
{
if (((HSUSBD->EP[i].EPCFG & 0xf0ul) >> 4) == u32EpNum)
{
HSUSBD->EP[i].EPRSPCTL = (HSUSBD->EP[i].EPRSPCTL & 0xf7ul) | HSUSBD_EP_RSPCTL_HALT;
}
}
}
}
/**
* @brief Clear USB endpoint stall state
* @param[in] u32Ep The USB endpoint ID.
* @return None
* @details Clear USB endpoint stall state for the specified endpoint ID. Endpoint will respond ACK/NAK token.
*/
static __INLINE void HSUSBD_ClearEpStall(uint32_t u32Ep)
{
HSUSBD->EP[u32Ep].EPRSPCTL = HSUSBD_EP_RSPCTL_TOGGLE;
}
/**
* @brief Clear USB endpoint stall state
*
* @param[in] u32EpNum USB endpoint
* @return None
*
* @details Clear USB endpoint stall state, endpoint will return ACK/NAK token.
*/
static __INLINE void HSUSBD_ClearStall(uint32_t u32EpNum)
{
uint32_t i;
for (i=0ul; i<HSUSBD_MAX_EP; i++)
{
if (((HSUSBD->EP[i].EPCFG & 0xf0ul) >> 4) == u32EpNum)
{
HSUSBD->EP[i].EPRSPCTL = HSUSBD_EP_RSPCTL_TOGGLE;
}
}
}
/**
* @brief Get USB endpoint stall state
* @param[in] u32Ep The USB endpoint ID.
* @retval 0 USB endpoint is not stalled.
* @retval Others USB endpoint is stalled.
* @details Get USB endpoint stall state of the specified endpoint ID.
*/
static __INLINE uint32_t HSUSBD_GetEpStall(uint32_t u32Ep)
{
return (HSUSBD->EP[u32Ep].EPRSPCTL & HSUSBD_EP_RSPCTL_HALT);
}
/**
* @brief Get USB endpoint stall state
*
* @param[in] u32EpNum USB endpoint
* @retval 0: USB endpoint is not stalled.
* @retval non-0: USB endpoint is stalled.
*
* @details Get USB endpoint stall state.
*/
static __INLINE uint32_t HSUSBD_GetStall(uint32_t u32EpNum)
{
uint32_t i;
uint32_t val = 0ul;
for (i=0ul; i<HSUSBD_MAX_EP; i++)
{
if (((HSUSBD->EP[i].EPCFG & 0xf0ul) >> 4) == u32EpNum)
{
val = (HSUSBD->EP[i].EPRSPCTL & HSUSBD_EP_RSPCTL_HALT);
break;
}
}
return val;
}
/*-------------------------------------------------------------------------------------------*/
typedef void (*HSUSBD_VENDOR_REQ)(void); /*!<USB Vendor request callback function */
typedef void (*HSUSBD_CLASS_REQ)(void); /*!<USB Class request callback function */
typedef void (*HSUSBD_SET_INTERFACE_REQ)(uint32_t u32AltInterface); /*!<USB Standard request "Set Interface" callback function */
void HSUSBD_Open(S_HSUSBD_INFO_T *param, HSUSBD_CLASS_REQ pfnClassReq, HSUSBD_SET_INTERFACE_REQ pfnSetInterface);
void HSUSBD_Start(void);
void HSUSBD_ProcessSetupPacket(void);
void HSUSBD_StandardRequest(void);
void HSUSBD_UpdateDeviceState(void);
void HSUSBD_PrepareCtrlIn(uint8_t pu8Buf[], uint32_t u32Size);
void HSUSBD_CtrlIn(void);
void HSUSBD_CtrlOut(uint8_t pu8Buf[], uint32_t u32Size);
void HSUSBD_SwReset(void);
void HSUSBD_SetVendorRequest(HSUSBD_VENDOR_REQ pfnVendorReq);
/*@}*/ /* end of group M480_HSUSBD_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_HSUSBD_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /*__HSUSBD_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,635 @@
/**************************************************************************//**
* @file i2c.c
* @version V3.00
* @brief M480 series I2C driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_I2C_Driver I2C Driver
@{
*/
/** @addtogroup M480_I2C_EXPORTED_FUNCTIONS I2C Exported Functions
@{
*/
/**
* @brief Enable specify I2C Controller and set Clock Divider
*
* @param[in] i2c Specify I2C port
* @param[in] u32BusClock The target I2C bus clock in Hz
*
* @return Actual I2C bus clock frequency
*
* @details The function enable the specify I2C Controller and set proper Clock Divider
* in I2C CLOCK DIVIDED REGISTER (I2CLK) according to the target I2C Bus clock.
* I2C Bus clock = PCLK / (4*(divider+1).
*
*/
uint32_t I2C_Open(I2C_T *i2c, uint32_t u32BusClock)
{
uint32_t u32Div;
uint32_t u32Pclk;
if(i2c == I2C1) {
u32Pclk = CLK_GetPCLK1Freq();
} else {
u32Pclk = CLK_GetPCLK0Freq();
}
u32Div = (uint32_t)(((u32Pclk * 10U) / (u32BusClock * 4U) + 5U) / 10U - 1U); /* Compute proper divider for I2C clock */
i2c->CLKDIV = u32Div;
/* Enable I2C */
i2c->CTL0 |= I2C_CTL0_I2CEN_Msk;
return (u32Pclk / ((u32Div + 1U) << 2U));
}
/**
* @brief Disable specify I2C Controller
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details Reset I2C Controller and disable specify I2C port.
*
*/
void I2C_Close(I2C_T *i2c)
{
/* Reset I2C Controller */
if((uint32_t)i2c == I2C0_BASE) {
SYS->IPRST1 |= SYS_IPRST1_I2C0RST_Msk;
SYS->IPRST1 &= ~SYS_IPRST1_I2C0RST_Msk;
} else if((uint32_t)i2c == I2C1_BASE) {
SYS->IPRST1 |= SYS_IPRST1_I2C1RST_Msk;
SYS->IPRST1 &= ~SYS_IPRST1_I2C1RST_Msk;
}
/* Disable I2C */
i2c->CTL0 &= ~I2C_CTL0_I2CEN_Msk;
}
/**
* @brief Clear Time-out Counter flag
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details When Time-out flag will be set, use this function to clear I2C Bus Time-out counter flag .
*
*/
void I2C_ClearTimeoutFlag(I2C_T *i2c)
{
i2c->TOCTL |= I2C_TOCTL_TOIF_Msk;
}
/**
* @brief Set Control bit of I2C Controller
*
* @param[in] i2c Specify I2C port
* @param[in] u8Start Set I2C START condition
* @param[in] u8Stop Set I2C STOP condition
* @param[in] u8Si Clear SI flag
* @param[in] u8Ack Set I2C ACK bit
*
* @return None
*
* @details The function set I2C Control bit of I2C Bus protocol.
*
*/
void I2C_Trigger(I2C_T *i2c, uint8_t u8Start, uint8_t u8Stop, uint8_t u8Si, uint8_t u8Ack)
{
uint32_t u32Reg = 0U;
if(u8Start) {
u32Reg |= I2C_CTL_STA;
}
if(u8Stop) {
u32Reg |= I2C_CTL_STO;
}
if(u8Si) {
u32Reg |= I2C_CTL_SI;
}
if(u8Ack) {
u32Reg |= I2C_CTL_AA;
}
i2c->CTL0 = (i2c->CTL0 & ~0x3CU) | u32Reg;
}
/**
* @brief Disable Interrupt of I2C Controller
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details The function is used for disable I2C interrupt
*
*/
void I2C_DisableInt(I2C_T *i2c)
{
i2c->CTL0 &= ~I2C_CTL0_INTEN_Msk;
}
/**
* @brief Enable Interrupt of I2C Controller
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details The function is used for enable I2C interrupt
*
*/
void I2C_EnableInt(I2C_T *i2c)
{
i2c->CTL0 |= I2C_CTL0_INTEN_Msk;
}
/**
* @brief Get I2C Bus Clock
*
* @param[in] i2c Specify I2C port
*
* @return The actual I2C Bus clock in Hz
*
* @details To get the actual I2C Bus Clock frequency.
*/
uint32_t I2C_GetBusClockFreq(I2C_T *i2c)
{
uint32_t u32Divider = i2c->CLKDIV;
uint32_t u32Pclk;
if(i2c == I2C1) {
u32Pclk = CLK_GetPCLK1Freq();
} else {
u32Pclk = CLK_GetPCLK0Freq();
}
return (u32Pclk / ((u32Divider + 1U) << 2U));
}
/**
* @brief Set I2C Bus Clock
*
* @param[in] i2c Specify I2C port
* @param[in] u32BusClock The target I2C Bus Clock in Hz
*
* @return The actual I2C Bus Clock in Hz
*
* @details To set the actual I2C Bus Clock frequency.
*/
uint32_t I2C_SetBusClockFreq(I2C_T *i2c, uint32_t u32BusClock)
{
uint32_t u32Div;
uint32_t u32Pclk;
if(i2c == I2C1) {
u32Pclk = CLK_GetPCLK1Freq();
} else {
u32Pclk = CLK_GetPCLK0Freq();
}
u32Div = (uint32_t)(((u32Pclk * 10U) / (u32BusClock * 4U) + 5U) / 10U - 1U); /* Compute proper divider for I2C clock */
i2c->CLKDIV = u32Div;
return (u32Pclk / ((u32Div + 1U) << 2U));
}
/**
* @brief Get Interrupt Flag
*
* @param[in] i2c Specify I2C port
*
* @return I2C interrupt flag status
*
* @details To get I2C Bus interrupt flag.
*/
uint32_t I2C_GetIntFlag(I2C_T *i2c)
{
uint32_t u32Value;
if((i2c->CTL0 & I2C_CTL0_SI_Msk) == I2C_CTL0_SI_Msk) {
u32Value = 1U;
} else {
u32Value = 0U;
}
return u32Value;
}
/**
* @brief Get I2C Bus Status Code
*
* @param[in] i2c Specify I2C port
*
* @return I2C Status Code
*
* @details To get I2C Bus Status Code.
*/
uint32_t I2C_GetStatus(I2C_T *i2c)
{
return (i2c->STATUS0);
}
/**
* @brief Read a Byte from I2C Bus
*
* @param[in] i2c Specify I2C port
*
* @return I2C Data
*
* @details To read a bytes data from specify I2C port.
*/
uint8_t I2C_GetData(I2C_T *i2c)
{
return (uint8_t)(i2c->DAT);
}
/**
* @brief Send a byte to I2C Bus
*
* @param[in] i2c Specify I2C port
* @param[in] u8Data The data to send to I2C bus
*
* @return None
*
* @details This function is used to write a byte to specified I2C port
*/
void I2C_SetData(I2C_T *i2c, uint8_t u8Data)
{
i2c->DAT = u8Data;
}
/**
* @brief Set 7-bit Slave Address and GC Mode
*
* @param[in] i2c Specify I2C port
* @param[in] u8SlaveNo Set the number of I2C address register (0~3)
* @param[in] u8SlaveAddr 7-bit slave address
* @param[in] u8GCMode Enable/Disable GC mode (I2C_GCMODE_ENABLE / I2C_GCMODE_DISABLE)
*
* @return None
*
* @details This function is used to set 7-bit slave addresses in I2C SLAVE ADDRESS REGISTER (I2CADDR0~3)
* and enable GC Mode.
*
*/
void I2C_SetSlaveAddr(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddr, uint8_t u8GCMode)
{
switch(u8SlaveNo) {
case 1:
i2c->ADDR1 = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
break;
case 2:
i2c->ADDR2 = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
break;
case 3:
i2c->ADDR3 = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
break;
case 0:
default:
i2c->ADDR0 = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
break;
}
}
/**
* @brief Configure the mask bits of 7-bit Slave Address
*
* @param[in] i2c Specify I2C port
* @param[in] u8SlaveNo Set the number of I2C address mask register (0~3)
* @param[in] u8SlaveAddrMask A byte for slave address mask
*
* @return None
*
* @details This function is used to set 7-bit slave addresses.
*
*/
void I2C_SetSlaveAddrMask(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddrMask)
{
switch(u8SlaveNo) {
case 1:
i2c->ADDRMSK1 = (uint32_t)u8SlaveAddrMask << 1U;
break;
case 2:
i2c->ADDRMSK2 = (uint32_t)u8SlaveAddrMask << 1U;
break;
case 3:
i2c->ADDRMSK3 = (uint32_t)u8SlaveAddrMask << 1U;
break;
case 0:
default:
i2c->ADDRMSK0 = (uint32_t)u8SlaveAddrMask << 1U;
break;
}
}
/**
* @brief Enable Time-out Counter Function and support Long Time-out
*
* @param[in] i2c Specify I2C port
* @param[in] u8LongTimeout Configure DIV4 to enable Long Time-out (0/1)
*
* @return None
*
* @details This function enable Time-out Counter function and configure DIV4 to support Long
* Time-out.
*
*/
void I2C_EnableTimeout(I2C_T *i2c, uint8_t u8LongTimeout)
{
if(u8LongTimeout) {
i2c->TOCTL |= I2C_TOCTL_TOCDIV4_Msk;
} else {
i2c->TOCTL &= ~I2C_TOCTL_TOCDIV4_Msk;
}
i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk;
}
/**
* @brief Disable Time-out Counter Function
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details To disable Time-out Counter function in I2CTOC register.
*
*/
void I2C_DisableTimeout(I2C_T *i2c)
{
i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk;
}
/**
* @brief Enable I2C Wake-up Function
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details To enable Wake-up function of I2C Wake-up control register.
*
*/
void I2C_EnableWakeup(I2C_T *i2c)
{
i2c->WKCTL |= I2C_WKCTL_WKEN_Msk;
}
/**
* @brief Disable I2C Wake-up Function
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details To disable Wake-up function of I2C Wake-up control register.
*
*/
void I2C_DisableWakeup(I2C_T *i2c)
{
i2c->WKCTL &= ~I2C_WKCTL_WKEN_Msk;
}
/**
* @brief To get SMBus Status
*
* @param[in] i2c Specify I2C port
*
* @return SMBus status
*
* @details To get the Bus Management status of I2C_BUSSTS register
*
*/
uint32_t I2C_SMBusGetStatus(I2C_T *i2c)
{
return (i2c->BUSSTS);
}
/**
* @brief Clear SMBus Interrupt Flag
*
* @param[in] i2c Specify I2C port
* @param[in] u8SMBusIntFlag Specify SMBus interrupt flag
*
* @return None
*
* @details To clear flags of I2C_BUSSTS status register if interrupt set.
*
*/
void I2C_SMBusClearInterruptFlag(I2C_T *i2c, uint8_t u8SMBusIntFlag)
{
i2c->BUSSTS |= u8SMBusIntFlag;
}
/**
* @brief Set SMBus Bytes Counts of Transmission or Reception
*
* @param[in] i2c Specify I2C port
* @param[in] u32PktSize Transmit / Receive bytes
*
* @return None
*
* @details The transmission or receive byte number in one transaction when PECEN is set. The maximum is 255 bytes.
*
*/
void I2C_SMBusSetPacketByteCount(I2C_T *i2c, uint32_t u32PktSize)
{
i2c->PKTSIZE = u32PktSize;
}
/**
* @brief Init SMBus Host/Device Mode
*
* @param[in] i2c Specify I2C port
* @param[in] u8HostDevice Init SMBus port mode(I2C_SMBH_ENABLE(1)/I2C_SMBD_ENABLE(0))
*
* @return None
*
* @details Using SMBus communication must specify the port is a Host or a Device.
*
*/
void I2C_SMBusOpen(I2C_T *i2c, uint8_t u8HostDevice)
{
/* Clear BMHEN, BMDEN of BUSCTL Register */
i2c->BUSCTL &= ~(I2C_BUSCTL_BMHEN_Msk | I2C_BUSCTL_BMDEN_Msk);
/* Set SMBus Host/Device Mode, and enable Bus Management*/
if(u8HostDevice == (uint8_t)I2C_SMBH_ENABLE) {
i2c->BUSCTL |= (I2C_BUSCTL_BMHEN_Msk | I2C_BUSCTL_BUSEN_Msk);
} else {
i2c->BUSCTL |= (I2C_BUSCTL_BMDEN_Msk | I2C_BUSCTL_BUSEN_Msk);
}
}
/**
* @brief Disable SMBus function
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details Disable all SMBus function include Bus disable, CRC check, Acknowledge by manual, Host/Device Mode.
*
*/
void I2C_SMBusClose(I2C_T *i2c)
{
i2c->BUSCTL = 0x00U;
}
/**
* @brief Enable SMBus PEC Transmit Function
*
* @param[in] i2c Specify I2C port
* @param[in] u8PECTxEn CRC transmit enable(PECTX_ENABLE) or disable(PECTX_DISABLE)
*
* @return None
*
* @details When enable CRC check function, the Host or Device needs to transmit CRC byte.
*
*/
void I2C_SMBusPECTxEnable(I2C_T *i2c, uint8_t u8PECTxEn)
{
i2c->BUSCTL &= ~I2C_BUSCTL_PECTXEN_Msk;
if(u8PECTxEn) {
i2c->BUSCTL |= (I2C_BUSCTL_PECEN_Msk | I2C_BUSCTL_PECTXEN_Msk);
} else {
i2c->BUSCTL |= I2C_BUSCTL_PECEN_Msk;
}
}
/**
* @brief Get SMBus CRC value
*
* @param[in] i2c Specify I2C port
*
* @return A byte is packet error check value
*
* @details The CRC check value after a transmission or a reception by count by using CRC8
*
*/
uint8_t I2C_SMBusGetPECValue(I2C_T *i2c)
{
return (uint8_t)i2c->PKTCRC;
}
/**
* @brief Calculate Time-out of SMBus idle period
*
* @param[in] i2c Specify I2C port
* @param[in] us Time-out length(us)
* @param[in] u32Hclk I2C peripheral clock frequency
*
* @return None
*
* @details This function is used to set SMBus Time-out length when bus is in Idle state.
*
*/
void I2C_SMBusIdleTimeout(I2C_T *i2c, uint32_t us, uint32_t u32Hclk)
{
uint32_t u32Div, u32Hclk_kHz;
i2c->BUSCTL |= I2C_BUSCTL_TIDLE_Msk;
u32Hclk_kHz = u32Hclk / 1000U;
u32Div = (((us * u32Hclk_kHz) / 1000U) >> 2U) - 1U;
if(u32Div > 255U) {
i2c->BUSTOUT = 0xFFU;
} else {
i2c->BUSTOUT = u32Div;
}
}
/**
* @brief Calculate Time-out of SMBus active period
*
* @param[in] i2c Specify I2C port
* @param[in] ms Time-out length(ms)
* @param[in] u32Pclk peripheral clock frequency
*
* @return None
*
* @details This function is used to set SMBus Time-out length when bus is in active state.
* Time-out length is calculate the SCL line "one clock" pull low timing.
*
*/
void I2C_SMBusTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk)
{
uint32_t u32Div, u32Pclk_kHz;
i2c->BUSCTL &= ~I2C_BUSCTL_TIDLE_Msk;
/* DIV4 disabled */
i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk;
u32Pclk_kHz = u32Pclk / 1000U;
u32Div = ((ms * u32Pclk_kHz) / (16U * 1024U)) - 1U;
if(u32Div <= 0xFFU) {
i2c->BUSTOUT = u32Div;
} else {
/* DIV4 enabled */
i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk;
i2c->BUSTOUT = (((ms * u32Pclk_kHz) / (16U * 1024U * 4U)) - 1U) & 0xFFU; /* The max value is 255 */
}
}
/**
* @brief Calculate Cumulative Clock low Time-out of SMBus active period
*
* @param[in] i2c Specify I2C port
* @param[in] ms Time-out length(ms)
* @param[in] u32Pclk peripheral clock frequency
*
* @return None
*
* @details This function is used to set SMBus Time-out length when bus is in Active state.
* Time-out length is calculate the SCL line "clocks" low cumulative timing.
*
*/
void I2C_SMBusClockLoTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk)
{
uint32_t u32Div, u32Pclk_kHz;
i2c->BUSCTL &= ~I2C_BUSCTL_TIDLE_Msk;
/* DIV4 disabled */
i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk;
u32Pclk_kHz = u32Pclk / 1000U;
u32Div = ((ms * u32Pclk_kHz) / (16U * 1024U)) - 1U;
if(u32Div <= 0xFFU) {
i2c->CLKTOUT = u32Div;
} else {
/* DIV4 enabled */
i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk;
i2c->CLKTOUT = (((ms * u32Pclk_kHz) / (16U * 1024U * 4U)) - 1U) & 0xFFU; /* The max value is 255 */
}
}
/*@}*/ /* end of group M480_I2C_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_I2C_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,489 @@
/****************************************************************************//**
* @file i2c.h
* @version V1.00
* @brief M480 series I2C driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __I2C_H__
#define __I2C_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_I2C_Driver I2C Driver
@{
*/
/** @addtogroup M480_I2C_EXPORTED_CONSTANTS I2C Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* I2C_CTL constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define I2C_CTL_STA_SI 0x28UL /*!< I2C_CTL setting for I2C control bits. It would set STA and SI bits \hideinitializer */
#define I2C_CTL_STA_SI_AA 0x2CUL /*!< I2C_CTL setting for I2C control bits. It would set STA, SI and AA bits \hideinitializer */
#define I2C_CTL_STO_SI 0x18UL /*!< I2C_CTL setting for I2C control bits. It would set STO and SI bits \hideinitializer */
#define I2C_CTL_STO_SI_AA 0x1CUL /*!< I2C_CTL setting for I2C control bits. It would set STO, SI and AA bits \hideinitializer */
#define I2C_CTL_SI 0x08UL /*!< I2C_CTL setting for I2C control bits. It would set SI bit \hideinitializer */
#define I2C_CTL_SI_AA 0x0CUL /*!< I2C_CTL setting for I2C control bits. It would set SI and AA bits \hideinitializer */
#define I2C_CTL_STA 0x20UL /*!< I2C_CTL setting for I2C control bits. It would set STA bit \hideinitializer */
#define I2C_CTL_STO 0x10UL /*!< I2C_CTL setting for I2C control bits. It would set STO bit \hideinitializer */
#define I2C_CTL_AA 0x04UL /*!< I2C_CTL setting for I2C control bits. It would set AA bit \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* I2C GCMode constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define I2C_GCMODE_ENABLE 1 /*!< Enable I2C GC Mode \hideinitializer */
#define I2C_GCMODE_DISABLE 0 /*!< Disable I2C GC Mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* I2C SMBUS constant definitions. */
/*---------------------------------------------------------------------------------------------------------*/
#define I2C_SMBH_ENABLE 1 /*!< Enable SMBus Host Mode enable \hideinitializer */
#define I2C_SMBD_ENABLE 0 /*!< Enable SMBus Device Mode enable \hideinitializer */
#define I2C_PECTX_ENABLE 1 /*!< Enable SMBus Packet Error Check Transmit function \hideinitializer */
#define I2C_PECTX_DISABLE 0 /*!< Disable SMBus Packet Error Check Transmit function \hideinitializer */
/*@}*/ /* end of group M480_I2C_EXPORTED_CONSTANTS */
/** @addtogroup M480_I2C_EXPORTED_FUNCTIONS I2C Exported Functions
@{
*/
/**
* @brief The macro is used to set I2C bus condition at One Time
*
* @param[in] i2c Specify I2C port
* @param[in] u8Ctrl A byte writes to I2C control register
*
* @return None
*
* @details Set I2C_CTL register to control I2C bus conditions of START, STOP, SI, ACK.
* \hideinitializer
*/
#define I2C_SET_CONTROL_REG(i2c, u8Ctrl) ((i2c)->CTL0 = ((i2c)->CTL0 & ~0x3c) | (u8Ctrl))
/**
* @brief The macro is used to set START condition of I2C Bus
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details Set the I2C bus START condition in I2C_CTL register.
* \hideinitializer
*/
#define I2C_START(i2c) ((i2c)->CTL0 = ((i2c)->CTL0 & ~I2C_CTL0_SI_Msk) | I2C_CTL0_STA_Msk)
/**
* @brief The macro is used to wait I2C bus status get ready
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details When a new status is presented of I2C bus, the SI flag will be set in I2C_CTL register.
* \hideinitializer
*/
#define I2C_WAIT_READY(i2c) while(!((i2c)->CTL0 & I2C_CTL0_SI_Msk))
/**
* @brief The macro is used to Read I2C Bus Data Register
*
* @param[in] i2c Specify I2C port
*
* @return A byte of I2C data register
*
* @details I2C controller read data from bus and save it in I2CDAT register.
* \hideinitializer
*/
#define I2C_GET_DATA(i2c) ((i2c)->DAT)
/**
* @brief Write a Data to I2C Data Register
*
* @param[in] i2c Specify I2C port
* @param[in] u8Data A byte that writes to data register
*
* @return None
*
* @details When write a data to I2C_DAT register, the I2C controller will shift it to I2C bus.
* \hideinitializer
*/
#define I2C_SET_DATA(i2c, u8Data) ((i2c)->DAT = (u8Data))
/**
* @brief Get I2C Bus status code
*
* @param[in] i2c Specify I2C port
*
* @return I2C status code
*
* @details To get this status code to monitor I2C bus event.
* \hideinitializer
*/
#define I2C_GET_STATUS(i2c) ((i2c)->STATUS0)
/**
* @brief Get Time-out flag from I2C Bus
*
* @param[in] i2c Specify I2C port
*
* @retval 0 I2C Bus time-out is not happened
* @retval 1 I2C Bus time-out is happened
*
* @details When I2C bus occurs time-out event, the time-out flag will be set.
* \hideinitializer
*/
#define I2C_GET_TIMEOUT_FLAG(i2c) ( ((i2c)->TOCTL & I2C_TOCTL_TOIF_Msk) == I2C_TOCTL_TOIF_Msk ? 1:0 )
/**
* @brief To get wake-up flag from I2C Bus
*
* @param[in] i2c Specify I2C port
*
* @retval 0 Chip is not woken-up from power-down mode
* @retval 1 Chip is woken-up from power-down mode
*
* @details I2C bus occurs wake-up event, wake-up flag will be set.
* \hideinitializer
*/
#define I2C_GET_WAKEUP_FLAG(i2c) ( ((i2c)->WKSTS & I2C_WKSTS_WKIF_Msk) == I2C_WKSTS_WKIF_Msk ? 1:0 )
/**
* @brief To clear wake-up flag
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details If wake-up flag is set, use this macro to clear it.
* \hideinitializer
*/
#define I2C_CLEAR_WAKEUP_FLAG(i2c) ((i2c)->WKSTS = I2C_WKSTS_WKIF_Msk)
/**
* @brief To get SMBus Status
*
* @param[in] i2c Specify I2C port
*
* @return SMBus status
*
* @details To get the Bus Management status of I2C_BUSSTS register
* \hideinitializer
*
*/
#define I2C_SMBUS_GET_STATUS(i2c) ((i2c)->BUSSTS)
/**
* @brief Get SMBus CRC value
*
* @param[in] i2c Specify I2C port
*
* @return Packet error check byte value
*
* @details The CRC check value after a transmission or a reception by count by using CRC8
* \hideinitializer
*/
#define I2C_SMBUS_GET_PEC_VALUE(i2c) ((i2c)->PKTCRC)
/**
* @brief Set SMBus Bytes number of Transmission or reception
*
* @param[in] i2c Specify I2C port
* @param[in] u32PktSize Transmit / Receive bytes
*
* @return None
*
* @details The transmission or receive byte number in one transaction when PECEN is set. The maximum is 255 bytes.
* \hideinitializer
*/
#define I2C_SMBUS_SET_PACKET_BYTE_COUNT(i2c, u32PktSize) ((i2c)->PKTSIZE = (u32PktSize))
/**
* @brief Enable SMBus Alert function
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details Device Mode(BMHEN=0): If ALERTEN(I2C_BUSCTL[4]) is set, the Alert pin will pull lo, and reply ACK when get ARP from host
* Host Mode(BMHEN=1): If ALERTEN(I2C_BUSCTL[4]) is set, the Alert pin is supported to receive alert state(Lo trigger)
* \hideinitializer
*/
#define I2C_SMBUS_ENABLE_ALERT(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_ALERTEN_Msk)
/**
* @brief Disable SMBus Alert pin function
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details Device Mode(BMHEN=0): If ALERTEN(I2C_BUSCTL[4]) is clear, the Alert pin will pull hi, and reply NACK when get ARP from host
* Host Mode(BMHEN=1): If ALERTEN(I2C_BUSCTL[4]) is clear, the Alert pin is not supported to receive alert state(Lo trigger)
* \hideinitializer
*/
#define I2C_SMBUS_DISABLE_ALERT(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_ALERTEN_Msk)
/**
* @brief Set SMBus SUSCON pin is output mode
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details This function to set SUSCON(I2C_BUSCTL[6]) pin is output mode.
*
* \hideinitializer
*/
#define I2C_SMBUS_SET_SUSCON_OUT(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_SCTLOEN_Msk)
/**
* @brief Set SMBus SUSCON pin is input mode
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details This function to set SUSCON(I2C_BUSCTL[6]) pin is input mode.
*
* \hideinitializer
*/
#define I2C_SMBUS_SET_SUSCON_IN(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_SCTLOEN_Msk)
/**
* @brief Set SMBus SUSCON pin output high state
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details This function to set SUSCON(I2C_BUSCTL[6]) pin is output hi state.
* \hideinitializer
*/
#define I2C_SMBUS_SET_SUSCON_HIGH(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_SCTLOSTS_Msk)
/**
* @brief Set SMBus SUSCON pin output low state
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details This function to set SUSCON(I2C_BUSCTL[6]) pin is output lo state.
* \hideinitializer
*/
#define I2C_SMBUS_SET_SUSCON_LOW(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_SCTLOSTS_Msk)
/**
* @brief Enable SMBus Acknowledge control by manual
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details The 9th bit can response the ACK or NACK according the received data by user. When the byte is received, SCLK line stretching to low between the 8th and 9th SCLK pulse.
* \hideinitializer
*/
#define I2C_SMBUS_ACK_MANUAL(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_ACKMEN_Msk)
/**
* @brief Disable SMBus Acknowledge control by manual
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details Disable acknowledge response control by user.
* \hideinitializer
*/
#define I2C_SMBUS_ACK_AUTO(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_ACKMEN_Msk)
/**
* @brief Enable SMBus Acknowledge manual interrupt
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details This function is used to enable SMBUS acknowledge manual interrupt on the 9th clock cycle when SMBUS=1 and ACKMEN=1
* \hideinitializer
*/
#define I2C_SMBUS_9THBIT_INT_ENABLE(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_ACKM9SI_Msk)
/**
* @brief Disable SMBus Acknowledge manual interrupt
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details This function is used to disable SMBUS acknowledge manual interrupt on the 9th clock cycle when SMBUS=1 and ACKMEN=1
* \hideinitializer
*/
#define I2C_SMBUS_9THBIT_INT_DISABLE(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_ACKM9SI_Msk)
/**
* @brief Enable SMBus PEC clear at REPEAT START
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details This function is used to enable the condition of REAEAT START can clear the PEC calculation.
* \hideinitializer
*/
#define I2C_SMBUS_RST_PEC_AT_START_ENABLE(i2c) ((i2c)->BUSCTL |= I2C_BUSCTL_PECCLR_Msk)
/**
* @brief Disable SMBus PEC clear at Repeat START
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details This function is used to disable the condition of Repeat START can clear the PEC calculation.
* \hideinitializer
*/
#define I2C_SMBUS_RST_PEC_AT_START_DISABLE(i2c) ((i2c)->BUSCTL &= ~I2C_BUSCTL_PECCLR_Msk)
/**
* @brief Enable RX PDMA function.
* @param[in] i2c The pointer of the specified I2C module.
* @return None.
* @details Set RXPDMAEN bit of I2C_CTL1 register to enable RX PDMA transfer function.
* \hideinitializer
*/
#define I2C_ENABLE_RX_PDMA(i2c) ((i2c)->CTL1 |= I2C_CTL1_RXPDMAEN_Msk)
/**
* @brief Enable TX PDMA function.
* @param[in] i2c The pointer of the specified I2C module.
* @return None.
* @details Set TXPDMAEN bit of I2C_CTL1 register to enable TX PDMA transfer function.
* \hideinitializer
*/
#define I2C_ENABLE_TX_PDMA(i2c) ((i2c)->CTL1 |= I2C_CTL1_TXPDMAEN_Msk)
/**
* @brief Disable RX PDMA transfer.
* @param[in] i2c The pointer of the specified I2C module.
* @return None.
* @details Clear RXPDMAEN bit of I2C_CTL1 register to disable RX PDMA transfer function.
* \hideinitializer
*/
#define I2C_DISABLE_RX_PDMA(i2c) ((i2c)->CTL1 &= ~I2C_CTL1_RXPDMAEN_Msk)
/**
* @brief Disable TX PDMA transfer.
* @param[in] i2c The pointer of the specified I2C module.
* @return None.
* @details Clear TXPDMAEN bit of I2C_CTL1 register to disable TX PDMA transfer function.
* \hideinitializer
*/
#define I2C_DISABLE_TX_PDMA(i2c) ((i2c)->CTL1 &= ~I2C_CTL1_TXPDMAEN_Msk)
/**
* @brief Enable PDMA stretch function.
* @param[in] i2c The pointer of the specified I2C module.
* @return None.
* @details Enable this function is to stretch bus by hardware after PDMA transfer is done if SI is not cleared.
* \hideinitializer
*/
#define I2C_ENABLE_PDMA_STRETCH(i2c) ((i2c)->CTL1 |= I2C_CTL1_PDMASTR_Msk)
/**
* @brief Disable PDMA stretch function.
* @param[in] i2c The pointer of the specified I2C module.
* @return None.
* @details I2C will send STOP after PDMA transfers done automatically.
* \hideinitializer
*/
#define I2C_DISABLE_PDMA_STRETCH(i2c) ((i2c)->CTL1 &= ~I2C_CTL1_PDMASTR_Msk)
/**
* @brief Reset PDMA function.
* @param[in] i2c The pointer of the specified I2C module.
* @return None.
* @details I2C PDMA engine will be reset after this function is called.
* \hideinitializer
*/
#define I2C_DISABLE_RST_PDMA(i2c) ((i2c)->CTL1 |= I2C_CTL1_PDMARST_Msk)
/*---------------------------------------------------------------------------------------------------------*/
/* inline functions */
/*---------------------------------------------------------------------------------------------------------*/
/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */
static __INLINE void I2C_STOP(I2C_T *i2c);
/**
* @brief The macro is used to set STOP condition of I2C Bus
*
* @param[in] i2c Specify I2C port
*
* @return None
*
* @details Set the I2C bus STOP condition in I2C_CTL register.
*/
static __INLINE void I2C_STOP(I2C_T *i2c)
{
(i2c)->CTL0 |= (I2C_CTL0_SI_Msk | I2C_CTL0_STO_Msk);
while(i2c->CTL0 & I2C_CTL0_STO_Msk) {
}
}
void I2C_ClearTimeoutFlag(I2C_T *i2c);
void I2C_Close(I2C_T *i2c);
void I2C_Trigger(I2C_T *i2c, uint8_t u8Start, uint8_t u8Stop, uint8_t u8Si, uint8_t u8Ack);
void I2C_DisableInt(I2C_T *i2c);
void I2C_EnableInt(I2C_T *i2c);
uint32_t I2C_GetBusClockFreq(I2C_T *i2c);
uint32_t I2C_GetIntFlag(I2C_T *i2c);
uint32_t I2C_GetStatus(I2C_T *i2c);
uint32_t I2C_Open(I2C_T *i2c, uint32_t u32BusClock);
uint8_t I2C_GetData(I2C_T *i2c);
void I2C_SetSlaveAddr(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddr, uint8_t u8GCMode);
void I2C_SetSlaveAddrMask(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddrMask);
uint32_t I2C_SetBusClockFreq(I2C_T *i2c, uint32_t u32BusClock);
void I2C_EnableTimeout(I2C_T *i2c, uint8_t u8LongTimeout);
void I2C_DisableTimeout(I2C_T *i2c);
void I2C_EnableWakeup(I2C_T *i2c);
void I2C_DisableWakeup(I2C_T *i2c);
void I2C_SetData(I2C_T *i2c, uint8_t u8Data);
void I2C_SMBusClearInterruptFlag(I2C_T *i2c, uint8_t u8SMBusIntFlag);
uint32_t I2C_SMBusGetStatus(I2C_T *i2c);
void I2C_SMBusSetPacketByteCount(I2C_T *i2c, uint32_t u32PktSize);
void I2C_SMBusOpen(I2C_T *i2c, uint8_t u8HostDevice);
void I2C_SMBusClose(I2C_T *i2c);
void I2C_SMBusPECTxEnable(I2C_T *i2c, uint8_t u8PECTxEn);
uint8_t I2C_SMBusGetPECValue(I2C_T *i2c);
void I2C_SMBusIdleTimeout(I2C_T *i2c, uint32_t us, uint32_t u32Hclk);
void I2C_SMBusTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk);
void I2C_SMBusClockLoTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk);
/*@}*/ /* end of group M480_I2C_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_I2C_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,240 @@
/**************************************************************************//**
* @file i2s.c
* @version V0.10
* @brief M480 I2S driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_I2S_Driver I2S Driver
@{
*/
/** @addtogroup M480_I2S_EXPORTED_FUNCTIONS I2S Exported Functions
@{
*/
static uint32_t I2S_GetSourceClockFreq(I2S_T *i2s);
/**
* @brief This function is used to get I2S source clock frequency.
* @param[in] i2s is the base address of I2S module.
* @return I2S source clock frequency (Hz).
*/
static uint32_t I2S_GetSourceClockFreq(I2S_T *i2s)
{
uint32_t u32Freq, u32ClkSrcSel;
/* get I2S selection clock source */
u32ClkSrcSel = CLK->CLKSEL3 & CLK_CLKSEL3_I2S0SEL_Msk;
switch (u32ClkSrcSel) {
case CLK_CLKSEL3_I2S0SEL_HXT:
u32Freq = __HXT;
break;
case CLK_CLKSEL3_I2S0SEL_PLL:
u32Freq = CLK_GetPLLClockFreq();
break;
case CLK_CLKSEL3_I2S0SEL_HIRC:
u32Freq = __HIRC;
break;
case CLK_CLKSEL3_I2S0SEL_PCLK0:
u32Freq = (uint32_t)CLK_GetPCLK0Freq();
break;
default:
u32Freq = __HIRC;
break;
}
return u32Freq;
}
/**
* @brief This function configures some parameters of I2S interface for general purpose use.
* The sample rate may not be used from the parameter, it depends on system's clock settings,
* but real sample rate used by system will be returned for reference.
* @param[in] i2s is the base address of I2S module.
* @param[in] u32MasterSlave I2S operation mode. Valid values are:
* - \ref I2S_MODE_MASTER
* - \ref I2S_MODE_SLAVE
* @param[in] u32SampleRate Sample rate
* @param[in] u32WordWidth Data length. Valid values are:
* - \ref I2S_DATABIT_8
* - \ref I2S_DATABIT_16
* - \ref I2S_DATABIT_24
* - \ref I2S_DATABIT_32
* @param[in] u32MonoData: Set audio data to mono or not. Valid values are:
* - \ref I2S_ENABLE_MONO
* - \ref I2S_DISABLE_MONO
* @param[in] u32DataFormat: Data format. This is also used to select I2S or PCM(TDM) function. Valid values are:
* - \ref I2S_FORMAT_I2S
* - \ref I2S_FORMAT_I2S_MSB
* - \ref I2S_FORMAT_I2S_LSB
* - \ref I2S_FORMAT_PCM
* - \ref I2S_FORMAT_PCM_MSB
* - \ref I2S_FORMAT_PCM_LSB
* @return Real sample rate.
*/
uint32_t I2S_Open(I2S_T *i2s, uint32_t u32MasterSlave, uint32_t u32SampleRate, uint32_t u32WordWidth, uint32_t u32MonoData, uint32_t u32DataFormat)
{
uint16_t u16Divider;
uint32_t u32BitRate, u32SrcClk;
SYS->IPRST1 |= SYS_IPRST1_I2S0RST_Msk;
SYS->IPRST1 &= ~SYS_IPRST1_I2S0RST_Msk;
i2s->CTL0 = u32MasterSlave | u32WordWidth | u32MonoData | u32DataFormat | I2S_FIFO_TX_LEVEL_WORD_8 | I2S_FIFO_RX_LEVEL_WORD_8;
u32SrcClk = I2S_GetSourceClockFreq(i2s);
u32BitRate = u32SampleRate * (((u32WordWidth>>4U) & 0x3U) + 1U) * 16U;
u16Divider = (uint16_t)((u32SrcClk/u32BitRate) >> 1U) - 1U;
i2s->CLKDIV = (i2s->CLKDIV & ~I2S_CLKDIV_BCLKDIV_Msk) | ((uint32_t)u16Divider << 8U);
/* calculate real sample rate */
u32BitRate = u32SrcClk / (2U*((uint32_t)u16Divider+1U));
u32SampleRate = u32BitRate / ((((u32WordWidth>>4U) & 0x3U) + 1U) * 16U);
i2s->CTL0 |= I2S_CTL0_I2SEN_Msk;
return u32SampleRate;
}
/**
* @brief Disable I2S function and I2S clock.
* @param[in] i2s is the base address of I2S module.
* @return none
*/
void I2S_Close(I2S_T *i2s)
{
i2s->CTL0 &= ~I2S_CTL0_I2SEN_Msk;
}
/**
* @brief This function enables the interrupt according to the mask parameter.
* @param[in] i2s is the base address of I2S module.
* @param[in] u32Mask is the combination of all related interrupt enable bits.
* Each bit corresponds to a interrupt bit.
* @return none
*/
void I2S_EnableInt(I2S_T *i2s, uint32_t u32Mask)
{
i2s->IEN |= u32Mask;
}
/**
* @brief This function disables the interrupt according to the mask parameter.
* @param[in] i2s is the base address of I2S module.
* @param[in] u32Mask is the combination of all related interrupt enable bits.
* Each bit corresponds to a interrupt bit.
* @return none
*/
void I2S_DisableInt(I2S_T *i2s, uint32_t u32Mask)
{
i2s->IEN &= ~u32Mask;
}
/**
* @brief Enable MCLK .
* @param[in] i2s is the base address of I2S module.
* @param[in] u32BusClock is the target MCLK clock
* @return Actual MCLK clock
*/
uint32_t I2S_EnableMCLK(I2S_T *i2s, uint32_t u32BusClock)
{
uint8_t u8Divider;
uint32_t u32SrcClk, u32Reg, u32Clock;
u32SrcClk = I2S_GetSourceClockFreq(i2s);
if (u32BusClock == u32SrcClk) {
u8Divider = 0U;
} else {
u8Divider = (uint8_t)(u32SrcClk/u32BusClock) >> 1U;
}
i2s->CLKDIV = (i2s->CLKDIV & ~I2S_CLKDIV_MCLKDIV_Msk) | u8Divider;
i2s->CTL0 |= I2S_CTL0_MCLKEN_Msk;
u32Reg = i2s->CLKDIV & I2S_CLKDIV_MCLKDIV_Msk;
if (u32Reg == 0U) {
u32Clock = u32SrcClk;
} else {
u32Clock = ((u32SrcClk >> 1U) / u32Reg);
}
return u32Clock;
}
/**
* @brief Disable MCLK .
* @param[in] i2s is the base address of I2S module.
* @return none
*/
void I2S_DisableMCLK(I2S_T *i2s)
{
i2s->CTL0 &= ~I2S_CTL0_MCLKEN_Msk;
}
/**
* @brief Configure FIFO threshold setting.
* @param[in] i2s The pointer of the specified I2S module.
* @param[in] u32TxThreshold Decides the TX FIFO threshold. It could be 0 ~ 7.
* @param[in] u32RxThreshold Decides the RX FIFO threshold. It could be 0 ~ 7.
* @return None
* @details Set TX FIFO threshold and RX FIFO threshold configurations.
*/
void I2S_SetFIFO(I2S_T *i2s, uint32_t u32TxThreshold, uint32_t u32RxThreshold)
{
i2s->CTL1 = ((i2s->CTL1 & ~(I2S_CTL1_TXTH_Msk | I2S_CTL1_RXTH_Msk)) |
(u32TxThreshold << I2S_CTL1_TXTH_Pos) |
(u32RxThreshold << I2S_CTL1_RXTH_Pos));
}
/**
* @brief Configure PCM(TDM) function parameters, such as channel width, channel number and sync pulse width
* @param[in] i2s The pointer of the specified I2S module.
* @param[in] u32ChannelWidth Channel width. Valid values are:
* - \ref I2S_TDM_WIDTH_8BIT
* - \ref I2S_TDM_WIDTH_16BIT
* - \ref I2S_TDM_WIDTH_24BIT
* - \ref I2S_TDM_WIDTH_32BIT
* @param[in] u32ChannelNum Channel number. Valid values are:
* - \ref I2S_TDM_2CH
* - \ref I2S_TDM_4CH
* - \ref I2S_TDM_6CH
* - \ref I2S_TDM_8CH
* @param[in] u32SyncWidth Width for sync pulse. Valid values are:
* - \ref I2S_TDM_SYNC_ONE_BCLK
* - \ref I2S_TDM_SYNC_ONE_CHANNEL
* @return None
* @details Set TX FIFO threshold and RX FIFO threshold configurations.
*/
void I2S_ConfigureTDM(I2S_T *i2s, uint32_t u32ChannelWidth, uint32_t u32ChannelNum, uint32_t u32SyncWidth)
{
i2s->CTL0 = ((i2s->CTL0 & ~(I2S_CTL0_TDMCHNUM_Msk | I2S_CTL0_CHWIDTH_Msk | I2S_CTL0_PCMSYNC_Msk)) |
(u32ChannelWidth << I2S_CTL0_CHWIDTH_Pos) |
(u32ChannelNum << I2S_CTL0_TDMCHNUM_Pos) |
(u32SyncWidth << I2S_CTL0_PCMSYNC_Pos));
}
/*@}*/ /* end of group M480_I2S_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_I2S_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,350 @@
/****************************************************************************//**
* @file i2s.h
* @version V0.10
* @brief M480 I2S driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __I2S_H__
#define __I2S_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_I2S_Driver I2S Driver
@{
*/
/** @addtogroup M480_I2S_EXPORTED_CONSTANTS I2S Exported Constants
@{
*/
#define I2S_DATABIT_8 (0U << I2S_CTL0_DATWIDTH_Pos) /*!< I2S data width is 8-bit \hideinitializer */
#define I2S_DATABIT_16 (1U << I2S_CTL0_DATWIDTH_Pos) /*!< I2S data width is 16-bit \hideinitializer */
#define I2S_DATABIT_24 (2U << I2S_CTL0_DATWIDTH_Pos) /*!< I2S data width is 24-bit \hideinitializer */
#define I2S_DATABIT_32 (3U << I2S_CTL0_DATWIDTH_Pos) /*!< I2S data width is 32-bit \hideinitializer */
/* Audio Format */
#define I2S_ENABLE_MONO I2S_CTL0_MONO_Msk /*!< Mono channel \hideinitializer */
#define I2S_DISABLE_MONO (0U) /*!< Stereo channel \hideinitializer */
/* I2S Data Format */
#define I2S_FORMAT_I2S (0U << I2S_CTL0_FORMAT_Pos) /*!< I2S data format \hideinitializer */
#define I2S_FORMAT_I2S_MSB (1U << I2S_CTL0_FORMAT_Pos) /*!< I2S MSB data format \hideinitializer */
#define I2S_FORMAT_I2S_LSB (2U << I2S_CTL0_FORMAT_Pos) /*!< I2S LSB data format \hideinitializer */
#define I2S_FORMAT_PCM (4U << I2S_CTL0_FORMAT_Pos) /*!< PCM data format \hideinitializer */
#define I2S_FORMAT_PCM_MSB (5U << I2S_CTL0_FORMAT_Pos) /*!< PCM MSB data format \hideinitializer */
#define I2S_FORMAT_PCM_LSB (6U << I2S_CTL0_FORMAT_Pos) /*!< PCM LSB data format \hideinitializer */
/* I2S Data Format */
#define I2S_ORDER_AT_MSB (0U) /*!< Channel data is at MSB \hideinitializer */
#define I2S_ORDER_AT_LSB I2S_CTL0_ORDER_Msk /*!< Channel data is at LSB \hideinitializer */
/* I2S TDM Channel Number */
#define I2S_TDM_2CH 0U /*!< Use TDM 2 channel \hideinitializer */
#define I2S_TDM_4CH 1U /*!< Use TDM 4 channel \hideinitializer */
#define I2S_TDM_6CH 2U /*!< Use TDM 6 channel \hideinitializer */
#define I2S_TDM_8CH 3U /*!< Use TDM 8 channel \hideinitializer */
/* I2S TDM Channel Width */
#define I2S_TDM_WIDTH_8BIT 0U /*!< TDM channel witch is 8-bit \hideinitializer */
#define I2S_TDM_WIDTH_16BIT 1U /*!< TDM channel witch is 16-bit \hideinitializer */
#define I2S_TDM_WIDTH_24BIT 2U /*!< TDM channel witch is 24-bit \hideinitializer */
#define I2S_TDM_WIDTH_32BIT 3U /*!< TDM channel witch is 32-bit \hideinitializer */
/* I2S TDM Sync Width */
#define I2S_TDM_SYNC_ONE_BCLK 0U /*!< TDM sync widht is one BLCK period \hideinitializer */
#define I2S_TDM_SYNC_ONE_CHANNEL 1U /*!< TDM sync widht is one channel period \hideinitializer */
/* I2S Operation mode */
#define I2S_MODE_SLAVE I2S_CTL0_SLAVE_Msk /*!< As slave mode \hideinitializer */
#define I2S_MODE_MASTER (0u) /*!< As master mode \hideinitializer */
/* I2S FIFO Threshold */
#define I2S_FIFO_TX_LEVEL_WORD_0 (0U) /*!< TX threshold is 0 word \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_1 (1U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 1 word \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_2 (2U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 2 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_3 (3U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 3 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_4 (4U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 4 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_5 (5U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 5 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_6 (6U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 6 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_7 (7U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 7 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_8 (8U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 8 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_9 (9U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 9 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_10 (10U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 10 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_11 (11U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 11 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_12 (12U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 12 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_13 (13U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 13 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_14 (14U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 14 words \hideinitializer */
#define I2S_FIFO_TX_LEVEL_WORD_15 (15U << I2S_CTL1_TXTH_Pos) /*!< TX threshold is 15 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_1 (0U) /*!< RX threshold is 1 word \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_2 (1U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 2 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_3 (2U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 3 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_4 (3U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 4 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_5 (4U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 5 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_6 (5U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 6 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_7 (6U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 7 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_8 (7U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 8 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_9 (8U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 9 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_10 (9U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 10 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_11 (10U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 11 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_12 (11U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 12 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_13 (12U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 13 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_14 (13U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 14 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_15 (14U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 15 words \hideinitializer */
#define I2S_FIFO_RX_LEVEL_WORD_16 (15U << I2S_CTL1_RXTH_Pos) /*!< RX threshold is 16 words \hideinitializer */
/* I2S Record Channel */
#define I2S_MONO_RIGHT (0U) /*!< Record mono right channel \hideinitializer */
#define I2S_MONO_LEFT I2S_CTL0_RXLCH_Msk /*!< Record mono left channel \hideinitializer */
/* I2S Channel */
#define I2S_RIGHT (0U) /*!< Select right channel \hideinitializer */
#define I2S_LEFT (1U) /*!< Select left channel \hideinitializer */
/*@}*/ /* end of group M480_I2S_EXPORTED_CONSTANTS */
/** @addtogroup M480_I2S_EXPORTED_FUNCTIONS I2S Exported Functions
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* inline functions */
/*---------------------------------------------------------------------------------------------------------*/
/**
* @brief Enable zero cross detect function.
* @param[in] i2s is the base address of I2S module.
* @param[in] u32ChMask is the mask for channel number (valid value is from (1~8).
* @return none
* \hideinitializer
*/
static __INLINE void I2S_ENABLE_TX_ZCD(I2S_T *i2s, uint32_t u32ChMask)
{
if((u32ChMask > 0U) && (u32ChMask < 9U)) {
i2s->CTL1 |= ((uint32_t)1U << (u32ChMask-1U));
}
}
/**
* @brief Disable zero cross detect function.
* @param[in] i2s is the base address of I2S module.
* @param[in] u32ChMask is the mask for channel number (valid value is from (1~8).
* @return none
* \hideinitializer
*/
static __INLINE void I2S_DISABLE_TX_ZCD(I2S_T *i2s, uint32_t u32ChMask)
{
if((u32ChMask > 0U) && (u32ChMask < 9U)) {
i2s->CTL1 &= ~((uint32_t)1U << (u32ChMask-1U));
}
}
/**
* @brief Enable I2S Tx DMA function. I2S requests DMA to transfer data to Tx FIFO.
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_ENABLE_TXDMA(i2s) ( (i2s)->CTL0 |= I2S_CTL0_TXPDMAEN_Msk )
/**
* @brief Disable I2S Tx DMA function. I2S requests DMA to transfer data to Tx FIFO.
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_DISABLE_TXDMA(i2s) ( (i2s)->CTL0 &= ~I2S_CTL0_TXPDMAEN_Msk )
/**
* @brief Enable I2S Rx DMA function. I2S requests DMA to transfer data from Rx FIFO.
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_ENABLE_RXDMA(i2s) ( (i2s)->CTL0 |= I2S_CTL0_RXPDMAEN_Msk )
/**
* @brief Disable I2S Rx DMA function. I2S requests DMA to transfer data from Rx FIFO.
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_DISABLE_RXDMA(i2s) ( (i2s)->CTL0 &= ~I2S_CTL0_RXPDMAEN_Msk )
/**
* @brief Enable I2S Tx function .
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_ENABLE_TX(i2s) ( (i2s)->CTL0 |= I2S_CTL0_TXEN_Msk )
/**
* @brief Disable I2S Tx function .
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_DISABLE_TX(i2s) ( (i2s)->CTL0 &= ~I2S_CTL0_TXEN_Msk )
/**
* @brief Enable I2S Rx function .
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_ENABLE_RX(i2s) ( (i2s)->CTL0 |= I2S_CTL0_RXEN_Msk )
/**
* @brief Disable I2S Rx function .
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_DISABLE_RX(i2s) ( (i2s)->CTL0 &= ~I2S_CTL0_RXEN_Msk )
/**
* @brief Enable Tx Mute function .
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_ENABLE_TX_MUTE(i2s) ( (i2s)->CTL0 |= I2S_CTL0_MUTE_Msk )
/**
* @brief Disable Tx Mute function .
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_DISABLE_TX_MUTE(i2s) ( (i2s)->CTL0 &= ~I2S_CTL0_MUTE_Msk )
/**
* @brief Clear Tx FIFO. Internal pointer is reset to FIFO start point.
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_CLR_TX_FIFO(i2s) ( (i2s)->CTL0 |= I2S_CTL0_TXFBCLR_Msk )
/**
* @brief Clear Rx FIFO. Internal pointer is reset to FIFO start point.
* @param[in] i2s is the base address of I2S module.
* @return none
* \hideinitializer
*/
#define I2S_CLR_RX_FIFO(i2s) ( (i2s)->CTL0 |= I2S_CTL0_RXFBCLR_Msk )
/**
* @brief This function sets the recording source channel when mono mode is used.
* @param[in] i2s is the base address of I2S module.
* @param[in] u32Ch left or right channel. Valid values are:
* - \ref I2S_MONO_LEFT
* - \ref I2S_MONO_RIGHT
* @return none
* \hideinitializer
*/
static __INLINE void I2S_SET_MONO_RX_CHANNEL(I2S_T *i2s, uint32_t u32Ch)
{
u32Ch == I2S_MONO_LEFT ?
(i2s->CTL0 |= I2S_CTL0_RXLCH_Msk) :
(i2s->CTL0 &= ~I2S_CTL0_RXLCH_Msk);
}
/**
* @brief Write data to I2S Tx FIFO.
* @param[in] i2s is the base address of I2S module.
* @param[in] u32Data: The data written to FIFO.
* @return none
* \hideinitializer
*/
#define I2S_WRITE_TX_FIFO(i2s, u32Data) ( (i2s)->TXFIFO = (u32Data) )
/**
* @brief Read Rx FIFO.
* @param[in] i2s is the base address of I2S module.
* @return Data in Rx FIFO.
* \hideinitializer
*/
#define I2S_READ_RX_FIFO(i2s) ( (i2s)->RXFIFO )
/**
* @brief This function gets the interrupt flag according to the mask parameter.
* @param[in] i2s is the base address of I2S module.
* @param[in] u32Mask is the mask for the all interrupt flags.
* @return The masked bit value of interrupt flag.
* \hideinitializer
*/
#define I2S_GET_INT_FLAG(i2s, u32Mask) ( (i2s)->STATUS0 & (u32Mask) )
/**
* @brief This function clears the interrupt flag according to the mask parameter.
* @param[in] i2s is the base address of I2S module.
* @param[in] u32Mask is the mask for the all interrupt flags.
* @return none
* \hideinitializer
*/
#define I2S_CLR_INT_FLAG(i2s, u32Mask) ( (i2s)->STATUS0 |= (u32Mask) )
/**
* @brief This function gets the zero crossing interrupt flag according to the mask parameter.
* @param[in] i2s is the base address of I2S module.
* @param[in] u32Mask is the mask for the all interrupt flags.
* @return The masked bit value of interrupt flag.
* \hideinitializer
*/
#define I2S_GET_ZC_INT_FLAG(i2s, u32Mask) ( (i2s)->STATUS1 & (u32Mask) )
/**
* @brief This function clears the zero crossing interrupt flag according to the mask parameter.
* @param[in] i2s is the base address of I2S module.
* @param[in] u32Mask is the mask for the all interrupt flags.
* @return none
* \hideinitializer
*/
#define I2S_CLR_ZC_INT_FLAG(i2s, u32Mask) ( (i2s)->STATUS1 |= (u32Mask) )
/**
* @brief Get transmit FIFO level
* @param[in] i2s is the base address of I2S module.
* @return FIFO level
* \hideinitializer
*/
#define I2S_GET_TX_FIFO_LEVEL(i2s) ( (((i2s)->STATUS1 & I2S_STATUS1_TXCNT_Msk) >> I2S_STATUS1_TXCNT_Pos) & 0xF )
/**
* @brief Get receive FIFO level
* @param[in] i2s is the base address of I2S module.
* @return FIFO level
* \hideinitializer
*/
#define I2S_GET_RX_FIFO_LEVEL(i2s) ( (((i2s)->STATUS1 & I2S_STATUS1_RXCNT_Msk) >> I2S_STATUS1_RXCNT_Pos) & 0xF )
void I2S_Close(I2S_T *i2s);
void I2S_EnableInt(I2S_T *i2s, uint32_t u32Mask);
void I2S_DisableInt(I2S_T *i2s, uint32_t u32Mask);
uint32_t I2S_EnableMCLK(I2S_T *i2s, uint32_t u32BusClock);
void I2S_DisableMCLK(I2S_T *i2s);
void I2S_SetFIFO(I2S_T *i2s, uint32_t u32TxThreshold, uint32_t u32RxThreshold);
void I2S_ConfigureTDM(I2S_T *i2s, uint32_t u32ChannelWidth, uint32_t u32ChannelNum, uint32_t u32SyncWidth);
uint32_t I2S_Open(I2S_T *i2s, uint32_t u32MasterSlave, uint32_t u32SampleRate, uint32_t u32WordWidth, uint32_t u32MonoData, uint32_t u32DataFormat);
/*@}*/ /* end of group M480_I2S_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_I2S_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,190 @@
/**************************************************************************//**
* @file opa.h
* @version V3.00
* @brief M480 series OPA driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __OPA_H__
#define __OPA_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup OPA_Driver OPA Driver
@{
*/
/** @addtogroup OPA_EXPORTED_CONSTANTS OPA Exported Constants
@{
*/
#define OPA_CALIBRATION_CLK_1K (0UL) /*!< OPA calibration clock select 1 KHz \hideinitializer */
#define OPA_CALIBRATION_RV_1_2_AVDD (0UL) /*!< OPA calibration reference voltage select 1/2 AVDD \hideinitializer */
#define OPA_CALIBRATION_RV_H_L_VCM (1UL) /*!< OPA calibration reference voltage select from high vcm to low vcm \hideinitializer */
/*@}*/ /* end of group OPA_EXPORTED_CONSTANTS */
/** @addtogroup OPA_EXPORTED_FUNCTIONS OPA Exported Functions
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* Define OPA functions prototype */
/*---------------------------------------------------------------------------------------------------------*/
__STATIC_INLINE int32_t OPA_Calibration(OPA_T *opa, uint32_t u32OpaNum, uint32_t u32ClockSel, uint32_t u32LevelSel);
/**
* @brief This macro is used to power on the OPA circuit
* @param[in] opa The pointer of the specified OPA module
* @param[in] u32OpaNum The OPA number. 0 for OPA0; 1 for OPA1; 2 for OPA2.
* @return None
* @details This macro will set OPx_EN (x=0, 1) bit of OPACR register to power on the OPA circuit.
* \hideinitializer
*/
#define OPA_POWER_ON(opa, u32OpaNum) ((opa)->CTL |= (1UL<<(OPA_CTL_OPEN0_Pos+(u32OpaNum))))
/**
* @brief This macro is used to power down the OPA circuit
* @param[in] opa The pointer of the specified OPA module
* @param[in] u32OpaNum The OPA number. 0 for OPA0; 1 for OPA1; 2 for OPA2.
* @return None
* @details This macro will clear OPx_EN (x=0, 1) bit of OPACR register to power down the OPA circuit.
* \hideinitializer
*/
#define OPA_POWER_DOWN(opa, u32OpaNum) ((opa)->CTL &= ~(1UL<<(OPA_CTL_OPEN0_Pos+(u32OpaNum))))
/**
* @brief This macro is used to enable the OPA Schmitt trigger buffer
* @param[in] opa The pointer of the specified OPA module
* @param[in] u32OpaNum The OPA number. 0 for OPA0; 1 for OPA1; 2 for OPA2.
* @return None
* @details This macro will set OPSCHx_EN (x=0, 1) bit of OPACR register to enable the OPA Schmitt trigger buffer.
* \hideinitializer
*/
#define OPA_ENABLE_SCH_TRIGGER(opa, u32OpaNum) ((opa)->CTL |= (1UL<<(OPA_CTL_OPDOEN0_Pos+(u32OpaNum))))
/**
* @brief This macro is used to disable the OPA Schmitt trigger buffer
* @param[in] opa The pointer of the specified OPA module
* @param[in] u32OpaNum The OPA number. 0 for OPA0; 1 for OPA1; 2 for OPA2.
* @return None
* @details This macro will clear OPSCHx_EN (x=0, 1) bit of OPACR register to disable the OPA Schmitt trigger buffer.
* \hideinitializer
*/
#define OPA_DISABLE_SCH_TRIGGER(opa, u32OpaNum) ((opa)->CTL &= ~(1UL<<(OPA_CTL_OPDOEN0_Pos+(u32OpaNum))))
/**
* @brief This macro is used to enable OPA Schmitt trigger digital output interrupt
* @param[in] opa The pointer of the specified OPA module
* @param[in] u32OpaNum The OPA number. 0 for OPA0; 1 for OPA1; 2 for OPA2.
* @return None
* @details This macro will set OPDIEx (x=0, 1) bit of OPACR register to enable the OPA Schmitt trigger digital output interrupt.
* \hideinitializer
*/
#define OPA_ENABLE_INT(opa, u32OpaNum) ((opa)->CTL |= (1UL<<(OPA_CTL_OPDOIEN0_Pos+(u32OpaNum))))
/**
* @brief This macro is used to disable OPA Schmitt trigger digital output interrupt
* @param[in] opa The pointer of the specified OPA module
* @param[in] u32OpaNum The OPA number. 0 for OPA0; 1 for OPA1; 2 for OPA2.
* @return None
* @details This macro will clear OPDIEx (x=0, 1) bit of OPACR register to disable the OPA Schmitt trigger digital output interrupt.
* \hideinitializer
*/
#define OPA_DISABLE_INT(opa, u32OpaNum) ((opa)->CTL &= ~(1UL<<(OPA_CTL_OPDOIEN0_Pos+(u32OpaNum))))
/**
* @brief This macro is used to get OPA digital output state
* @param[in] opa The pointer of the specified OPA module
* @param[in] u32OpaNum The OPA number. 0 for OPA0; 1 for OPA1; 2 for OPA2.
* @return OPA digital output state
* @details This macro will return the OPA digital output value.
* \hideinitializer
*/
#define OPA_GET_DIGITAL_OUTPUT(opa, u32OpaNum) (((opa)->STATUS & (OPA_STATUS_OPDO0_Msk<<(u32OpaNum)))?1UL:0UL)
/**
* @brief This macro is used to get OPA interrupt flag
* @param[in] opa The pointer of the specified OPA module
* @param[in] u32OpaNum The OPA number. 0 for OPA0; 1 for OPA1; 2 for OPA2.
* @retval 0 OPA interrupt does not occur.
* @retval 1 OPA interrupt occurs.
* @details This macro will return the ACMP interrupt flag.
* \hideinitializer
*/
#define OPA_GET_INT_FLAG(opa, u32OpaNum) (((opa)->STATUS & (OPA_STATUS_OPDOIF0_Msk<<(u32OpaNum)))?1UL:0UL)
/**
* @brief This macro is used to clear OPA interrupt flag
* @param[in] opa The pointer of the specified OPA module
* @param[in] u32OpaNum The OPA number. 0 for OPA0; 1 for OPA1; 2 for OPA2.
* @return None
* @details This macro will write 1 to OPDFx (x=0,1) bit of OPASR register to clear interrupt flag.
* \hideinitializer
*/
#define OPA_CLR_INT_FLAG(opa, u32OpaNum) ((opa)->STATUS = (OPA_STATUS_OPDOIF0_Msk<<(u32OpaNum)))
/**
* @brief This function is used to configure and start OPA calibration
* @param[in] opa The pointer of the specified OPA module
* @param[in] u32OpaNum The OPA number. 0 for OPA0; 1 for OPA1; 2 for OPA2.
* @param[in] u32ClockSel Select OPA calibration clock
* - \ref OPA_CALIBRATION_CLK_1K
* @param[in] u32RefVol Select OPA reference voltage
* - \ref OPA_CALIBRATION_RV_1_2_AVDD
* - \ref OPA_CALIBRATION_RV_H_L_VCM
* @retval 0 PMOS and NMOS calibration successfully.
* @retval -1 only PMOS calibration failed.
* @retval -2 only NMOS calibration failed.
* @retval -3 PMOS and NMOS calibration failed.
*/
__STATIC_INLINE int32_t OPA_Calibration(OPA_T *opa,
uint32_t u32OpaNum,
uint32_t u32ClockSel,
uint32_t u32RefVol)
{
uint32_t u32CALResult;
int32_t i32Ret = 0L;
(opa)->CALCTL = (((opa)->CALCTL) & ~(OPA_CALCTL_CALCLK0_Msk << (u32OpaNum << 1)));
(opa)->CALCTL = (((opa)->CALCTL) & ~(OPA_CALCTL_CALRVS0_Msk << (u32OpaNum))) | (((u32RefVol) << OPA_CALCTL_CALRVS0_Pos) << (u32OpaNum));
(opa)->CALCTL |= (OPA_CALCTL_CALTRG0_Msk << (u32OpaNum));
while((opa)->CALCTL & (OPA_CALCTL_CALTRG0_Msk << (u32OpaNum))){}
u32CALResult = ((opa)->CALST >> ((u32OpaNum)*4U)) & (OPA_CALST_CALNS0_Msk|OPA_CALST_CALPS0_Msk);
if (u32CALResult == 0U) {
i32Ret = 0L;
} else if (u32CALResult == OPA_CALST_CALNS0_Msk) {
i32Ret = -2L;
} else if (u32CALResult == OPA_CALST_CALPS0_Msk) {
i32Ret = -1L;
} else if (u32CALResult == (OPA_CALST_CALNS0_Msk|OPA_CALST_CALPS0_Msk)) {
i32Ret = -3L;
}
return i32Ret;
}
/*@}*/ /* end of group OPA_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group OPA_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __OPA_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,268 @@
/**************************************************************************//**
* @file otg.h
* @version V0.10
* @brief M480 Series OTG Driver Header File
*
* @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#ifndef __OTG_H__
#define __OTG_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_OTG_Driver OTG Driver
@{
*/
/** @addtogroup M480_OTG_EXPORTED_CONSTANTS OTG Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* OTG constant definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define OTG_VBUS_EN_ACTIVE_HIGH (0UL) /*!< USB VBUS power switch enable signal is active high. \hideinitializer */
#define OTG_VBUS_EN_ACTIVE_LOW (1UL) /*!< USB VBUS power switch enable signal is active low. \hideinitializer */
#define OTG_VBUS_ST_VALID_HIGH (0UL) /*!< USB VBUS power switch valid status is high. \hideinitializer */
#define OTG_VBUS_ST_VALID_LOW (1UL) /*!< USB VBUS power switch valid status is low. \hideinitializer */
/*@}*/ /* end of group M480_OTG_EXPORTED_CONSTANTS */
/** @addtogroup M480_OTG_EXPORTED_FUNCTIONS OTG Exported Functions
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* Define Macros and functions */
/*---------------------------------------------------------------------------------------------------------*/
/**
* @brief This macro is used to enable OTG function
* @param None
* @return None
* @details This macro will set OTGEN bit of OTG_CTL register to enable OTG function.
* \hideinitializer
*/
#define OTG_ENABLE() (OTG->CTL |= OTG_CTL_OTGEN_Msk)
/**
* @brief This macro is used to disable OTG function
* @param None
* @return None
* @details This macro will clear OTGEN bit of OTG_CTL register to disable OTG function.
* \hideinitializer
*/
#define OTG_DISABLE() (OTG->CTL &= ~OTG_CTL_OTGEN_Msk)
/**
* @brief This macro is used to enable USB PHY
* @param None
* @return None
* @details When the USB role is selected as OTG device, use this macro to enable USB PHY.
* This macro will set OTGPHYEN bit of OTG_PHYCTL register to enable USB PHY.
* \hideinitializer
*/
#define OTG_ENABLE_PHY() (OTG->PHYCTL |= OTG_PHYCTL_OTGPHYEN_Msk)
/**
* @brief This macro is used to disable USB PHY
* @param None
* @return None
* @details This macro will clear OTGPHYEN bit of OTG_PHYCTL register to disable USB PHY.
* \hideinitializer
*/
#define OTG_DISABLE_PHY() (OTG->PHYCTL &= ~OTG_PHYCTL_OTGPHYEN_Msk)
/**
* @brief This macro is used to enable ID detection function
* @param None
* @return None
* @details This macro will set IDDETEN bit of OTG_PHYCTL register to enable ID detection function.
* \hideinitializer
*/
#define OTG_ENABLE_ID_DETECT() (OTG->PHYCTL |= OTG_PHYCTL_IDDETEN_Msk)
/**
* @brief This macro is used to disable ID detection function
* @param None
* @return None
* @details This macro will clear IDDETEN bit of OTG_PHYCTL register to disable ID detection function.
* \hideinitializer
*/
#define OTG_DISABLE_ID_DETECT() (OTG->PHYCTL &= ~OTG_PHYCTL_IDDETEN_Msk)
/**
* @brief This macro is used to enable OTG wake-up function
* @param None
* @return None
* @details This macro will set WKEN bit of OTG_CTL register to enable OTG wake-up function.
* \hideinitializer
*/
#define OTG_ENABLE_WAKEUP() (OTG->CTL |= OTG_CTL_WKEN_Msk)
/**
* @brief This macro is used to disable OTG wake-up function
* @param None
* @return None
* @details This macro will clear WKEN bit of OTG_CTL register to disable OTG wake-up function.
* \hideinitializer
*/
#define OTG_DISABLE_WAKEUP() (OTG->CTL &= ~OTG_CTL_WKEN_Msk)
/**
* @brief This macro is used to set the polarity of USB_VBUS_EN pin
* @param[in] u32Pol The polarity selection. Valid values are listed below.
* - \ref OTG_VBUS_EN_ACTIVE_HIGH
* - \ref OTG_VBUS_EN_ACTIVE_LOW
* @return None
* @details This macro is used to set the polarity of external USB VBUS power switch enable signal.
* \hideinitializer
*/
#define OTG_SET_VBUS_EN_POL(u32Pol) (OTG->PHYCTL = (OTG->PHYCTL & (~OTG_PHYCTL_VBENPOL_Msk)) | ((u32Pol)<<OTG_PHYCTL_VBENPOL_Pos))
/**
* @brief This macro is used to set the polarity of USB_VBUS_ST pin
* @param[in] u32Pol The polarity selection. Valid values are listed below.
* - \ref OTG_VBUS_ST_VALID_HIGH
* - \ref OTG_VBUS_ST_VALID_LOW
* @return None
* @details This macro is used to set the polarity of external USB VBUS power switch status signal.
* \hideinitializer
*/
#define OTG_SET_VBUS_STS_POL(u32Pol) (OTG->PHYCTL = (OTG->PHYCTL & (~OTG_PHYCTL_VBSTSPOL_Msk)) | ((u32Pol)<<OTG_PHYCTL_VBSTSPOL_Pos))
/**
* @brief This macro is used to enable OTG related interrupts
* @param[in] u32Mask The combination of interrupt source. Each bit corresponds to a interrupt source. Valid values are listed below.
* - \ref OTG_INTEN_ROLECHGIEN_Msk
* - \ref OTG_INTEN_VBEIEN_Msk
* - \ref OTG_INTEN_SRPFIEN_Msk
* - \ref OTG_INTEN_HNPFIEN_Msk
* - \ref OTG_INTEN_GOIDLEIEN_Msk
* - \ref OTG_INTEN_IDCHGIEN_Msk
* - \ref OTG_INTEN_PDEVIEN_Msk
* - \ref OTG_INTEN_HOSTIEN_Msk
* - \ref OTG_INTEN_BVLDCHGIEN_Msk
* - \ref OTG_INTEN_AVLDCHGIEN_Msk
* - \ref OTG_INTEN_VBCHGIEN_Msk
* - \ref OTG_INTEN_SECHGIEN_Msk
* - \ref OTG_INTEN_SRPDETIEN_Msk
* @return None
* @details This macro will enable OTG related interrupts specified by u32Mask parameter.
* \hideinitializer
*/
#define OTG_ENABLE_INT(u32Mask) (OTG->INTEN |= (u32Mask))
/**
* @brief This macro is used to disable OTG related interrupts
* @param[in] u32Mask The combination of interrupt source. Each bit corresponds to a interrupt source. Valid values are listed below.
* - \ref OTG_INTEN_ROLECHGIEN_Msk
* - \ref OTG_INTEN_VBEIEN_Msk
* - \ref OTG_INTEN_SRPFIEN_Msk
* - \ref OTG_INTEN_HNPFIEN_Msk
* - \ref OTG_INTEN_GOIDLEIEN_Msk
* - \ref OTG_INTEN_IDCHGIEN_Msk
* - \ref OTG_INTEN_PDEVIEN_Msk
* - \ref OTG_INTEN_HOSTIEN_Msk
* - \ref OTG_INTEN_BVLDCHGIEN_Msk
* - \ref OTG_INTEN_AVLDCHGIEN_Msk
* - \ref OTG_INTEN_VBCHGIEN_Msk
* - \ref OTG_INTEN_SECHGIEN_Msk
* - \ref OTG_INTEN_SRPDETIEN_Msk
* @return None
* @details This macro will disable OTG related interrupts specified by u32Mask parameter.
* \hideinitializer
*/
#define OTG_DISABLE_INT(u32Mask) (OTG->INTEN &= ~(u32Mask))
/**
* @brief This macro is used to get OTG related interrupt flags
* @param[in] u32Mask The combination of interrupt source. Each bit corresponds to a interrupt source. Valid values are listed below.
* - \ref OTG_INTSTS_ROLECHGIF_Msk
* - \ref OTG_INTSTS_VBEIF_Msk
* - \ref OTG_INTSTS_SRPFIF_Msk
* - \ref OTG_INTSTS_HNPFIF_Msk
* - \ref OTG_INTSTS_GOIDLEIF_Msk
* - \ref OTG_INTSTS_IDCHGIF_Msk
* - \ref OTG_INTSTS_PDEVIF_Msk
* - \ref OTG_INTSTS_HOSTIF_Msk
* - \ref OTG_INTSTS_BVLDCHGIF_Msk
* - \ref OTG_INTSTS_AVLDCHGIF_Msk
* - \ref OTG_INTSTS_VBCHGIF_Msk
* - \ref OTG_INTSTS_SECHGIF_Msk
* - \ref OTG_INTSTS_SRPDETIF_Msk
* @return Interrupt flags of selected sources.
* @details This macro will return OTG related interrupt flags specified by u32Mask parameter.
* \hideinitializer
*/
#define OTG_GET_INT_FLAG(u32Mask) (OTG->INTSTS & (u32Mask))
/**
* @brief This macro is used to clear OTG related interrupt flags
* @param[in] u32Mask The combination of interrupt source. Each bit corresponds to a interrupt source. Valid values are listed below.
* - \ref OTG_INTSTS_ROLECHGIF_Msk
* - \ref OTG_INTSTS_VBEIF_Msk
* - \ref OTG_INTSTS_SRPFIF_Msk
* - \ref OTG_INTSTS_HNPFIF_Msk
* - \ref OTG_INTSTS_GOIDLEIF_Msk
* - \ref OTG_INTSTS_IDCHGIF_Msk
* - \ref OTG_INTSTS_PDEVIF_Msk
* - \ref OTG_INTSTS_HOSTIF_Msk
* - \ref OTG_INTSTS_BVLDCHGIF_Msk
* - \ref OTG_INTSTS_AVLDCHGIF_Msk
* - \ref OTG_INTSTS_VBCHGIF_Msk
* - \ref OTG_INTSTS_SECHGIF_Msk
* - \ref OTG_INTSTS_SRPDETIF_Msk
* @return None
* @details This macro will clear OTG related interrupt flags specified by u32Mask parameter.
* \hideinitializer
*/
#define OTG_CLR_INT_FLAG(u32Mask) (OTG->INTSTS = (u32Mask))
/**
* @brief This macro is used to get OTG related status
* @param[in] u32Mask The combination of user specified source. Valid values are listed below.
* - \ref OTG_STATUS_OVERCUR_Msk
* - \ref OTG_STATUS_IDSTS_Msk
* - \ref OTG_STATUS_SESSEND_Msk
* - \ref OTG_STATUS_BVLD_Msk
* - \ref OTG_STATUS_AVLD_Msk
* - \ref OTG_STATUS_VBUSVLD_Msk
* @return The user specified status.
* @details This macro will return OTG related status specified by u32Mask parameter.
* \hideinitializer
*/
#define OTG_GET_STATUS(u32Mask) (OTG->STATUS & (u32Mask))
/*@}*/ /* end of group M480_OTG_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_OTG_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /*__OTG_H__ */
/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,419 @@
/**************************************************************************//**
* @file pdma.c
* @version V1.00
* $Revision: 1 $
* $Date: 16/06/14 10:23a $
* @brief M480 series PDMA driver source file
*
* @note
* @copyright (C) 2014~2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
static uint32_t u32ChSelect[PDMA_CH_MAX];
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup PDMA_Driver PDMA Driver
@{
*/
/** @addtogroup PDMA_EXPORTED_FUNCTIONS PDMA Exported Functions
@{
*/
/**
* @brief PDMA Open
*
* @param[in] u32Mask Channel enable bits.
*
* @return None
*
* @details This function enable the PDMA channels.
*/
void PDMA_Open(uint32_t u32Mask)
{
uint32_t i;
for (i=0UL; i<PDMA_CH_MAX; i++) {
PDMA->DSCT[i].CTL = 0UL;
u32ChSelect[i] = PDMA_MEM;
}
PDMA->CHCTL |= u32Mask;
}
/**
* @brief PDMA Close
*
* @param None
*
* @return None
*
* @details This function disable all PDMA channels.
*/
void PDMA_Close(void)
{
PDMA->CHCTL = 0UL;
}
/**
* @brief Set PDMA Transfer Count
*
* @param[in] u32Ch The selected channel
* @param[in] u32Width Data width. Valid values are
* - \ref PDMA_WIDTH_8
* - \ref PDMA_WIDTH_16
* - \ref PDMA_WIDTH_32
* @param[in] u32TransCount Transfer count
*
* @return None
*
* @details This function set the selected channel data width and transfer count.
*/
void PDMA_SetTransferCnt(uint32_t u32Ch, uint32_t u32Width, uint32_t u32TransCount)
{
PDMA->DSCT[u32Ch].CTL &= ~(PDMA_DSCT_CTL_TXCNT_Msk | PDMA_DSCT_CTL_TXWIDTH_Msk);
PDMA->DSCT[u32Ch].CTL |= (u32Width | ((u32TransCount - 1UL) << PDMA_DSCT_CTL_TXCNT_Pos));
}
/**
* @brief Set PDMA Stride Mode
*
* @param[in] u32Ch The selected channel
* @param[in] u32DestLen Destination stride count
* @param[in] u32SrcLen Source stride count
* @param[in] u32TransCount Transfer count
*
* @return None
*
* @details This function set the selected stride mode.
*/
void PDMA_SetStride(uint32_t u32Ch, uint32_t u32DestLen, uint32_t u32SrcLen, uint32_t u32TransCount)
{
PDMA->DSCT[u32Ch].CTL |= PDMA_DSCT_CTL_STRIDEEN_Msk;
PDMA->STRIDE[u32Ch].ASOCR =(u32DestLen<<16) | u32SrcLen;
PDMA->STRIDE[u32Ch].STCR = u32TransCount;
}
/**
* @brief Set PDMA Transfer Address
*
* @param[in] u32Ch The selected channel
* @param[in] u32SrcAddr Source address
* @param[in] u32SrcCtrl Source control attribute. Valid values are
* - \ref PDMA_SAR_INC
* - \ref PDMA_SAR_FIX
* @param[in] u32DstAddr destination address
* @param[in] u32DstCtrl destination control attribute. Valid values are
* - \ref PDMA_DAR_INC
* - \ref PDMA_DAR_FIX
*
* @return None
*
* @details This function set the selected channel source/destination address and attribute.
*/
void PDMA_SetTransferAddr(uint32_t u32Ch, uint32_t u32SrcAddr, uint32_t u32SrcCtrl, uint32_t u32DstAddr, uint32_t u32DstCtrl)
{
PDMA->DSCT[u32Ch].SA = u32SrcAddr;
PDMA->DSCT[u32Ch].DA = u32DstAddr;
PDMA->DSCT[u32Ch].CTL &= ~(PDMA_DSCT_CTL_SAINC_Msk | PDMA_DSCT_CTL_DAINC_Msk);
PDMA->DSCT[u32Ch].CTL |= (u32SrcCtrl | u32DstCtrl);
}
/**
* @brief Set PDMA Transfer Mode
*
* @param[in] u32Ch The selected channel
* @param[in] u32Peripheral The selected peripheral. Valid values are
* - \ref PDMA_MEM
* - \ref PDMA_USB_TX
* - \ref PDMA_USB_RX
* - \ref PDMA_UART0_TX
* - \ref PDMA_UART0_RX
* - \ref PDMA_UART1_TX
* - \ref PDMA_UART1_RX
* - \ref PDMA_UART2_TX
* - \ref PDMA_UART2_RX
* - \ref PDMA_UART3_TX
* - \ref PDMA_UART3_RX
* - \ref PDMA_UART4_TX
* - \ref PDMA_UART4_RX
* - \ref PDMA_UART5_TX
* - \ref PDMA_UART5_RX
* - \ref PDMA_USCI0_TX
* - \ref PDMA_USCI0_RX
* - \ref PDMA_USCI1_TX
* - \ref PDMA_USCI1_RX
* - \ref PDMA_SPI0_TX
* - \ref PDMA_SPI0_RX
* - \ref PDMA_SPI1_TX
* - \ref PDMA_SPI1_RX
* - \ref PDMA_SPI2_TX
* - \ref PDMA_SPI2_RX
* - \ref PDMA_SPI3_TX
* - \ref PDMA_SPI3_RX
* - \ref PDMA_SPI4_TX
* - \ref PDMA_SPI4_RX
* - \ref PDMA_EPWM0_P1_RX
* - \ref PDMA_EPWM0_P2_RX
* - \ref PDMA_EPWM0_P3_RX
* - \ref PDMA_EPWM1_P1_RX
* - \ref PDMA_EPWM1_P2_RX
* - \ref PDMA_EPWM1_P3_RX
* - \ref PDMA_I2C0_TX
* - \ref PDMA_I2C0_RX
* - \ref PDMA_I2C1_TX
* - \ref PDMA_I2C1_RX
* - \ref PDMA_I2C2_TX
* - \ref PDMA_I2C2_RX
* - \ref PDMA_I2S0_TX
* - \ref PDMA_I2S0_RX
* - \ref PDMA_TMR0
* - \ref PDMA_TMR1
* - \ref PDMA_TMR2
* - \ref PDMA_TMR3
* - \ref PDMA_ADC_RX
* - \ref PDMA_DAC0_TX
* - \ref PDMA_DAC1_TX
* @param[in] u32ScatterEn Scatter-gather mode enable
* @param[in] u32DescAddr Scatter-gather descriptor address
*
* @return None
*
* @details This function set the selected channel transfer mode. Include peripheral setting.
*/
void PDMA_SetTransferMode(uint32_t u32Ch, uint32_t u32Peripheral, uint32_t u32ScatterEn, uint32_t u32DescAddr)
{
u32ChSelect[u32Ch] = u32Peripheral;
switch(u32Ch) {
case 0ul:
PDMA->REQSEL0_3 = (PDMA->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC0_Msk) | u32Peripheral;
break;
case 1ul:
PDMA->REQSEL0_3 = (PDMA->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC1_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC1_Pos);
break;
case 2ul:
PDMA->REQSEL0_3 = (PDMA->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC2_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC2_Pos);
break;
case 3ul:
PDMA->REQSEL0_3 = (PDMA->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC3_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC3_Pos);
break;
case 4ul:
PDMA->REQSEL4_7 = (PDMA->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC4_Msk) | u32Peripheral;
break;
case 5ul:
PDMA->REQSEL4_7 = (PDMA->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC5_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC5_Pos);
break;
case 6ul:
PDMA->REQSEL4_7 = (PDMA->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC6_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC6_Pos);
break;
case 7ul:
PDMA->REQSEL4_7 = (PDMA->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC7_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC7_Pos);
break;
case 8ul:
PDMA->REQSEL8_11 = (PDMA->REQSEL8_11 & ~PDMA_REQSEL8_11_REQSRC8_Msk) | u32Peripheral;
break;
case 9ul:
PDMA->REQSEL8_11 = (PDMA->REQSEL8_11 & ~PDMA_REQSEL8_11_REQSRC9_Msk) | (u32Peripheral << PDMA_REQSEL8_11_REQSRC9_Pos);
break;
case 10ul:
PDMA->REQSEL8_11 = (PDMA->REQSEL8_11 & ~PDMA_REQSEL8_11_REQSRC10_Msk) | (u32Peripheral << PDMA_REQSEL8_11_REQSRC10_Pos);
break;
case 11ul:
PDMA->REQSEL8_11 = (PDMA->REQSEL8_11 & ~PDMA_REQSEL8_11_REQSRC11_Msk) | (u32Peripheral << PDMA_REQSEL8_11_REQSRC11_Pos);
break;
case 12ul:
PDMA->REQSEL12_15 = (PDMA->REQSEL12_15 & ~PDMA_REQSEL12_15_REQSRC12_Msk) | u32Peripheral;
break;
case 13ul:
PDMA->REQSEL12_15 = (PDMA->REQSEL12_15 & ~PDMA_REQSEL12_15_REQSRC13_Msk) | (u32Peripheral << PDMA_REQSEL12_15_REQSRC13_Pos);
break;
case 14ul:
PDMA->REQSEL12_15 = (PDMA->REQSEL12_15 & ~PDMA_REQSEL12_15_REQSRC14_Msk) | (u32Peripheral << PDMA_REQSEL12_15_REQSRC14_Pos);
break;
case 15ul:
PDMA->REQSEL12_15 = (PDMA->REQSEL12_15 & ~PDMA_REQSEL12_15_REQSRC15_Msk) | (u32Peripheral << PDMA_REQSEL12_15_REQSRC15_Pos);
break;
default:
break;
}
if(u32ScatterEn) {
PDMA->DSCT[u32Ch].CTL = (PDMA->DSCT[u32Ch].CTL & ~PDMA_DSCT_CTL_OPMODE_Msk) | PDMA_OP_SCATTER;
PDMA->DSCT[u32Ch].NEXT = u32DescAddr - (PDMA->SCATBA);
} else {
PDMA->DSCT[u32Ch].CTL = (PDMA->DSCT[u32Ch].CTL & ~PDMA_DSCT_CTL_OPMODE_Msk) | PDMA_OP_BASIC;
}
}
/**
* @brief Set PDMA Burst Type and Size
*
* @param[in] u32Ch The selected channel
* @param[in] u32BurstType Burst mode or single mode. Valid values are
* - \ref PDMA_REQ_SINGLE
* - \ref PDMA_REQ_BURST
* @param[in] u32BurstSize Set the size of burst mode. Valid values are
* - \ref PDMA_BURST_128
* - \ref PDMA_BURST_64
* - \ref PDMA_BURST_32
* - \ref PDMA_BURST_16
* - \ref PDMA_BURST_8
* - \ref PDMA_BURST_4
* - \ref PDMA_BURST_2
* - \ref PDMA_BURST_1
*
* @return None
*
* @details This function set the selected channel burst type and size.
*/
void PDMA_SetBurstType(uint32_t u32Ch, uint32_t u32BurstType, uint32_t u32BurstSize)
{
PDMA->DSCT[u32Ch].CTL &= ~(PDMA_DSCT_CTL_TXTYPE_Msk | PDMA_DSCT_CTL_BURSIZE_Msk);
PDMA->DSCT[u32Ch].CTL |= (u32BurstType | u32BurstSize);
}
/**
* @brief Enable timeout function
*
* @param[in] u32Mask Channel enable bits.
*
* @return None
*
* @details This function enable timeout function of the selected channel(s).
*/
void PDMA_EnableTimeout(uint32_t u32Mask)
{
PDMA->TOUTEN |= u32Mask;
}
/**
* @brief Disable timeout function
*
* @param[in] u32Mask Channel enable bits.
*
* @return None
*
* @details This function disable timeout function of the selected channel(s).
*/
void PDMA_DisableTimeout(uint32_t u32Mask)
{
PDMA->TOUTEN &= ~u32Mask;
}
/**
* @brief Set PDMA Timeout Count
*
* @param[in] u32Ch The selected channel,
* @param[in] u32OnOff Enable/disable time out function
* @param[in] u32TimeOutCnt Timeout count
*
* @return None
*
* @details This function set the timeout count.
* @note M480 only supported channel 0/1.
*/
void PDMA_SetTimeOut(uint32_t u32Ch, uint32_t u32OnOff, uint32_t u32TimeOutCnt)
{
switch(u32Ch) {
case 0ul:
PDMA->TOC0_1 = (PDMA->TOC0_1 & ~PDMA_TOC0_1_TOC0_Msk) | u32TimeOutCnt;
break;
case 1ul:
PDMA->TOC0_1 = (PDMA->TOC0_1 & ~PDMA_TOC0_1_TOC1_Msk) | (u32TimeOutCnt << PDMA_TOC0_1_TOC1_Pos);
break;
default:
break;
}
}
/**
* @brief Trigger PDMA
*
* @param[in] u32Ch The selected channel
*
* @return None
*
* @details This function trigger the selected channel.
*/
void PDMA_Trigger(uint32_t u32Ch)
{
if(u32ChSelect[u32Ch] == PDMA_MEM) {
PDMA->SWREQ = (1ul << u32Ch);
} else {}
}
/**
* @brief Enable Interrupt
*
* @param[in] u32Ch The selected channel
* @param[in] u32Mask The Interrupt Type. Valid values are
* - \ref PDMA_INT_TRANS_DONE
* - \ref PDMA_INT_TEMPTY
* - \ref PDMA_INT_TIMEOUT
*
* @return None
*
* @details This function enable the selected channel interrupt.
*/
void PDMA_EnableInt(uint32_t u32Ch, uint32_t u32Mask)
{
switch(u32Mask) {
case PDMA_INT_TRANS_DONE:
PDMA->INTEN |= (1ul << u32Ch);
break;
case PDMA_INT_TEMPTY:
PDMA->DSCT[u32Ch].CTL &= ~PDMA_DSCT_CTL_TBINTDIS_Msk;
break;
case PDMA_INT_TIMEOUT:
PDMA->TOUTIEN |= (1ul << u32Ch);
break;
default:
break;
}
}
/**
* @brief Disable Interrupt
*
* @param[in] u32Ch The selected channel
* @param[in] u32Mask The Interrupt Type. Valid values are
* - \ref PDMA_INT_TRANS_DONE
* - \ref PDMA_INT_TEMPTY
* - \ref PDMA_INT_TIMEOUT
*
* @return None
*
* @details This function disable the selected channel interrupt.
*/
void PDMA_DisableInt(uint32_t u32Ch, uint32_t u32Mask)
{
switch(u32Mask) {
case PDMA_INT_TRANS_DONE:
PDMA->INTEN &= ~(1ul << u32Ch);
break;
case PDMA_INT_TEMPTY:
PDMA->DSCT[u32Ch].CTL |= PDMA_DSCT_CTL_TBINTDIS_Msk;
break;
case PDMA_INT_TIMEOUT:
PDMA->TOUTIEN &= ~(1ul << u32Ch);
break;
default:
break;
}
}
/*@}*/ /* end of group PDMA_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group PDMA_Driver */
/*@}*/ /* end of group Standard_Driver */
/*** (C) COPYRIGHT 2014~2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,369 @@
/**************************************************************************//**
* @file pdma.h
* @version V1.00
* @brief M480 series PDMA driver header file
*
* @copyright (C) 2014~2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __PDMA_H__
#define __PDMA_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup PDMA_Driver PDMA Driver
@{
*/
/** @addtogroup PDMA_EXPORTED_CONSTANTS PDMA Exported Constants
@{
*/
#define PDMA_CH_MAX 16UL /*!< Specify Maximum Channels of PDMA \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Operation Mode Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define PDMA_OP_STOP 0x00000000UL /*!<DMA Stop Mode \hideinitializer */
#define PDMA_OP_BASIC 0x00000001UL /*!<DMA Basic Mode \hideinitializer */
#define PDMA_OP_SCATTER 0x00000002UL /*!<DMA Scatter-gather Mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Data Width Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define PDMA_WIDTH_8 0x00000000UL /*!<DMA Transfer Width 8-bit \hideinitializer */
#define PDMA_WIDTH_16 0x00001000UL /*!<DMA Transfer Width 16-bit \hideinitializer */
#define PDMA_WIDTH_32 0x00002000UL /*!<DMA Transfer Width 32-bit \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Address Attribute Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define PDMA_SAR_INC 0x00000000UL /*!<DMA SAR increment \hideinitializer */
#define PDMA_SAR_FIX 0x00000300UL /*!<DMA SAR fix address \hideinitializer */
#define PDMA_DAR_INC 0x00000000UL /*!<DMA DAR increment \hideinitializer */
#define PDMA_DAR_FIX 0x00000C00UL /*!<DMA DAR fix address \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Burst Mode Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define PDMA_REQ_SINGLE 0x00000004UL /*!<DMA Single Request \hideinitializer */
#define PDMA_REQ_BURST 0x00000000UL /*!<DMA Burst Request \hideinitializer */
#define PDMA_BURST_128 0x00000000UL /*!<DMA Burst 128 Transfers \hideinitializer */
#define PDMA_BURST_64 0x00000010UL /*!<DMA Burst 64 Transfers \hideinitializer */
#define PDMA_BURST_32 0x00000020UL /*!<DMA Burst 32 Transfers \hideinitializer */
#define PDMA_BURST_16 0x00000030UL /*!<DMA Burst 16 Transfers \hideinitializer */
#define PDMA_BURST_8 0x00000040UL /*!<DMA Burst 8 Transfers \hideinitializer */
#define PDMA_BURST_4 0x00000050UL /*!<DMA Burst 4 Transfers \hideinitializer */
#define PDMA_BURST_2 0x00000060UL /*!<DMA Burst 2 Transfers \hideinitializer */
#define PDMA_BURST_1 0x00000070UL /*!<DMA Burst 1 Transfers \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Table Interrupt Disable Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define PDMA_TBINTDIS_ENABLE (0x0UL<<PDMA_DSCT_CTL_TBINTDIS_Pos) /*!<DMA Table Interrupt Enabled \hideinitializer */
#define PDMA_TBINTDIS_DISABLE (0x1UL<<PDMA_DSCT_CTL_TBINTDIS_Pos) /*!<DMA Table Interrupt Disabled \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Peripheral Transfer Mode Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define PDMA_MEM 0UL /*!<DMA Connect to Memory \hideinitializer */
#define PDMA_USB_TX 2UL /*!<DMA Connect to USB_TX \hideinitializer */
#define PDMA_USB_RX 3UL /*!<DMA Connect to USB_RX \hideinitializer */
#define PDMA_UART0_TX 4UL /*!<DMA Connect to UART0_TX \hideinitializer */
#define PDMA_UART0_RX 5UL /*!<DMA Connect to UART0_RX \hideinitializer */
#define PDMA_UART1_TX 6UL /*!<DMA Connect to UART1_TX \hideinitializer */
#define PDMA_UART1_RX 7UL /*!<DMA Connect to UART1_RX \hideinitializer */
#define PDMA_UART2_TX 8UL /*!<DMA Connect to UART2_TX \hideinitializer */
#define PDMA_UART2_RX 9UL /*!<DMA Connect to UART2_RX \hideinitializer */
#define PDMA_UART3_TX 10UL /*!<DMA Connect to UART3_TX \hideinitializer */
#define PDMA_UART3_RX 11UL /*!<DMA Connect to UART3_RX \hideinitializer */
#define PDMA_UART4_TX 12UL /*!<DMA Connect to UART4_TX \hideinitializer */
#define PDMA_UART4_RX 13UL /*!<DMA Connect to UART4_RX \hideinitializer */
#define PDMA_UART5_TX 14UL /*!<DMA Connect to UART5_TX \hideinitializer */
#define PDMA_UART5_RX 15UL /*!<DMA Connect to UART5_RX \hideinitializer */
#define PDMA_USCI0_TX 16UL /*!<DMA Connect to USCI0_TX \hideinitializer */
#define PDMA_USCI0_RX 17UL /*!<DMA Connect to USCI0_RX \hideinitializer */
#define PDMA_USCI1_TX 18UL /*!<DMA Connect to USCI1_TX \hideinitializer */
#define PDMA_USCI1_RX 19UL /*!<DMA Connect to USCI1_RX \hideinitializer */
#define PDMA_SPI0_TX 20UL /*!<DMA Connect to SPI0_TX \hideinitializer */
#define PDMA_SPI0_RX 21UL /*!<DMA Connect to SPI0_RX \hideinitializer */
#define PDMA_SPI1_TX 22UL /*!<DMA Connect to SPI1_TX \hideinitializer */
#define PDMA_SPI1_RX 23UL /*!<DMA Connect to SPI1_RX \hideinitializer */
#define PDMA_SPI2_TX 24UL /*!<DMA Connect to SPI2_TX \hideinitializer */
#define PDMA_SPI2_RX 25UL /*!<DMA Connect to SPI2_RX \hideinitializer */
#define PDMA_SPI3_TX 26UL /*!<DMA Connect to SPI3_TX \hideinitializer */
#define PDMA_SPI3_RX 27UL /*!<DMA Connect to SPI3_RX \hideinitializer */
#define PDMA_SPI4_TX 28UL /*!<DMA Connect to SPI4_TX \hideinitializer */
#define PDMA_SPI4_RX 29UL /*!<DMA Connect to SPI4_RX \hideinitializer */
#define PDMA_EPWM0_P1_RX 32UL /*!<DMA Connect to EPWM0_P1 \hideinitializer */
#define PDMA_EPWM0_P2_RX 33UL /*!<DMA Connect to EPWM0_P2 \hideinitializer */
#define PDMA_EPWM0_P3_RX 34UL /*!<DMA Connect to EPWM0_P3 \hideinitializer */
#define PDMA_EPWM1_P1_RX 35UL /*!<DMA Connect to EPWM1_P1 \hideinitializer */
#define PDMA_EPWM1_P2_RX 36UL /*!<DMA Connect to EPWM1_P2 \hideinitializer */
#define PDMA_EPWM1_P3_RX 37UL /*!<DMA Connect to PWM1_P3 \hideinitializer */
#define PDMA_I2C0_TX 38UL /*!<DMA Connect to I2C0_TX \hideinitializer */
#define PDMA_I2C0_RX 39UL /*!<DMA Connect to I2C0_RX \hideinitializer */
#define PDMA_I2C1_TX 40UL /*!<DMA Connect to I2C1_TX \hideinitializer */
#define PDMA_I2C1_RX 41UL /*!<DMA Connect to I2C1_RX \hideinitializer */
#define PDMA_I2C2_TX 42UL /*!<DMA Connect to I2C2_TX \hideinitializer */
#define PDMA_I2C2_RX 43UL /*!<DMA Connect to I2C2_RX \hideinitializer */
#define PDMA_I2S0_TX 44UL /*!<DMA Connect to I2S0_TX \hideinitializer */
#define PDMA_I2S0_RX 45UL /*!<DMA Connect to I2S0_RX \hideinitializer */
#define PDMA_TMR0 46UL /*!<DMA Connect to TMR0 \hideinitializer */
#define PDMA_TMR1 47UL /*!<DMA Connect to TMR1 \hideinitializer */
#define PDMA_TMR2 48UL /*!<DMA Connect to TMR2 \hideinitializer */
#define PDMA_TMR3 49UL /*!<DMA Connect to TMR3 \hideinitializer */
#define PDMA_ADC_RX 50UL /*!<DMA Connect to ADC_RX \hideinitializer */
#define PDMA_DAC0_TX 51UL /*!<DMA Connect to DAC0_TX \hideinitializer */
#define PDMA_DAC1_TX 52UL /*!<DMA Connect to DAC1_TX \hideinitializer */
#define EPWM0_CH0_TX 53UL /*!<DMA Connect to EPWM0_CH0_TX \hideinitializer */
#define EPWM0_CH1_TX 54UL /*!<DMA Connect to EPWM0_CH1_TX \hideinitializer */
#define EPWM0_CH2_TX 55UL /*!<DMA Connect to EPWM0_CH2_TX \hideinitializer */
#define EPWM0_CH3_TX 56UL /*!<DMA Connect to EPWM0_CH3_TX \hideinitializer */
#define EPWM0_CH4_TX 57UL /*!<DMA Connect to EPWM0_CH4_TX \hideinitializer */
#define EPWM0_CH5_TX 58UL /*!<DMA Connect to EPWM0_CH5_TX \hideinitializer */
#define EPWM1_CH0_TX 59UL /*!<DMA Connect to EPWM1_CH0_TX \hideinitializer */
#define EPWM1_CH1_TX 60UL /*!<DMA Connect to EPWM1_CH1_TX \hideinitializer */
#define EPWM1_CH2_TX 61UL /*!<DMA Connect to EPWM1_CH2_TX \hideinitializer */
#define EPWM1_CH3_TX 62UL /*!<DMA Connect to EPWM1_CH3_TX \hideinitializer */
#define EPWM1_CH4_TX 63UL /*!<DMA Connect to EPWM1_CH4_TX \hideinitializer */
#define EPWM1_CH5_TX 64UL /*!<DMA Connect to EPWM1_CH5_TX \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Interrupt Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define PDMA_INT_TRANS_DONE 0x00000000UL /*!<Transfer Done Interrupt \hideinitializer */
#define PDMA_INT_TEMPTY 0x00000001UL /*!<Table Empty Interrupt \hideinitializer */
#define PDMA_INT_TIMEOUT 0x00000002UL /*!<Timeout Interrupt \hideinitializer */
/*@}*/ /* end of group PDMA_EXPORTED_CONSTANTS */
/** @addtogroup PDMA_EXPORTED_FUNCTIONS PDMA Exported Functions
@{
*/
/**
* @brief Get PDMA Interrupt Status
*
* @param[in] None
*
* @return None
*
* @details This macro gets the interrupt status.
* \hideinitializer
*/
#define PDMA_GET_INT_STATUS() ((uint32_t)(PDMA->INTSTS))
/**
* @brief Get Transfer Done Interrupt Status
*
* @param[in] None
*
* @return None
*
* @details Get the transfer done Interrupt status.
* \hideinitializer
*/
#define PDMA_GET_TD_STS() ((uint32_t)(PDMA->TDSTS))
/**
* @brief Clear Transfer Done Interrupt Status
*
* @param[in] u32Mask The channel mask
*
* @return None
*
* @details Clear the transfer done Interrupt status.
* \hideinitializer
*/
#define PDMA_CLR_TD_FLAG(u32Mask) ((uint32_t)(PDMA->TDSTS = (u32Mask)))
/**
* @brief Get Target Abort Interrupt Status
*
* @param[in] None
*
* @return None
*
* @details Get the target abort Interrupt status.
* \hideinitializer
*/
#define PDMA_GET_ABORT_STS() ((uint32_t)(PDMA->ABTSTS))
/**
* @brief Clear Target Abort Interrupt Status
*
* @param[in] u32Mask The channel mask
*
* @return None
*
* @details Clear the target abort Interrupt status.
* \hideinitializer
*/
#define PDMA_CLR_ABORT_FLAG(u32Mask) ((uint32_t)(PDMA->ABTSTS = (u32Mask)))
/**
* @brief Get Scatter-Gather Table Empty Interrupt Status
*
* @param[in] None
*
* @return None
*
* @details Get the scatter-gather table empty Interrupt status.
* \hideinitializer
*/
#define PDMA_GET_EMPTY_STS() ((uint32_t)(PDMA->SCATSTS))
/**
* @brief Clear Scatter-Gather Table Empty Interrupt Status
*
* @param[in] u32Mask The channel mask
*
* @return None
*
* @details Clear the scatter-gather table empty Interrupt status.
* \hideinitializer
*/
#define PDMA_CLR_EMPTY_FLAG(u32Mask) ((uint32_t)(PDMA->SCATSTS = (u32Mask)))
/**
* @brief Clear Timeout Interrupt Status
*
* @param[in] u32Ch The selected channel
*
* @return None
*
* @details Clear the selected channel timeout interrupt status.
* \hideinitializer
*/
#define PDMA_CLR_TMOUT_FLAG(u32Ch) ((uint32_t)(PDMA->INTSTS = (1 << ((u32Ch) + 8))))
/**
* @brief Check Channel Status
*
* @param[in] u32Ch The selected channel
*
* @retval 0 Idle state
* @retval 1 Busy state
*
* @details Check the selected channel is busy or not.
* \hideinitializer
*/
#define PDMA_IS_CH_BUSY(u32Ch) ((uint32_t)(PDMA->TRGSTS & (1 << (u32Ch)))? 1 : 0)
/**
* @brief Set Source Address
*
* @param[in] u32Ch The selected channel
* @param[in] u32Addr The selected address
*
* @return None
*
* @details This macro set the selected channel source address.
* \hideinitializer
*/
#define PDMA_SET_SRC_ADDR(u32Ch, u32Addr) ((uint32_t)(PDMA->DSCT[(u32Ch)].SA = (u32Addr)))
/**
* @brief Set Destination Address
*
* @param[in] u32Ch The selected channel
* @param[in] u32Addr The selected address
*
* @return None
*
* @details This macro set the selected channel destination address.
* \hideinitializer
*/
#define PDMA_SET_DST_ADDR(u32Ch, u32Addr) ((uint32_t)(PDMA->DSCT[(u32Ch)].DA = (u32Addr)))
/**
* @brief Set Transfer Count
*
* @param[in] u32Ch The selected channel
* @param[in] u32TransCount Transfer Count
*
* @return None
*
* @details This macro set the selected channel transfer count.
* \hideinitializer
*/
#define PDMA_SET_TRANS_CNT(u32Ch, u32TransCount) ((uint32_t)(PDMA->DSCT[(u32Ch)].CTL=(PDMA->DSCT[(u32Ch)].CTL&~PDMA_DSCT_CTL_TXCNT_Msk)|(((u32TransCount)-1) << PDMA_DSCT_CTL_TXCNT_Pos)))
/**
* @brief Set Scatter-gather descriptor Address
*
* @param[in] u32Ch The selected channel
* @param[in] u32Addr The descriptor address
*
* @return None
*
* @details This macro set the selected channel scatter-gather descriptor address.
* \hideinitializer
*/
#define PDMA_SET_SCATTER_DESC(u32Ch, u32Addr) ((uint32_t)(PDMA->DSCT[(u32Ch)].NEXT = (u32Addr) - (PDMA->SCATBA)))
/**
* @brief Stop the channel
*
* @param[in] u32Ch The selected channel
*
* @return None
*
* @details This macro stop the selected channel.
* \hideinitializer
*/
#define PDMA_STOP(u32Ch) ((uint32_t)(PDMA->PAUSE = (1 << (u32Ch))))
/**
* @brief Pause the channel
*
* @param[in] u32Ch The selected channel
*
* @return None
*
* @details This macro pause the selected channel.
* \hideinitializer
*/
#define PDMA_PAUSE(u32Ch) ((uint32_t)(PDMA->PAUSE = (1 << (u32Ch))))
/*---------------------------------------------------------------------------------------------------------*/
/* Define PDMA functions prototype */
/*---------------------------------------------------------------------------------------------------------*/
void PDMA_Open(uint32_t u32Mask);
void PDMA_Close(void);
void PDMA_SetTransferCnt(uint32_t u32Ch, uint32_t u32Width, uint32_t u32TransCount);
void PDMA_SetTransferAddr(uint32_t u32Ch, uint32_t u32SrcAddr, uint32_t u32SrcCtrl, uint32_t u32DstAddr, uint32_t u32DstCtrl);
void PDMA_SetTransferMode(uint32_t u32Ch, uint32_t u32Peripheral, uint32_t u32ScatterEn, uint32_t u32DescAddr);
void PDMA_SetBurstType(uint32_t u32Ch, uint32_t u32BurstType, uint32_t u32BurstSize);
void PDMA_EnableTimeout(uint32_t u32Mask);
void PDMA_DisableTimeout(uint32_t u32Mask);
void PDMA_SetTimeOut(uint32_t u32Ch, uint32_t u32OnOff, uint32_t u32TimeOutCnt);
void PDMA_Trigger(uint32_t u32Ch);
void PDMA_EnableInt(uint32_t u32Ch, uint32_t u32Mask);
void PDMA_DisableInt(uint32_t u32Ch, uint32_t u32Mask);
void PDMA_SetStride(uint32_t u32Ch, uint32_t u32DestLen, uint32_t u32SrcLen, uint32_t u32TransCount);
/*@}*/ /* end of group PDMA_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group PDMA_Driver */
/*@}*/ /* end of group Standard_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __PDMA_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,140 @@
/**************************************************************************//**
* @file qei.c
* @version V3.00
* $Revision: 1 $
* $Date: 16/06/16 10:23a $
* @brief Quadrature Encoder Interface (QEI) driver source file
*
* @note
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup QEI_Driver QEI Driver
@{
*/
/** @addtogroup QEI_EXPORTED_FUNCTIONS QEI Exported Functions
@{
*/
/**
* @brief Close QEI function
* @param[in] qei The pointer of the specified QEI module.
* @return None
* @details This function reset QEI configuration and stop QEI counting.
*/
void QEI_Close(QEI_T* qei)
{
/* Reset QEI configuration */
qei->CTL = (uint32_t)0;
}
/**
* @brief Disable QEI interrupt
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32IntSel Interrupt type selection.
* - \ref QEI_CTL_DIRIEN_Msk : Direction change interrupt
* - \ref QEI_CTL_OVUNIEN_Msk : Counter overflow or underflow interrupt
* - \ref QEI_CTL_CMPIEN_Msk : Compare-match interrupt
* - \ref QEI_CTL_IDXIEN_Msk : Index detected interrupt
* @return None
* @details This function disable QEI specified interrupt.
*/
void QEI_DisableInt(QEI_T* qei, uint32_t u32IntSel)
{
/* Disable QEI specified interrupt */
QEI_DISABLE_INT(qei, u32IntSel);
/* Disable NVIC QEI IRQ */
if(qei ==(QEI_T*)QEI0) {
NVIC_DisableIRQ((IRQn_Type)QEI0_IRQn);
} else {
NVIC_DisableIRQ((IRQn_Type)QEI1_IRQn);
}
}
/**
* @brief Enable QEI interrupt
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32IntSel Interrupt type selection.
* - \ref QEI_CTL_DIRIEN_Msk : Direction change interrupt
* - \ref QEI_CTL_OVUNIEN_Msk : Counter overflow or underflow interrupt
* - \ref QEI_CTL_CMPIEN_Msk : Compare-match interrupt
* - \ref QEI_CTL_IDXIEN_Msk : Index detected interrupt
* @return None
* @details This function enable QEI specified interrupt.
*/
void QEI_EnableInt(QEI_T* qei, uint32_t u32IntSel)
{
/* Enable QEI specified interrupt */
QEI_ENABLE_INT(qei, u32IntSel);
/* Enable NVIC QEI IRQ */
if(qei == (QEI_T*)QEI0) {
NVIC_EnableIRQ(QEI0_IRQn);
} else {
NVIC_EnableIRQ(QEI1_IRQn);
}
}
/**
* @brief Open QEI in specified mode and enable input
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32Mode QEI counting mode.
* - \ref QEI_CTL_X4_FREE_COUNTING_MODE
* - \ref QEI_CTL_X2_FREE_COUNTING_MODE
* - \ref QEI_CTL_X4_COMPARE_COUNTING_MODE
* - \ref QEI_CTL_X2_COMPARE_COUNTING_MODE
* @param[in] u32Value The counter maximum value in compare-counting mode.
* @return None
* @details This function set QEI in specified mode and enable input.
*/
void QEI_Open(QEI_T* qei, uint32_t u32Mode, uint32_t u32Value)
{
/* Set QEI function configuration */
/* Set QEI counting mode */
/* Enable IDX, QEA and QEB input to QEI controller */
qei->CTL = (qei->CTL & (~QEI_CTL_MODE_Msk)) | ((u32Mode) | QEI_CTL_CHAEN_Msk | QEI_CTL_CHBEN_Msk | QEI_CTL_IDXEN_Msk);
/* Set QEI maximum count value in in compare-counting mode */
qei->CNTMAX = u32Value;
}
/**
* @brief Start QEI function
* @param[in] qei The pointer of the specified QEI module.
* @return None
* @details This function enable QEI function and start QEI counting.
*/
void QEI_Start(QEI_T* qei)
{
/* Enable QEI controller function */
qei->CTL |= QEI_CTL_QEIEN_Msk;
}
/**
* @brief Stop QEI function
* @param[in] qei The pointer of the specified QEI module.
* @return None
* @details This function disable QEI function and stop QEI counting.
*/
void QEI_Stop(QEI_T* qei)
{
/* Disable QEI controller function */
qei->CTL &= (~QEI_CTL_QEIEN_Msk);
}
/*@}*/ /* end of group QEI_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group QEI_Driver */
/*@}*/ /* end of group Standard_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,389 @@
/**************************************************************************//**
* @file qei.h
* @version V3.00
* @brief Quadrature Encoder Interface (QEI) driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __QEI_H__
#define __QEI_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup QEI_Driver QEI Driver
@{
*/
/** @addtogroup QEI_EXPORTED_CONSTANTS QEI Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* QEI counting mode selection constants definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define QEI_CTL_X4_FREE_COUNTING_MODE (0x0<<QEI_CTL_MODE_Pos) /*!< QEI operate in X4 free-counting mode \hideinitializer */
#define QEI_CTL_X2_FREE_COUNTING_MODE (0x1<<QEI_CTL_MODE_Pos) /*!< QEI operate in X2 free-counting mode \hideinitializer */
#define QEI_CTL_X4_COMPARE_COUNTING_MODE (0x2<<QEI_CTL_MODE_Pos) /*!< QEI operate in X4 compare-counting mode \hideinitializer */
#define QEI_CTL_X2_COMPARE_COUNTING_MODE (0x3<<QEI_CTL_MODE_Pos) /*!< QEI operate in X2 compare-counting mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* QEI noise filter clock pre-divide selection constants definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define QEI_CTL_NFCLKSEL_DIV1 (0x0<<QEI_CTL_NFCLKSEL_Pos) /*!< The sampling frequency of the noise filter is QEI_CLK \hideinitializer */
#define QEI_CTL_NFCLKSEL_DIV2 (0x1<<QEI_CTL_NFCLKSEL_Pos) /*!< The sampling frequency of the noise filter is QEI_CLK/2 \hideinitializer */
#define QEI_CTL_NFCLKSEL_DIV4 (0x2<<QEI_CTL_NFCLKSEL_Pos) /*!< The sampling frequency of the noise filter is QEI_CLK/4 \hideinitializer */
#define QEI_CTL_NFCLKSEL_DIV16 (0x3<<QEI_CTL_NFCLKSEL_Pos) /*!< The sampling frequency of the noise filter is QEI_CLK/16 \hideinitializer */
#define QEI_CTL_NFCLKSEL_DIV32 (0x4<<QEI_CTL_NFCLKSEL_Pos) /*!< The sampling frequency of the noise filter is QEI_CLK/16 \hideinitializer */
#define QEI_CTL_NFCLKSEL_DIV64 (0x5<<QEI_CTL_NFCLKSEL_Pos) /*!< The sampling frequency of the noise filter is QEI_CLK/16 \hideinitializer */
/*@}*/ /* end of group QEI_EXPORTED_CONSTANTS */
/** @addtogroup QEI_EXPORTED_FUNCTIONS QEI Exported Functions
@{
*/
/**
* @brief Disable QEI compare function
* @param[in] qei The pointer of the specified QEI module.
* @return None
* @details This macro disable QEI counter compare function.
* \hideinitializer
*/
#define QEI_DISABLE_CNT_CMP(qei) ((qei)->CTL &= (~QEI_CTL_CMPEN_Msk))
/**
* @brief Enable QEI compare function
* @param[in] qei The pointer of the specified QEI module.
* @return None
* @details This macro enable QEI counter compare function.
* \hideinitializer
*/
#define QEI_ENABLE_CNT_CMP(qei) ((qei)->CTL |= QEI_CTL_CMPEN_Msk)
/**
* @brief Disable QEI index latch function
* @param[in] qei The pointer of the specified QEI module.
* @return None
* @details This macro disable QEI index trigger counter latch function.
* \hideinitializer
*/
#define QEI_DISABLE_INDEX_LATCH(qei) ((qei)->CTL &= (~QEI_CTL_IDXLATEN_Msk))
/**
* @brief Enable QEI index latch function
* @param[in] qei The pointer of the specified QEI module.
* @return None
* @details This macro enable QEI index trigger counter latch function.
* \hideinitializer
*/
#define QEI_ENABLE_INDEX_LATCH(qei) ((qei)->CTL |= QEI_CTL_IDXLATEN_Msk)
/**
* @brief Disable QEI index reload function
* @param[in] qei The pointer of the specified QEI module.
* @return None
* @details This macro disable QEI index trigger counter reload function.
* \hideinitializer
*/
#define QEI_DISABLE_INDEX_RELOAD(qei) ((qei)->CTL &= (~QEI_CTL_IDXRLDEN_Msk))
/**
* @brief Enable QEI index reload function
* @param[in] qei The pointer of the specified QEI module.
* @return None
* @details This macro enable QEI index trigger counter reload function.
* \hideinitializer
*/
#define QEI_ENABLE_INDEX_RELOAD(qei) ((qei)->CTL |= QEI_CTL_IDXRLDEN_Msk)
/**
* @brief Disable QEI input
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32InputType Input signal type.
* - \ref QEI_CTL_CHAEN_Msk : QEA input
* - \ref QEI_CTL_CHAEN_Msk : QEB input
* - \ref QEI_CTL_IDXEN_Msk : IDX input
* @return None
* @details This macro disable specified QEI signal input.
* \hideinitializer
*/
#define QEI_DISABLE_INPUT(qei, u32InputType) ((qei)->CTL &= ~(u32InputType))
/**
* @brief Enable QEI input
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32InputType Input signal type .
* - \ref QEI_CTL_CHAEN_Msk : QEA input
* - \ref QEI_CTL_CHBEN_Msk : QEB input
* - \ref QEI_CTL_IDXEN_Msk : IDX input
* @return None
* @details This macro enable specified QEI signal input.
* \hideinitializer
*/
#define QEI_ENABLE_INPUT(qei, u32InputType) ((qei)->CTL |= (u32InputType))
/**
* @brief Disable inverted input polarity
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32InputType Input signal type .
* - \ref QEI_CTL_CHAINV_Msk : QEA Input
* - \ref QEI_CTL_CHBINV_Msk : QEB Input
* - \ref QEI_CTL_IDXINV_Msk : IDX Input
* @return None
* @details This macro disable specified QEI signal inverted input polarity.
* \hideinitializer
*/
#define QEI_DISABLE_INPUT_INV(qei, u32InputType) ((qei)->CTL &= ~(u32InputType))
/**
* @brief Enable inverted input polarity
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32InputType Input signal type.
* - \ref QEI_CTL_CHAINV_Msk : QEA Input
* - \ref QEI_CTL_CHBINV_Msk : QEB Input
* - \ref QEI_CTL_IDXINV_Msk : IDX Input
* @return None
* @details This macro inverse specified QEI signal input polarity.
* \hideinitializer
*/
#define QEI_ENABLE_INPUT_INV(qei, u32InputType) ((qei)->CTL |= (u32InputType))
/**
* @brief Disable QEI interrupt
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32IntSel Interrupt type selection.
* - \ref QEI_CTL_DIRIEN_Msk : Direction change interrupt
* - \ref QEI_CTL_OVUNIEN_Msk : Counter overflow or underflow interrupt
* - \ref QEI_CTL_CMPIEN_Msk : Compare-match interrupt
* - \ref QEI_CTL_IDXIEN_Msk : Index detected interrupt
* @return None
* @details This macro disable specified QEI interrupt.
* \hideinitializer
*/
#define QEI_DISABLE_INT(qei, u32IntSel) ((qei)->CTL &= ~(u32IntSel))
/**
* @brief Enable QEI interrupt
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32IntSel Interrupt type selection.
* - \ref QEI_CTL_DIRIEN_Msk : Direction change interrupt
* - \ref QEI_CTL_OVUNIEN_Msk : Counter overflow or underflow interrupt
* - \ref QEI_CTL_CMPIEN_Msk : Compare-match interrupt
* - \ref QEI_CTL_IDXIEN_Msk : Index detected interrupt
* @return None
* @details This macro disable specified QEI interrupt.
* \hideinitializer
*/
#define QEI_ENABLE_INT(qei, u32IntSel) ((qei)->CTL |= (u32IntSel))
/**
* @brief Disable QEI noise filter
* @param[in] qei The pointer of the specified QEI module.
* @return None
* @details This macro disable QEI noise filter function.
* \hideinitializer
*/
#define QEI_DISABLE_NOISE_FILTER(qei) ((qei)->CTL |= QEI_CTL_NFDIS_Msk)
/**
* @brief Enable QEI noise filter
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32ClkSel The sampling frequency of the noise filter clock.
* - \ref QEI_CTL_NFCLKSEL_DIV1
* - \ref QEI_CTL_NFCLKSEL_DIV2
* - \ref QEI_CTL_NFCLKSEL_DIV4
* - \ref QEI_CTL_NFCLKSEL_DIV16
* - \ref QEI_CTL_NFCLKSEL_DIV32
* - \ref QEI_CTL_NFCLKSEL_DIV64
* @return None
* @details This macro enable QEI noise filter function and select noise filter clock.
* \hideinitializer
*/
#define QEI_ENABLE_NOISE_FILTER(qei, u32ClkSel) ((qei)->CTL = ((qei)->CTL & (~(QEI_CTL_NFDIS_Msk|QEI_CTL_NFCLKSEL_Msk))) | (u32ClkSel))
/**
* @brief Get QEI counter value
* @param[in] qei The pointer of the specified QEI module.
* @return QEI pulse counter register value.
* @details This macro get QEI pulse counter value.
* \hideinitializer
*/
#define QEI_GET_CNT_VALUE(qei) ((qei)->CNT)
/**
* @brief Get QEI counting direction
* @param[in] qei The pointer of the specified QEI module.
* @retval 0 QEI counter is in down-counting.
* @retval 1 QEI counter is in up-counting.
* @details This macro get QEI counting direction.
* \hideinitializer
*/
#define QEI_GET_DIR(qei) (((qei)->STATUS & (QEI_STATUS_DIRF_Msk))?1:0)
/**
* @brief Get QEI counter hold value
* @param[in] qei The pointer of the specified QEI module.
* @return QEI pulse counter hold register value.
* @details This macro get QEI pulse counter hold value, which is updated with counter value in hold counter value control.
* \hideinitializer
*/
#define QEI_GET_HOLD_VALUE(qei) ((qei)->CNTHOLD)
/**
* @brief Get QEI counter index latch value
* @param[in] qei The pointer of the specified QEI module.
* @return QEI pulse counter index latch value
* @details This macro get QEI pulse counter index latch value, which is updated with counter value when the index is detected.
* \hideinitializer
*/
#define QEI_GET_INDEX_LATCH_VALUE(qei) ((qei)->CNTLATCH)
/**
* @brief Set QEI counter index latch value
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32Val The latch value.
* @return QEI pulse counter index latch value
* @details This macro set QEI pulse counter index latch value, which is updated with counter value when the index is detected.
* \hideinitializer
*/
#define QEI_SET_INDEX_LATCH_VALUE(qei,u32Val) ((qei)->CNTLATCH = (u32Val))
/**
* @brief Get QEI interrupt flag status
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32IntSel Interrupt type selection.
* - \ref QEI_STATUS_DIRF_Msk : Counting direction flag
* - \ref QEI_STATUS_DIRCHGF_Msk : Direction change flag
* - \ref QEI_STATUS_OVUNF_Msk : Counter overflow or underflow flag
* - \ref QEI_STATUS_CMPF_Msk : Compare-match flag
* - \ref QEI_STATUS_IDXF_Msk : Index detected flag
* @retval 0 QEI specified interrupt flag is not set.
* @retval 1 QEI specified interrupt flag is set.
* @details This macro get QEI specified interrupt flag status.
* \hideinitializer
*/
#define QEI_GET_INT_FLAG(qei, u32IntSel) (((qei)->STATUS & (u32IntSel))?1:0)
/**
* @brief Clear QEI interrupt flag
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32IntSel Interrupt type selection.
* - \ref QEI_STATUS_DIRCHGF_Msk : Direction change flag
* - \ref QEI_STATUS_OVUNF_Msk : Counter overflow or underflow flag
* - \ref QEI_STATUS_CMPF_Msk : Compare-match flag
* - \ref QEI_STATUS_IDXF_Msk : Index detected flag
* @return None
* @details This macro clear QEI specified interrupt flag.
* \hideinitializer
*/
#define QEI_CLR_INT_FLAG(qei, u32IntSel) ((qei)->STATUS = (u32IntSel))
/**
* @brief Set QEI counter compare value
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32Value The counter compare value.
* @return None
* @details This macro set QEI pulse counter compare value.
* \hideinitializer
*/
#define QEI_SET_CNT_CMP(qei, u32Value) ((qei)->CNTCMP = (u32Value))
/**
* @brief Set QEI counter value
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32Value The counter compare value.
* @return None
* @details This macro set QEI pulse counter compare value.
* \hideinitializer
*/
#define QEI_SET_CNT_VALUE(qei, u32Value) ((qei)->CNT = (u32Value))
/**
* @brief Enable QEI counter hold mode
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32Type The triggered type.
* - \ref QEI_CTL_HOLDCNT_Msk : Hold QEI_CNT control
* - \ref QEI_CTL_HOLDTMR0_Msk : Hold QEI_CNT by Timer0
* - \ref QEI_CTL_HOLDTMR1_Msk : Hold QEI_CNT by Timer1
* - \ref QEI_CTL_HOLDTMR2_Msk : Hold QEI_CNT by Timer2
* - \ref QEI_CTL_HOLDTMR3_Msk : Hold QEI_CNT by Timer3
* @return None
* @details This macro set QEI counter hold mode.
* \hideinitializer
*/
#define QEI_ENABLE_HOLD_TRG_SRC(qei, u32Type) ((qei)->CTL |= (u32Type))
/**
* @brief Disable QEI counter hold mode
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32Type The triggered type.
* - \ref QEI_CTL_HOLDCNT_Msk : Hold QEI_CNT control
* - \ref QEI_CTL_HOLDTMR0_Msk : Hold QEI_CNT by Timer0
* - \ref QEI_CTL_HOLDTMR1_Msk : Hold QEI_CNT by Timer1
* - \ref QEI_CTL_HOLDTMR2_Msk : Hold QEI_CNT by Timer2
* - \ref QEI_CTL_HOLDTMR3_Msk : Hold QEI_CNT by Timer3
* @return None
* @details This macro set QEI counter hold mode.
* \hideinitializer
*/
#define QEI_DISABLE_HOLD_TRG_SRC(qei, u32Type) ((qei)->CTL &= ~(u32Type))
/**
* @brief Set QEI maximum count value
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32Value The counter maximum value.
* @return QEI maximum count value
* @details This macro set QEI maximum count value.
* \hideinitializer
*/
#define QEI_SET_CNT_MAX(qei, u32Value) ((qei)->CNTMAX = (u32Value))
/**
* @brief Set QEI counting mode
* @param[in] qei The pointer of the specified QEI module.
* @param[in] u32Mode QEI counting mode.
* - \ref QEI_CTL_X4_FREE_COUNTING_MODE
* - \ref QEI_CTL_X2_FREE_COUNTING_MODE
* - \ref QEI_CTL_X4_COMPARE_COUNTING_MODE
* - \ref QEI_CTL_X2_COMPARE_COUNTING_MODE
* @return None
* @details This macro set QEI counting mode.
* \hideinitializer
*/
#define QEI_SET_CNT_MODE(qei, u32Mode) ((qei)->CTL = ((qei)->CTL & (~QEI_CTL_MODE_Msk)) | (u32Mode))
void QEI_Close(QEI_T* qei);
void QEI_DisableInt(QEI_T* qei, uint32_t u32IntSel);
void QEI_EnableInt(QEI_T* qei, uint32_t u32IntSel);
void QEI_Open(QEI_T* qei, uint32_t u32Mode, uint32_t u32Value);
void QEI_Start(QEI_T* qei);
void QEI_Stop(QEI_T* qei);
/*@}*/ /* end of group QEI_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group QEI_Driver */
/*@}*/ /* end of group Standard_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __QEI_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,965 @@
/**************************************************************************//**
* @file rtc.c
* @version V3.00
* $Revision: 5 $
* $Date: 14/06/10 5:49p $
* @brief M480 series RTC driver source file
*
* @note
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @cond HIDDEN_SYMBOLS */
/*---------------------------------------------------------------------------------------------------------*/
/* Macro, type and constant definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_GLOBALS
/*---------------------------------------------------------------------------------------------------------*/
/* Global file scope (static) variables */
/*---------------------------------------------------------------------------------------------------------*/
static volatile uint32_t g_u32hiYear, g_u32loYear, g_u32hiMonth, g_u32loMonth, g_u32hiDay, g_u32loDay;
static volatile uint32_t g_u32hiHour, g_u32loHour, g_u32hiMin, g_u32loMin, g_u32hiSec, g_u32loSec;
/** @endcond HIDDEN_SYMBOLS */
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_RTC_Driver RTC Driver
@{
*/
/** @addtogroup M480_RTC_EXPORTED_FUNCTIONS RTC Exported Functions
@{
*/
/**
* @brief Initialize RTC module and start counting
*
* @param[in] sPt Specify the time property and current date and time. It includes: \n
* u32Year: Year value, range between 2000 ~ 2099. \n
* u32Month: Month value, range between 1 ~ 12. \n
* u32Day: Day value, range between 1 ~ 31. \n
* u32DayOfWeek: Day of the week. [RTC_SUNDAY / RTC_MONDAY / RTC_TUESDAY /
* RTC_WEDNESDAY / RTC_THURSDAY / RTC_FRIDAY /
* RTC_SATURDAY] \n
* u32Hour: Hour value, range between 0 ~ 23. \n
* u32Minute: Minute value, range between 0 ~ 59. \n
* u32Second: Second value, range between 0 ~ 59. \n
* u32TimeScale: [RTC_CLOCK_12 / RTC_CLOCK_24] \n
* u8AmPm: [RTC_AM / RTC_PM] \n
*
* @return None
*
* @details This function is used to: \n
* 1. Write initial key to let RTC start count. \n
* 2. Input parameter indicates start date/time. \n
* 3. User has to make sure that parameters of RTC date/time are reasonable. \n
* @note Null pointer for using default starting date/time.
*/
void RTC_Open(S_RTC_TIME_DATA_T *sPt)
{
RTC->INIT = RTC_INIT_KEY;
if(RTC->INIT != RTC_INIT_ACTIVE_Msk) {
RTC->INIT = RTC_INIT_KEY;
while(RTC->INIT != RTC_INIT_ACTIVE_Msk) {
}
}
if(sPt == 0) {
} else {
/* Set RTC date and time */
RTC_SetDateAndTime(sPt);
}
}
/**
* @brief Disable RTC Clock
*
* @param None
*
* @return None
*
* @details This API will disable RTC peripheral clock and stops RTC counting.
*/
void RTC_Close(void)
{
CLK->APBCLK0 &= ~CLK_APBCLK0_RTCCKEN_Msk;
}
/**
* @brief Set Frequency Compensation Data
*
* @param[in] i32FrequencyX10000 Specify the RTC clock X10000, ex: 327736512 means 32773.6512.
*
* @return None
*
*/
void RTC_32KCalibration(int32_t i32FrequencyX10000)
{
uint64_t u64Compensate;
u64Compensate = (uint64_t)(0x2710000000000);
u64Compensate = (uint64_t)(u64Compensate / (uint64_t)i32FrequencyX10000);
if(u64Compensate >= (uint64_t)0x400000) {
u64Compensate = (uint64_t)0x3FFFFF;
}
RTC_WaitAccessEnable();
RTC->FREQADJ = (uint32_t)u64Compensate;
}
/**
* @brief Get Current RTC Date and Time
*
* @param[out] sPt The returned pointer is specified the current RTC value. It includes: \n
* u32Year: Year value \n
* u32Month: Month value \n
* u32Day: Day value \n
* u32DayOfWeek: Day of week \n
* u32Hour: Hour value \n
* u32Minute: Minute value \n
* u32Second: Second value \n
* u32TimeScale: [RTC_CLOCK_12 / RTC_CLOCK_24] \n
* u8AmPm: [RTC_AM / RTC_PM] \n
*
* @return None
*
* @details This API is used to get the current RTC date and time value.
*/
void RTC_GetDateAndTime(S_RTC_TIME_DATA_T *sPt)
{
uint32_t u32Tmp;
sPt->u32TimeScale = RTC->CLKFMT & RTC_CLKFMT_24HEN_Msk; /* 12/24-hour */
sPt->u32DayOfWeek = RTC->WEEKDAY & RTC_WEEKDAY_WEEKDAY_Msk; /* Day of the week */
/* Get [Date digit] data */
g_u32hiYear = (RTC->CAL & RTC_CAL_TENYEAR_Msk) >> RTC_CAL_TENYEAR_Pos;
g_u32loYear = (RTC->CAL & RTC_CAL_YEAR_Msk) >> RTC_CAL_YEAR_Pos;
g_u32hiMonth = (RTC->CAL & RTC_CAL_TENMON_Msk) >> RTC_CAL_TENMON_Pos;
g_u32loMonth = (RTC->CAL & RTC_CAL_MON_Msk) >> RTC_CAL_MON_Pos;
g_u32hiDay = (RTC->CAL & RTC_CAL_TENDAY_Msk) >> RTC_CAL_TENDAY_Pos;
g_u32loDay = (RTC->CAL & RTC_CAL_DAY_Msk) >> RTC_CAL_DAY_Pos;
/* Get [Time digit] data */
g_u32hiHour = (RTC->TIME & RTC_TIME_TENHR_Msk) >> RTC_TIME_TENHR_Pos;
g_u32loHour = (RTC->TIME & RTC_TIME_HR_Msk) >> RTC_TIME_HR_Pos;
g_u32hiMin = (RTC->TIME & RTC_TIME_TENMIN_Msk) >> RTC_TIME_TENMIN_Pos;
g_u32loMin = (RTC->TIME & RTC_TIME_MIN_Msk) >> RTC_TIME_MIN_Pos;
g_u32hiSec = (RTC->TIME & RTC_TIME_TENSEC_Msk) >> RTC_TIME_TENSEC_Pos;
g_u32loSec = (RTC->TIME & RTC_TIME_SEC_Msk) >> RTC_TIME_SEC_Pos;
/* Compute to 20XX year */
u32Tmp = (g_u32hiYear * 10ul);
u32Tmp += g_u32loYear;
sPt->u32Year = u32Tmp + RTC_YEAR2000;
/* Compute 0~12 month */
u32Tmp = (g_u32hiMonth * 10ul);
sPt->u32Month = u32Tmp + g_u32loMonth;
/* Compute 0~31 day */
u32Tmp = (g_u32hiDay * 10ul);
sPt->u32Day = u32Tmp + g_u32loDay;
/* Compute 12/24 hour */
if(sPt->u32TimeScale == RTC_CLOCK_12) {
u32Tmp = (g_u32hiHour * 10ul);
u32Tmp += g_u32loHour;
sPt->u32Hour = u32Tmp; /* AM: 1~12. PM: 21~32. */
if(sPt->u32Hour >= 21ul) {
sPt->u32AmPm = RTC_PM;
sPt->u32Hour -= 20ul;
} else {
sPt->u32AmPm = RTC_AM;
}
u32Tmp = (g_u32hiMin * 10ul);
u32Tmp += g_u32loMin;
sPt->u32Minute = u32Tmp;
u32Tmp = (g_u32hiSec * 10ul);
u32Tmp += g_u32loSec;
sPt->u32Second = u32Tmp;
} else {
u32Tmp = (g_u32hiHour * 10ul);
u32Tmp += g_u32loHour;
sPt->u32Hour = u32Tmp;
u32Tmp = (g_u32hiMin * 10ul);
u32Tmp += g_u32loMin;
sPt->u32Minute = u32Tmp;
u32Tmp = (g_u32hiSec * 10ul);
u32Tmp += g_u32loSec;
sPt->u32Second = u32Tmp;
}
}
/**
* @brief Get RTC Alarm Date and Time
*
* @param[out] sPt The returned pointer is specified the RTC alarm value. It includes: \n
* u32Year: Year value \n
* u32Month: Month value \n
* u32Day: Day value \n
* u32DayOfWeek: Day of week \n
* u32Hour: Hour value \n
* u32Minute: Minute value \n
* u32Second: Second value \n
* u32TimeScale: [RTC_CLOCK_12 / RTC_CLOCK_24] \n
* u8AmPm: [RTC_AM / RTC_PM] \n
*
* @return None
*
* @details This API is used to get the RTC alarm date and time setting.
*/
void RTC_GetAlarmDateAndTime(S_RTC_TIME_DATA_T *sPt)
{
uint32_t u32Tmp;
sPt->u32TimeScale = RTC->CLKFMT & RTC_CLKFMT_24HEN_Msk; /* 12/24-hour */
sPt->u32DayOfWeek = RTC->WEEKDAY & RTC_WEEKDAY_WEEKDAY_Msk; /* Day of the week */
/* Get alarm [Date digit] data */
RTC_WaitAccessEnable();
g_u32hiYear = (RTC->CALM & RTC_CALM_TENYEAR_Msk) >> RTC_CALM_TENYEAR_Pos;
g_u32loYear = (RTC->CALM & RTC_CALM_YEAR_Msk) >> RTC_CALM_YEAR_Pos;
g_u32hiMonth = (RTC->CALM & RTC_CALM_TENMON_Msk) >> RTC_CALM_TENMON_Pos;
g_u32loMonth = (RTC->CALM & RTC_CALM_MON_Msk) >> RTC_CALM_MON_Pos;
g_u32hiDay = (RTC->CALM & RTC_CALM_TENDAY_Msk) >> RTC_CALM_TENDAY_Pos;
g_u32loDay = (RTC->CALM & RTC_CALM_DAY_Msk) >> RTC_CALM_DAY_Pos;
/* Get alarm [Time digit] data */
RTC_WaitAccessEnable();
g_u32hiHour = (RTC->TALM & RTC_TALM_TENHR_Msk) >> RTC_TALM_TENHR_Pos;
g_u32loHour = (RTC->TALM & RTC_TALM_HR_Msk) >> RTC_TALM_HR_Pos;
g_u32hiMin = (RTC->TALM & RTC_TALM_TENMIN_Msk) >> RTC_TALM_TENMIN_Pos;
g_u32loMin = (RTC->TALM & RTC_TALM_MIN_Msk) >> RTC_TALM_MIN_Pos;
g_u32hiSec = (RTC->TALM & RTC_TALM_TENSEC_Msk) >> RTC_TALM_TENSEC_Pos;
g_u32loSec = (RTC->TALM & RTC_TALM_SEC_Msk) >> RTC_TALM_SEC_Pos;
/* Compute to 20XX year */
u32Tmp = (g_u32hiYear * 10ul);
u32Tmp += g_u32loYear;
sPt->u32Year = u32Tmp + RTC_YEAR2000;
/* Compute 0~12 month */
u32Tmp = (g_u32hiMonth * 10ul);
sPt->u32Month = u32Tmp + g_u32loMonth;
/* Compute 0~31 day */
u32Tmp = (g_u32hiDay * 10ul);
sPt->u32Day = u32Tmp + g_u32loDay;
/* Compute 12/24 hour */
if(sPt->u32TimeScale == RTC_CLOCK_12) {
u32Tmp = (g_u32hiHour * 10ul);
u32Tmp += g_u32loHour;
sPt->u32Hour = u32Tmp; /* AM: 1~12. PM: 21~32. */
if(sPt->u32Hour >= 21ul) {
sPt->u32AmPm = RTC_PM;
sPt->u32Hour -= 20ul;
} else {
sPt->u32AmPm = RTC_AM;
}
u32Tmp = (g_u32hiMin * 10ul);
u32Tmp += g_u32loMin;
sPt->u32Minute = u32Tmp;
u32Tmp = (g_u32hiSec * 10ul);
u32Tmp += g_u32loSec;
sPt->u32Second = u32Tmp;
} else {
u32Tmp = (g_u32hiHour * 10ul);
u32Tmp += g_u32loHour;
sPt->u32Hour = u32Tmp;
u32Tmp = (g_u32hiMin * 10ul);
u32Tmp += g_u32loMin;
sPt->u32Minute = u32Tmp;
u32Tmp = (g_u32hiSec * 10ul);
u32Tmp += g_u32loSec;
sPt->u32Second = u32Tmp;
}
}
/**
* @brief Update Current RTC Date and Time
*
* @param[in] sPt Specify the time property and current date and time. It includes: \n
* u32Year: Year value, range between 2000 ~ 2099. \n
* u32Month: Month value, range between 1 ~ 12. \n
* u32Day: Day value, range between 1 ~ 31. \n
* u32DayOfWeek: Day of the week. [RTC_SUNDAY / RTC_MONDAY / RTC_TUESDAY /
* RTC_WEDNESDAY / RTC_THURSDAY / RTC_FRIDAY /
* RTC_SATURDAY] \n
* u32Hour: Hour value, range between 0 ~ 23. \n
* u32Minute: Minute value, range between 0 ~ 59. \n
* u32Second: Second value, range between 0 ~ 59. \n
* u32TimeScale: [RTC_CLOCK_12 / RTC_CLOCK_24] \n
* u8AmPm: [RTC_AM / RTC_PM] \n
*
* @return None
*
* @details This API is used to update current date and time to RTC.
*/
void RTC_SetDateAndTime(S_RTC_TIME_DATA_T *sPt)
{
uint32_t u32RegCAL, u32RegTIME;
if(sPt == 0ul) {
} else {
/*-----------------------------------------------------------------------------------------------------*/
/* Set RTC 24/12 hour setting and Day of the Week */
/*-----------------------------------------------------------------------------------------------------*/
RTC_WaitAccessEnable();
if(sPt->u32TimeScale == RTC_CLOCK_12) {
RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk;
/*-------------------------------------------------------------------------------------------------*/
/* Important, range of 12-hour PM mode is 21 up to 32 */
/*-------------------------------------------------------------------------------------------------*/
if(sPt->u32AmPm == RTC_PM) {
sPt->u32Hour += 20ul;
}
} else {
RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk;
}
/* Set Day of the Week */
RTC_WaitAccessEnable();
RTC->WEEKDAY = sPt->u32DayOfWeek;
/*-----------------------------------------------------------------------------------------------------*/
/* Set RTC Current Date and Time */
/*-----------------------------------------------------------------------------------------------------*/
u32RegCAL = ((sPt->u32Year - RTC_YEAR2000) / 10ul) << 20;
u32RegCAL |= (((sPt->u32Year - RTC_YEAR2000) % 10ul) << 16);
u32RegCAL |= ((sPt->u32Month / 10ul) << 12);
u32RegCAL |= ((sPt->u32Month % 10ul) << 8);
u32RegCAL |= ((sPt->u32Day / 10ul) << 4);
u32RegCAL |= (sPt->u32Day % 10ul);
u32RegTIME = ((sPt->u32Hour / 10ul) << 20);
u32RegTIME |= ((sPt->u32Hour % 10ul) << 16);
u32RegTIME |= ((sPt->u32Minute / 10ul) << 12);
u32RegTIME |= ((sPt->u32Minute % 10ul) << 8);
u32RegTIME |= ((sPt->u32Second / 10ul) << 4);
u32RegTIME |= (sPt->u32Second % 10ul);
/*-----------------------------------------------------------------------------------------------------*/
/* Set RTC Calender and Time Loading */
/*-----------------------------------------------------------------------------------------------------*/
RTC_WaitAccessEnable();
RTC->CAL = (uint32_t)u32RegCAL;
RTC_WaitAccessEnable();
RTC->TIME = (uint32_t)u32RegTIME;
}
}
/**
* @brief Update RTC Alarm Date and Time
*
* @param[in] sPt Specify the time property and alarm date and time. It includes: \n
* u32Year: Year value, range between 2000 ~ 2099. \n
* u32Month: Month value, range between 1 ~ 12. \n
* u32Day: Day value, range between 1 ~ 31. \n
* u32DayOfWeek: Day of the week. [RTC_SUNDAY / RTC_MONDAY / RTC_TUESDAY /
* RTC_WEDNESDAY / RTC_THURSDAY / RTC_FRIDAY /
* RTC_SATURDAY] \n
* u32Hour: Hour value, range between 0 ~ 23. \n
* u32Minute: Minute value, range between 0 ~ 59. \n
* u32Second: Second value, range between 0 ~ 59. \n
* u32TimeScale: [RTC_CLOCK_12 / RTC_CLOCK_24] \n
* u8AmPm: [RTC_AM / RTC_PM] \n
*
* @return None
*
* @details This API is used to update alarm date and time setting to RTC.
*/
void RTC_SetAlarmDateAndTime(S_RTC_TIME_DATA_T *sPt)
{
uint32_t u32RegCALM, u32RegTALM;
if(sPt == 0) {
} else {
/*-----------------------------------------------------------------------------------------------------*/
/* Set RTC 24/12 hour setting and Day of the Week */
/*-----------------------------------------------------------------------------------------------------*/
RTC_WaitAccessEnable();
if(sPt->u32TimeScale == RTC_CLOCK_12) {
RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk;
/*-------------------------------------------------------------------------------------------------*/
/* Important, range of 12-hour PM mode is 21 up to 32 */
/*-------------------------------------------------------------------------------------------------*/
if(sPt->u32AmPm == RTC_PM) {
sPt->u32Hour += 20ul;
}
} else {
RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk;
}
/*-----------------------------------------------------------------------------------------------------*/
/* Set RTC Alarm Date and Time */
/*-----------------------------------------------------------------------------------------------------*/
u32RegCALM = ((sPt->u32Year - RTC_YEAR2000) / 10ul) << 20;
u32RegCALM |= (((sPt->u32Year - RTC_YEAR2000) % 10ul) << 16);
u32RegCALM |= ((sPt->u32Month / 10ul) << 12);
u32RegCALM |= ((sPt->u32Month % 10ul) << 8);
u32RegCALM |= ((sPt->u32Day / 10ul) << 4);
u32RegCALM |= (sPt->u32Day % 10ul);
u32RegTALM = ((sPt->u32Hour / 10ul) << 20);
u32RegTALM |= ((sPt->u32Hour % 10ul) << 16);
u32RegTALM |= ((sPt->u32Minute / 10ul) << 12);
u32RegTALM |= ((sPt->u32Minute % 10ul) << 8);
u32RegTALM |= ((sPt->u32Second / 10ul) << 4);
u32RegTALM |= (sPt->u32Second % 10ul);
RTC_WaitAccessEnable();
RTC->CALM = (uint32_t)u32RegCALM;
RTC_WaitAccessEnable();
RTC->TALM = (uint32_t)u32RegTALM;
}
}
/**
* @brief Update RTC Current Date
*
* @param[in] u32Year The year calendar digit of current RTC setting.
* @param[in] u32Month The month calendar digit of current RTC setting.
* @param[in] u32Day The day calendar digit of current RTC setting.
* @param[in] u32DayOfWeek The Day of the week. [RTC_SUNDAY / RTC_MONDAY / RTC_TUESDAY /
* RTC_WEDNESDAY / RTC_THURSDAY / RTC_FRIDAY /
* RTC_SATURDAY]
*
* @return None
*
* @details This API is used to update current date to RTC.
*/
void RTC_SetDate(uint32_t u32Year, uint32_t u32Month, uint32_t u32Day, uint32_t u32DayOfWeek)
{
uint32_t u32RegCAL;
u32RegCAL = ((u32Year - RTC_YEAR2000) / 10ul) << 20;
u32RegCAL |= (((u32Year - RTC_YEAR2000) % 10ul) << 16);
u32RegCAL |= ((u32Month / 10ul) << 12);
u32RegCAL |= ((u32Month % 10ul) << 8);
u32RegCAL |= ((u32Day / 10ul) << 4);
u32RegCAL |= (u32Day % 10ul);
/* Set Day of the Week */
RTC_WaitAccessEnable();
RTC->WEEKDAY = u32DayOfWeek & RTC_WEEKDAY_WEEKDAY_Msk;
/* Set RTC Calender Loading */
RTC_WaitAccessEnable();
RTC->CAL = (uint32_t)u32RegCAL;
}
/**
* @brief Update RTC Current Time
*
* @param[in] u32Hour The hour time digit of current RTC setting.
* @param[in] u32Minute The minute time digit of current RTC setting.
* @param[in] u32Second The second time digit of current RTC setting.
* @param[in] u32TimeMode The 24-Hour / 12-Hour Time Scale Selection. [RTC_CLOCK_12 / RTC_CLOCK_24]
* @param[in] u32AmPm 12-hour time scale with AM and PM indication. Only Time Scale select 12-hour used. [RTC_AM / RTC_PM]
*
* @return None
*
* @details This API is used to update current time to RTC.
*/
void RTC_SetTime(uint32_t u32Hour, uint32_t u32Minute, uint32_t u32Second, uint32_t u32TimeMode, uint32_t u32AmPm)
{
uint32_t u32RegTIME;
/* Important, range of 12-hour PM mode is 21 up to 32 */
if((u32TimeMode == RTC_CLOCK_12) && (u32AmPm == RTC_PM)) {
u32Hour += 20ul;
}
u32RegTIME = ((u32Hour / 10ul) << 20);
u32RegTIME |= ((u32Hour % 10ul) << 16);
u32RegTIME |= ((u32Minute / 10ul) << 12);
u32RegTIME |= ((u32Minute % 10ul) << 8);
u32RegTIME |= ((u32Second / 10ul) << 4);
u32RegTIME |= (u32Second % 10ul);
/*-----------------------------------------------------------------------------------------------------*/
/* Set RTC 24/12 hour setting and Day of the Week */
/*-----------------------------------------------------------------------------------------------------*/
RTC_WaitAccessEnable();
if(u32TimeMode == RTC_CLOCK_12) {
RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk;
} else {
RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk;
}
RTC_WaitAccessEnable();
RTC->TIME = (uint32_t)u32RegTIME;
}
/**
* @brief Update RTC Alarm Date
*
* @param[in] u32Year The year calendar digit of RTC alarm setting.
* @param[in] u32Month The month calendar digit of RTC alarm setting.
* @param[in] u32Day The day calendar digit of RTC alarm setting.
*
* @return None
*
* @details This API is used to update alarm date setting to RTC.
*/
void RTC_SetAlarmDate(uint32_t u32Year, uint32_t u32Month, uint32_t u32Day)
{
uint32_t u32RegCALM;
u32RegCALM = ((u32Year - RTC_YEAR2000) / 10ul) << 20;
u32RegCALM |= (((u32Year - RTC_YEAR2000) % 10ul) << 16);
u32RegCALM |= ((u32Month / 10ul) << 12);
u32RegCALM |= ((u32Month % 10ul) << 8);
u32RegCALM |= ((u32Day / 10ul) << 4);
u32RegCALM |= (u32Day % 10ul);
RTC_WaitAccessEnable();
/* Set RTC Alarm Date */
RTC->CALM = (uint32_t)u32RegCALM;
}
/**
* @brief Update RTC Alarm Time
*
* @param[in] u32Hour The hour time digit of RTC alarm setting.
* @param[in] u32Minute The minute time digit of RTC alarm setting.
* @param[in] u32Second The second time digit of RTC alarm setting.
* @param[in] u32TimeMode The 24-Hour / 12-Hour Time Scale Selection. [RTC_CLOCK_12 / RTC_CLOCK_24]
* @param[in] u32AmPm 12-hour time scale with AM and PM indication. Only Time Scale select 12-hour used. [RTC_AM / RTC_PM]
*
* @return None
*
* @details This API is used to update alarm time setting to RTC.
*/
void RTC_SetAlarmTime(uint32_t u32Hour, uint32_t u32Minute, uint32_t u32Second, uint32_t u32TimeMode, uint32_t u32AmPm)
{
uint32_t u32RegTALM;
/* Important, range of 12-hour PM mode is 21 up to 32 */
if((u32TimeMode == RTC_CLOCK_12) && (u32AmPm == RTC_PM)) {
u32Hour += 20ul;
}
u32RegTALM = ((u32Hour / 10ul) << 20);
u32RegTALM |= ((u32Hour % 10ul) << 16);
u32RegTALM |= ((u32Minute / 10ul) << 12);
u32RegTALM |= ((u32Minute % 10ul) << 8);
u32RegTALM |= ((u32Second / 10ul) << 4);
u32RegTALM |= (u32Second % 10ul);
/*-----------------------------------------------------------------------------------------------------*/
/* Set RTC 24/12 hour setting and Day of the Week */
/*-----------------------------------------------------------------------------------------------------*/
RTC_WaitAccessEnable();
if(u32TimeMode == RTC_CLOCK_12) {
RTC->CLKFMT &= ~RTC_CLKFMT_24HEN_Msk;
} else {
RTC->CLKFMT |= RTC_CLKFMT_24HEN_Msk;
}
/* Set RTC Alarm Time */
RTC_WaitAccessEnable();
RTC->TALM = (uint32_t)u32RegTALM;
}
/**
* @brief Get Day of the Week
*
* @param None
*
* @retval 0 Sunday
* @retval 1 Monday
* @retval 2 Tuesday
* @retval 3 Wednesday
* @retval 4 Thursday
* @retval 5 Friday
* @retval 6 Saturday
*
* @details This API is used to get day of the week of current RTC date.
*/
uint32_t RTC_GetDayOfWeek(void)
{
return (RTC->WEEKDAY & RTC_WEEKDAY_WEEKDAY_Msk);
}
/**
* @brief Set RTC Tick Period Time
*
* @param[in] u32TickSelection It is used to set the RTC tick period time for Periodic Time Tick request. \n
* It consists of:
* - \ref RTC_TICK_1_SEC : Time tick is 1 second
* - \ref RTC_TICK_1_2_SEC : Time tick is 1/2 second
* - \ref RTC_TICK_1_4_SEC : Time tick is 1/4 second
* - \ref RTC_TICK_1_8_SEC : Time tick is 1/8 second
* - \ref RTC_TICK_1_16_SEC : Time tick is 1/16 second
* - \ref RTC_TICK_1_32_SEC : Time tick is 1/32 second
* - \ref RTC_TICK_1_64_SEC : Time tick is 1/64 second
* - \ref RTC_TICK_1_128_SEC : Time tick is 1/128 second
*
* @return None
*
* @details This API is used to set RTC tick period time for each tick interrupt.
*/
void RTC_SetTickPeriod(uint32_t u32TickSelection)
{
RTC_WaitAccessEnable();
RTC->TICK = (RTC->TICK & ~RTC_TICK_TICK_Msk) | u32TickSelection;
}
/**
* @brief Enable RTC Interrupt
*
* @param[in] u32IntFlagMask Specify the interrupt source. It consists of:
* - \ref RTC_INTEN_ALMIEN_Msk : Alarm interrupt
* - \ref RTC_INTEN_TICKIEN_Msk : Tick interrupt
* - \ref RTC_INTEN_TAMP0IEN_Msk : Tamper 0 Pin Event Detection interrupt
* - \ref RTC_INTEN_TAMP1IEN_Msk : Tamper 1 Pin Event Detection interrupt
* - \ref RTC_INTEN_TAMP2IEN_Msk : Tamper 2 Pin Event Detection interrupt
* - \ref RTC_INTEN_TAMP3IEN_Msk : Tamper 3 Pin Event Detection interrupt
* - \ref RTC_INTEN_TAMP4IEN_Msk : Tamper 4 Pin Event Detection interrupt
* - \ref RTC_INTEN_TAMP5IEN_Msk : Tamper 5 Pin Event Detection interrupt
*
* @return None
*
* @details This API is used to enable the specify RTC interrupt function.
*/
void RTC_EnableInt(uint32_t u32IntFlagMask)
{
RTC_WaitAccessEnable();
RTC->INTEN |= u32IntFlagMask;
}
/**
* @brief Disable RTC Interrupt
*
* @param[in] u32IntFlagMask Specify the interrupt source. It consists of:
* - \ref RTC_INTEN_ALMIEN_Msk : Alarm interrupt
* - \ref RTC_INTEN_TICKIEN_Msk : Tick interrupt
* - \ref RTC_INTEN_TAMP0IEN_Msk : Tamper 0 Pin Event Detection interrupt
* - \ref RTC_INTEN_TAMP1IEN_Msk : Tamper 1 Pin Event Detection interrupt
* - \ref RTC_INTEN_TAMP2IEN_Msk : Tamper 2 Pin Event Detection interrupt
* - \ref RTC_INTEN_TAMP3IEN_Msk : Tamper 3 Pin Event Detection interrupt
* - \ref RTC_INTEN_TAMP4IEN_Msk : Tamper 4 Pin Event Detection interrupt
* - \ref RTC_INTEN_TAMP5IEN_Msk : Tamper 5 Pin Event Detection interrupt
*
* @return None
*
* @details This API is used to disable the specify RTC interrupt function.
*/
void RTC_DisableInt(uint32_t u32IntFlagMask)
{
RTC_WaitAccessEnable();
RTC->INTEN &= ~u32IntFlagMask;
RTC_WaitAccessEnable();
RTC->INTSTS = u32IntFlagMask;
}
/**
* @brief Enable Spare Registers Access
*
* @param None
*
* @return None
*
* @details This API is used to enable the spare registers 0~19 can be accessed.
*/
void RTC_EnableSpareAccess(void)
{
RTC_WaitAccessEnable();
RTC->SPRCTL |= RTC_SPRCTL_SPRRWEN_Msk;
}
/**
* @brief Disable Spare Register
*
* @param None
*
* @return None
*
* @details This API is used to disable the spare register 0~19 cannot be accessed.
*/
void RTC_DisableSpareRegister(void)
{
RTC_WaitAccessEnable();
RTC->SPRCTL &= ~RTC_SPRCTL_SPRRWEN_Msk;
}
/**
* @brief Static Tamper Detect
*
* @param[in] u32TamperSelect Tamper pin select. Possible options are
* - \ref RTC_TAMPER5_SELECT
* - \ref RTC_TAMPER4_SELECT
* - \ref RTC_TAMPER3_SELECT
* - \ref RTC_TAMPER2_SELECT
* - \ref RTC_TAMPER1_SELECT
* - \ref RTC_TAMPER0_SELECT
*
* @param[in] u32DetecLevel Tamper pin detection level select. Possible options are
* - \ref RTC_TAMPER_HIGH_LEVEL_DETECT
* - \ref RTC_TAMPER_LOW_LEVEL_DETECT
*
* @param[in] u32DebounceEn Tamper pin de-bounce enable
* - \ref RTC_TAMPER_DEBOUNCE_ENABLE
* - \ref RTC_TAMPER_DEBOUNCE_DISABLE
*
* @return None
*
* @details This API is used to enable the tamper pin detect function with specify trigger condition.
*/
void RTC_StaticTamperEnable(uint32_t u32TamperSelect, uint32_t u32DetecLevel, uint32_t u32DebounceEn)
{
uint32_t i;
uint32_t u32Reg;
uint32_t u32TmpReg;
RTC_WaitAccessEnable();
u32Reg = RTC->TAMPCTL;
u32TmpReg = ( RTC_TAMPCTL_TAMP0EN_Msk | (u32DetecLevel << RTC_TAMPCTL_TAMP0LV_Pos) |
(u32DebounceEn << RTC_TAMPCTL_TAMP0DBEN_Pos) );
for(i = 0ul; i < MAX_TAMPER_PIN_NUM; i++) {
if(u32TamperSelect & (0x1ul << i)) {
u32Reg &= ~((RTC_TAMPCTL_TAMP0EN_Msk|RTC_TAMPCTL_TAMP0LV_Msk|RTC_TAMPCTL_TAMP0DBEN_Msk) << (i*4ul));
u32Reg |= (u32TmpReg << (i*4ul));
}
}
RTC_WaitAccessEnable();
RTC->TAMPCTL = u32Reg;
}
/**
* @brief Static Tamper Disable
*
* @param[in] u32TamperSelect Tamper pin select. Possible options are
* - \ref RTC_TAMPER5_SELECT
* - \ref RTC_TAMPER4_SELECT
* - \ref RTC_TAMPER3_SELECT
* - \ref RTC_TAMPER2_SELECT
* - \ref RTC_TAMPER1_SELECT
* - \ref RTC_TAMPER0_SELECT
*
* @return None
*
* @details This API is used to disable the static tamper pin detect.
*/
void RTC_StaticTamperDisable(uint32_t u32TamperSelect)
{
uint32_t i;
uint32_t u32Reg;
uint32_t u32TmpReg;
RTC_WaitAccessEnable();
u32Reg = RTC->TAMPCTL;
u32TmpReg = (RTC_TAMPCTL_TAMP0EN_Msk);
for(i = 0ul; i < MAX_TAMPER_PIN_NUM; i++) {
if(u32TamperSelect & (0x1ul << i)) {
u32Reg &= ~(u32TmpReg << (i*4ul));
}
}
RTC_WaitAccessEnable();
RTC->TAMPCTL = u32Reg;
}
/**
* @brief Dynamic Tamper Detect
*
* @param[in] u32PairSel Tamper pin detection enable. Possible options are
* - \ref RTC_PAIR0_SELECT
* - \ref RTC_PAIR1_SELECT
* - \ref RTC_PAIR2_SELECT
*
* @param[in] u32DebounceEn Tamper pin de-bounce enable
* - \ref RTC_TAMPER_DEBOUNCE_ENABLE
* - \ref RTC_TAMPER_DEBOUNCE_DISABLE
*
* @param[in] u32Pair1Source Dynamic Pair 1 Input Source Select
* 0: Pair 1 source select tamper 2
* 1: Pair 1 source select tamper 0
*
* @param[in] u32Pair2Source Dynamic Pair 2 Input Source Select
* 0: Pair 2 source select tamper 4
* 1: Pair 2 source select tamper 0
*
* @return None
*
* @details This API is used to enable the dynamic tamper.
*/
void RTC_DynamicTamperEnable(uint32_t u32PairSel, uint32_t u32DebounceEn, uint32_t u32Pair1Source, uint32_t u32Pair2Source)
{
uint32_t i;
uint32_t u32Reg;
uint32_t u32TmpReg;
uint32_t u32Tamper2Debounce, u32Tamper4Debounce;
RTC_WaitAccessEnable();
u32Reg = RTC->TAMPCTL;
u32Tamper2Debounce = u32Reg & RTC_TAMPCTL_TAMP2DBEN_Msk;
u32Tamper4Debounce = u32Reg & RTC_TAMPCTL_TAMP4DBEN_Msk;
u32Reg &= ~(RTC_TAMPCTL_TAMP0EN_Msk | RTC_TAMPCTL_TAMP1EN_Msk | RTC_TAMPCTL_TAMP2EN_Msk |
RTC_TAMPCTL_TAMP3EN_Msk | RTC_TAMPCTL_TAMP4EN_Msk | RTC_TAMPCTL_TAMP5EN_Msk);
u32Reg &= ~(RTC_TAMPCTL_DYN1ISS_Msk | RTC_TAMPCTL_DYN2ISS_Msk);
u32Reg |= ((u32Pair1Source & 0x1ul) << RTC_TAMPCTL_DYN1ISS_Pos) | ((u32Pair2Source & 0x1ul) << RTC_TAMPCTL_DYN2ISS_Pos);
if(u32DebounceEn) {
u32TmpReg = (RTC_TAMPCTL_TAMP0EN_Msk | RTC_TAMPCTL_TAMP1EN_Msk |
RTC_TAMPCTL_TAMP0DBEN_Msk | RTC_TAMPCTL_TAMP1DBEN_Msk | RTC_TAMPCTL_DYNPR0EN_Msk);
} else {
u32TmpReg = (RTC_TAMPCTL_TAMP0EN_Msk | RTC_TAMPCTL_TAMP1EN_Msk | RTC_TAMPCTL_DYNPR0EN_Msk);
}
for(i = 0ul; i < MAX_PAIR_NUM; i++) {
if(u32PairSel & (0x1ul << i)) {
u32Reg &= ~((RTC_TAMPCTL_TAMP0DBEN_Msk | RTC_TAMPCTL_TAMP1DBEN_Msk) << (i*8ul));
u32Reg |= (u32TmpReg << (i*8ul));
}
}
if((u32Pair1Source) && (u32PairSel & RTC_PAIR1_SELECT)) {
u32Reg &= ~RTC_TAMPCTL_TAMP2EN_Msk;
u32Reg |= u32Tamper2Debounce;
}
if((u32Pair2Source) && (u32PairSel & RTC_PAIR2_SELECT)) {
u32Reg &= ~RTC_TAMPCTL_TAMP4EN_Msk;
u32Reg |= u32Tamper4Debounce;
}
RTC_WaitAccessEnable();
RTC->TAMPCTL = u32Reg;
}
/**
* @brief Dynamic Tamper Disable
*
* @param[in] u32PairSel Tamper pin detection enable. Possible options are
* - \ref RTC_PAIR0_SELECT
* - \ref RTC_PAIR1_SELECT
* - \ref RTC_PAIR2_SELECT
*
* @return None
*
* @details This API is used to disable the dynamic tamper.
*/
void RTC_DynamicTamperDisable(uint32_t u32PairSel)
{
uint32_t i;
uint32_t u32Reg;
uint32_t u32TmpReg;
uint32_t u32Tamper2En = 0ul, u32Tamper4En = 0ul;
RTC_WaitAccessEnable();
u32Reg = RTC->TAMPCTL;
if((u32Reg & RTC_TAMPCTL_DYN1ISS_Msk) && (u32PairSel & RTC_PAIR1_SELECT)) {
u32Tamper2En = u32Reg & RTC_TAMPCTL_TAMP2EN_Msk;
}
if((u32Reg & RTC_TAMPCTL_DYN2ISS_Msk) && (u32PairSel & RTC_PAIR2_SELECT)) {
u32Tamper4En = u32Reg & RTC_TAMPCTL_TAMP4EN_Msk;
}
u32TmpReg = (RTC_TAMPCTL_TAMP0EN_Msk | RTC_TAMPCTL_TAMP1EN_Msk | RTC_TAMPCTL_DYNPR0EN_Msk);
for(i = 0ul; i < MAX_PAIR_NUM; i++) {
if(u32PairSel & (0x1ul << i)) {
u32Reg &= ~(u32TmpReg << ((i*8ul)));
}
}
u32Reg |= (u32Tamper2En | u32Tamper4En);
RTC_WaitAccessEnable();
RTC->TAMPCTL = u32Reg;
}
/**
* @brief Config dynamic tamper
*
* @param[in] u32ChangeRate The dynamic tamper output change rate
* - \ref RTC_2POW10_CLK
* - \ref RTC_2POW11_CLK
* - \ref RTC_2POW12_CLK
* - \ref RTC_2POW13_CLK
* - \ref RTC_2POW14_CLK
* - \ref RTC_2POW15_CLK
* - \ref RTC_2POW16_CLK
* - \ref RTC_2POW17_CLK
*
* @param[in] u32SeedReload Reload new seed or not
* 0: not reload new seed
* 1: reload new seed
*
* @param[in] u32RefPattern Reference pattern
* - \ref REF_RANDOM_PATTERN
* - \ref REF_PREVIOUS_PATTERN
* - \ref REF_SEED
*
* @param[in] u32Seed Seed Value (0x0 ~ 0xFFFFFFFF)
*
* @return None
*
* @details This API is used to config dynamic tamper setting.
*/
void RTC_DynamicTamperConfig(uint32_t u32ChangeRate, uint32_t u32SeedReload, uint32_t u32RefPattern, uint32_t u32Seed)
{
uint32_t u32Reg;
RTC_WaitAccessEnable();
u32Reg = RTC->TAMPCTL;
u32Reg &= ~(RTC_TAMPCTL_DYNSRC_Msk | RTC_TAMPCTL_SEEDRLD_Msk | RTC_TAMPCTL_DYNRATE_Msk);
u32Reg |= (u32ChangeRate) | ((u32SeedReload & 0x1ul) << RTC_TAMPCTL_SEEDRLD_Pos) |
((u32RefPattern & 0x3ul) << RTC_TAMPCTL_DYNSRC_Pos);
RTC_WaitAccessEnable();
RTC->TAMPSEED = u32Seed; /* need set seed value before re-load seed */
RTC->TAMPCTL = u32Reg;
}
/*@}*/ /* end of group M480_RTC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_RTC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,333 @@
/**************************************************************************//**
* @file rtc.h
* @version V3.00
* @brief M480 series RTC driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __RTC_H__
#define __RTC_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_RTC_Driver RTC Driver
@{
*/
/** @addtogroup M480_RTC_EXPORTED_CONSTANTS RTC Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* RTC Initial Keyword Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_INIT_KEY 0xA5EB1357UL /*!< RTC Initiation Key to make RTC leaving reset state \hideinitializer */
#define RTC_WRITE_KEY 0x0000A965UL /*!< RTC Register Access Enable Key to enable RTC read/write accessible and kept 1024 RTC clock \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* RTC Time Attribute Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_CLOCK_12 0UL /*!< RTC as 12-hour time scale with AM and PM indication \hideinitializer */
#define RTC_CLOCK_24 1UL /*!< RTC as 24-hour time scale \hideinitializer */
#define RTC_AM 1UL /*!< RTC as AM indication \hideinitializer */
#define RTC_PM 2UL /*!< RTC as PM indication \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* RTC Tick Period Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_TICK_1_SEC 0x0UL /*!< RTC time tick period is 1 second \hideinitializer */
#define RTC_TICK_1_2_SEC 0x1UL /*!< RTC time tick period is 1/2 second \hideinitializer */
#define RTC_TICK_1_4_SEC 0x2UL /*!< RTC time tick period is 1/4 second \hideinitializer */
#define RTC_TICK_1_8_SEC 0x3UL /*!< RTC time tick period is 1/8 second \hideinitializer */
#define RTC_TICK_1_16_SEC 0x4UL /*!< RTC time tick period is 1/16 second \hideinitializer */
#define RTC_TICK_1_32_SEC 0x5UL /*!< RTC time tick period is 1/32 second \hideinitializer */
#define RTC_TICK_1_64_SEC 0x6UL /*!< RTC time tick period is 1/64 second \hideinitializer */
#define RTC_TICK_1_128_SEC 0x7UL /*!< RTC time tick period is 1/128 second \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* RTC Day of Week Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_SUNDAY 0x0UL /*!< Day of the Week is Sunday \hideinitializer */
#define RTC_MONDAY 0x1UL /*!< Day of the Week is Monday \hideinitializer */
#define RTC_TUESDAY 0x2UL /*!< Day of the Week is Tuesday \hideinitializer */
#define RTC_WEDNESDAY 0x3UL /*!< Day of the Week is Wednesday \hideinitializer */
#define RTC_THURSDAY 0x4UL /*!< Day of the Week is Thursday \hideinitializer */
#define RTC_FRIDAY 0x5UL /*!< Day of the Week is Friday \hideinitializer */
#define RTC_SATURDAY 0x6UL /*!< Day of the Week is Saturday \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* RTC Miscellaneous Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_WAIT_COUNT 0xFFFFFFFFUL /*!< Initial Time-out Value \hideinitializer */
#define RTC_YEAR2000 2000UL /*!< RTC Reference for compute year data \hideinitializer */
#define RTC_FCR_REFERENCE 32761UL /*!< RTC Reference for frequency compensation \hideinitializer */
#define RTC_TAMPER0_SELECT (0x1ul << 0) /*!< Select Tamper 0 \hideinitializer */
#define RTC_TAMPER1_SELECT (0x1ul << 1) /*!< Select Tamper 1 \hideinitializer */
#define RTC_TAMPER2_SELECT (0x1ul << 2) /*!< Select Tamper 2 \hideinitializer */
#define RTC_TAMPER3_SELECT (0x1ul << 3) /*!< Select Tamper 3 \hideinitializer */
#define RTC_TAMPER4_SELECT (0x1ul << 4) /*!< Select Tamper 4 \hideinitializer */
#define RTC_TAMPER5_SELECT (0x1ul << 5) /*!< Select Tamper 5 \hideinitializer */
#define MAX_TAMPER_PIN_NUM 6ul /*!< Tamper Pin number \hideinitializer */
#define RTC_TAMPER_HIGH_LEVEL_DETECT 1ul /*!< Tamper pin detect voltage level is high \hideinitializer */
#define RTC_TAMPER_LOW_LEVEL_DETECT 0ul /*!< Tamper pin detect voltage level is low \hideinitializer */
#define RTC_TAMPER_DEBOUNCE_ENABLE 1ul /*!< Enable RTC tamper pin de-bounce function \hideinitializer */
#define RTC_TAMPER_DEBOUNCE_DISABLE 0ul /*!< Disable RTC tamper pin de-bounce function \hideinitializer */
#define RTC_PAIR0_SELECT (0x1ul << 0) /*!< Select Pair 0 \hideinitializer */
#define RTC_PAIR1_SELECT (0x1ul << 1) /*!< Select Pair 1 \hideinitializer */
#define RTC_PAIR2_SELECT (0x1ul << 2) /*!< Select Pair 2 \hideinitializer */
#define MAX_PAIR_NUM 3ul /*!< Pair number \hideinitializer */
#define RTC_2POW10_CLK (0x0 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 RTC clock cycles \hideinitializer */
#define RTC_2POW11_CLK (0x1 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 2 RTC clock cycles \hideinitializer */
#define RTC_2POW12_CLK (0x2 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 4 RTC clock cycles \hideinitializer */
#define RTC_2POW13_CLK (0x3 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 6 RTC clock cycles \hideinitializer */
#define RTC_2POW14_CLK (0x4 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 8 RTC clock cycles \hideinitializer */
#define RTC_2POW15_CLK (0x5 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 16 RTC clock cycles \hideinitializer */
#define RTC_2POW16_CLK (0x6 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 32 RTC clock cycles \hideinitializer */
#define RTC_2POW17_CLK (0x7 << RTC_TAMPCTL_DYNRATE_Pos) /*!< 1024 x 64 RTC clock cycles \hideinitializer */
#define REF_RANDOM_PATTERN 0x0 /*!< The new reference pattern is generated by random number generator when the reference pattern run out \hideinitializer */
#define REF_PREVIOUS_PATTERN 0x1 /*!< The new reference pattern is repeated previous random value when the reference pattern run out \hideinitializer */
#define REF_SEED 0x3 /*!< The new reference pattern is repeated from SEED (RTC_TAMPSEED[31:0]) when the reference pattern run out \hideinitializer */
/*@}*/ /* end of group M480_RTC_EXPORTED_CONSTANTS */
/** @addtogroup M480_RTC_EXPORTED_STRUCTS RTC Exported Structs
@{
*/
/**
* @details RTC define Time Data Struct
*/
typedef struct {
uint32_t u32Year; /*!< Year value */
uint32_t u32Month; /*!< Month value */
uint32_t u32Day; /*!< Day value */
uint32_t u32DayOfWeek; /*!< Day of week value */
uint32_t u32Hour; /*!< Hour value */
uint32_t u32Minute; /*!< Minute value */
uint32_t u32Second; /*!< Second value */
uint32_t u32TimeScale; /*!< 12-Hour, 24-Hour */
uint32_t u32AmPm; /*!< Only Time Scale select 12-hr used */
} S_RTC_TIME_DATA_T;
/*@}*/ /* end of group M480_RTC_EXPORTED_STRUCTS */
/** @addtogroup M480_RTC_EXPORTED_FUNCTIONS RTC Exported Functions
@{
*/
/**
* @brief Indicate is Leap Year or not
*
* @param None
*
* @retval 0 This year is not a leap year
* @retval 1 This year is a leap year
*
* @details According to current date, return this year is leap year or not.
* \hideinitializer
*/
#define RTC_IS_LEAP_YEAR() (RTC->LEAPYEAR & RTC_LEAPYEAR_LEAPYEAR_Msk ? 1:0)
/**
* @brief Clear RTC Alarm Interrupt Flag
*
* @param None
*
* @return None
*
* @details This macro is used to clear RTC alarm interrupt flag.
* \hideinitializer
*/
#define RTC_CLEAR_ALARM_INT_FLAG() (RTC->INTSTS = RTC_INTSTS_ALMIF_Msk)
/**
* @brief Clear RTC Tick Interrupt Flag
*
* @param None
*
* @return None
*
* @details This macro is used to clear RTC tick interrupt flag.
* \hideinitializer
*/
#define RTC_CLEAR_TICK_INT_FLAG() (RTC->INTSTS = RTC_INTSTS_TICKIF_Msk)
/**
* @brief Clear RTC Tamper Interrupt Flag
*
* @param u32TamperFlag Tamper interrupt flag. It consists of: \n
* - \ref RTC_INTSTS_TAMP0IF_Msk \n
* - \ref RTC_INTSTS_TAMP1IF_Msk \n
* - \ref RTC_INTSTS_TAMP2IF_Msk \n
* - \ref RTC_INTSTS_TAMP3IF_Msk \n
* - \ref RTC_INTSTS_TAMP4IF_Msk \n
* - \ref RTC_INTSTS_TAMP5IF_Msk
*
* @return None
*
* @details This macro is used to clear RTC snooper pin interrupt flag.
* \hideinitializer
*/
#define RTC_CLEAR_TAMPER_INT_FLAG(u32TamperFlag) (RTC->INTSTS = (u32TamperFlag))
/**
* @brief Get RTC Alarm Interrupt Flag
*
* @param None
*
* @retval 0 RTC alarm interrupt did not occur
* @retval 1 RTC alarm interrupt occurred
*
* @details This macro indicates RTC alarm interrupt occurred or not.
* \hideinitializer
*/
#define RTC_GET_ALARM_INT_FLAG() ((RTC->INTSTS & RTC_INTSTS_ALMIF_Msk)? 1:0)
/**
* @brief Get RTC Time Tick Interrupt Flag
*
* @param None
*
* @retval 0 RTC time tick interrupt did not occur
* @retval 1 RTC time tick interrupt occurred
*
* @details This macro indicates RTC time tick interrupt occurred or not.
* \hideinitializer
*/
#define RTC_GET_TICK_INT_FLAG() ((RTC->INTSTS & RTC_INTSTS_TICKIF_Msk)? 1:0)
/**
* @brief Get RTC Tamper Interrupt Flag
*
* @param None
*
* @retval 0 RTC snooper pin interrupt did not occur
* @retval 1 RTC snooper pin interrupt occurred
*
* @details This macro indicates RTC snooper pin interrupt occurred or not.
* \hideinitializer
*/
#define RTC_GET_TAMPER_INT_FLAG() ((RTC->INTSTS & (0x3F00))? 1:0)
/**
* @brief Get RTC TAMPER Interrupt Status
*
* @param None
*
* @retval RTC_INTSTS_TAMP0IF_Msk Tamper 0 interrupt flag is generated
* @retval RTC_INTSTS_TAMP1IF_Msk Tamper 1 interrupt flag is generated
* @retval RTC_INTSTS_TAMP2IF_Msk Tamper 2 interrupt flag is generated
* @retval RTC_INTSTS_TAMP3IF_Msk Tamper 3 interrupt flag is generated
* @retval RTC_INTSTS_TAMP4IF_Msk Tamper 4 interrupt flag is generated
* @retval RTC_INTSTS_TAMP5IF_Msk Tamper 5 interrupt flag is generated
*
* @details This macro indicates RTC snooper pin interrupt occurred or not.
* \hideinitializer
*/
#define RTC_GET_TAMPER_INT_STATUS() ((RTC->INTSTS & (0x3F00)))
/**
* @brief Read Spare Register
*
* @param[in] u32RegNum The spare register number, 0~19.
*
* @return Spare register content
*
* @details Read the specify spare register content.
* @note The returned value is valid only when SPRRDY(SPRCTL[7] SPR Register Ready) bit is set. \n
* And its controlled by RTC Access Enable Register.
* \hideinitializer
*/
#define RTC_READ_SPARE_REGISTER(u32RegNum) (RTC->SPR[(u32RegNum)])
/**
* @brief Write Spare Register
*
* @param[in] u32RegNum The spare register number, 0~19.
* @param[in] u32RegValue The spare register value.
*
* @return None
*
* @details Write specify data to spare register.
* @note This macro is effect only when SPRRDY(SPRCTL[7] SPR Register Ready) bit is set. \n
* And its controlled by RTC Access Enable Register(RTC_RWEN).
* \hideinitializer
*/
#define RTC_WRITE_SPARE_REGISTER(u32RegNum, u32RegValue) (RTC->SPR[(u32RegNum)] = (u32RegValue))
/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */
static __INLINE void RTC_WaitAccessEnable(void);
/**
* @brief Wait RTC Access Enable
*
* @param None
*
* @return None
*
* @details This function is used to enable the maximum RTC read/write accessible time.
*/
static __INLINE void RTC_WaitAccessEnable(void)
{
while((RTC->RWEN & RTC_RWEN_RTCBUSY_Msk) == RTC_RWEN_RTCBUSY_Msk) {
}
/* To wait RWENF bit is cleared and enable RWENF bit (Access Enable bit) again */
RTC->RWEN = RTC_WRITE_KEY;
/* To wait RWENF bit is set and user can access the protected-register of RTC from now on */
while((RTC->RWEN & RTC_RWEN_RWENF_Msk) == (uint32_t)0x0) {
}
}
void RTC_Open(S_RTC_TIME_DATA_T *sPt);
void RTC_Close(void);
void RTC_32KCalibration(int32_t i32FrequencyX10000);
void RTC_GetDateAndTime(S_RTC_TIME_DATA_T *sPt);
void RTC_GetAlarmDateAndTime(S_RTC_TIME_DATA_T *sPt);
void RTC_SetDateAndTime(S_RTC_TIME_DATA_T *sPt);
void RTC_SetAlarmDateAndTime(S_RTC_TIME_DATA_T *sPt);
void RTC_SetDate(uint32_t u32Year, uint32_t u32Month, uint32_t u32Day, uint32_t u32DayOfWeek);
void RTC_SetTime(uint32_t u32Hour, uint32_t u32Minute, uint32_t u32Second, uint32_t u32TimeMode, uint32_t u32AmPm);
void RTC_SetAlarmDate(uint32_t u32Year, uint32_t u32Month, uint32_t u32Day);
void RTC_SetAlarmTime(uint32_t u32Hour, uint32_t u32Minute, uint32_t u32Second, uint32_t u32TimeMode, uint32_t u32AmPm);
uint32_t RTC_GetDayOfWeek(void);
void RTC_SetTickPeriod(uint32_t u32TickSelection);
void RTC_EnableInt(uint32_t u32IntFlagMask);
void RTC_DisableInt(uint32_t u32IntFlagMask);
void RTC_EnableSpareAccess(void);
void RTC_DisableSpareRegister(void);
void RTC_StaticTamperEnable(uint32_t u32TamperSelect, uint32_t u32DetecLevel, uint32_t u32DebounceEn);
void RTC_StaticTamperDisable(uint32_t u32TamperSelect);
void RTC_DynamicTamperEnable(uint32_t u32PairSel, uint32_t u32DebounceEn, uint32_t u32Pair1Source, uint32_t u32Pair2Source);
void RTC_DynamicTamperDisable(uint32_t u32PairSel);
void RTC_DynamicTamperConfig(uint32_t u32ChangeRate, uint32_t u32SeedReload, uint32_t u32RefPattern, uint32_t u32Seed);
/*@}*/ /* end of group M480_RTC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_RTC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __RTC_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,337 @@
/**************************************************************************//**
* @file sc.c
* @version V3.00
* @brief M480 Smartcard(SC) driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/* Below are variables used locally by SC driver and does not want to parse by doxygen unless HIDDEN_SYMBOLS is defined */
/** @cond HIDDEN_SYMBOLS */
static uint32_t u32CardStateIgnore[SC_INTERFACE_NUM] = {0UL, 0UL, 0UL};
/** @endcond HIDDEN_SYMBOLS */
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_SC_Driver SC Driver
@{
*/
/** @addtogroup M480_SC_EXPORTED_FUNCTIONS SC Exported Functions
@{
*/
/**
* @brief This function indicates specified smartcard slot status
* @param[in] sc Base address of smartcard module
* @return Card insert status
* @retval TRUE Card insert
* @retval FALSE Card remove
*/
uint32_t SC_IsCardInserted(SC_T *sc)
{
uint32_t ret;
/* put conditions into two variable to remove IAR compilation warning */
uint32_t cond1 = ((sc->STATUS & SC_STATUS_CDPINSTS_Msk) >> SC_STATUS_CDPINSTS_Pos);
uint32_t cond2 = ((sc->CTL & SC_CTL_CDLV_Msk) >> SC_CTL_CDLV_Pos);
if((sc == SC0) && (u32CardStateIgnore[0] == 1UL)) {
ret = (uint32_t)TRUE;
} else if((sc == SC1) && (u32CardStateIgnore[1] == 1UL)) {
ret = (uint32_t)TRUE;
} else if((sc == SC2) && (u32CardStateIgnore[2] == 1UL)) {
ret = (uint32_t)TRUE;
} else if(cond1 != cond2) {
ret = (uint32_t)FALSE;
} else {
ret = (uint32_t)TRUE;
}
return ret;
}
/**
* @brief This function reset both transmit and receive FIFO of specified smartcard module
* @param[in] sc Base address of smartcard module
* @return None
*/
void SC_ClearFIFO(SC_T *sc)
{
while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk) {
;
}
sc->ALTCTL |= (SC_ALTCTL_TXRST_Msk | SC_ALTCTL_RXRST_Msk);
}
/**
* @brief This function disable specified smartcard module
* @param[in] sc Base address of smartcard module
* @return None
*/
void SC_Close(SC_T *sc)
{
sc->INTEN = 0UL;
while(sc->PINCTL & SC_PINCTL_SYNC_Msk) {
;
}
sc->PINCTL = 0UL;
sc->ALTCTL = 0UL;
while(sc->CTL & SC_CTL_SYNC_Msk) {
;
}
sc->CTL = 0UL;
}
/**
* @brief This function initialized smartcard module
* @param[in] sc Base address of smartcard module
* @param[in] u32CD Card detect polarity, select the CD pin state which indicates card insert. Could be
* -\ref SC_PIN_STATE_HIGH
* -\ref SC_PIN_STATE_LOW
* -\ref SC_PIN_STATE_IGNORE, no card detect pin, always assumes card present
* @param[in] u32PWR Power on polarity, select the PWR pin state which could set smartcard VCC to high level. Could be
* -\ref SC_PIN_STATE_HIGH
* -\ref SC_PIN_STATE_LOW
* @return None
*/
void SC_Open(SC_T *sc, uint32_t u32CD, uint32_t u32PWR)
{
uint32_t u32Reg = 0UL, u32Intf;
if(sc == SC0) {
u32Intf = 0UL;
} else if(sc == SC1) {
u32Intf = 1UL;
} else {
u32Intf = 2UL;
}
if(u32CD != SC_PIN_STATE_IGNORE) {
u32Reg = u32CD ? 0UL: SC_CTL_CDLV_Msk;
u32CardStateIgnore[u32Intf] = 0UL;
} else {
u32CardStateIgnore[u32Intf] = 1UL;
}
sc->PINCTL = u32PWR ? 0UL : SC_PINCTL_PWRINV_Msk;
while(sc->CTL & SC_CTL_SYNC_Msk) {
;
}
sc->CTL = SC_CTL_SCEN_Msk | u32Reg;
}
/**
* @brief This function reset specified smartcard module to its default state for activate smartcard
* @param[in] sc Base address of smartcard module
* @return None
*/
void SC_ResetReader(SC_T *sc)
{
uint32_t u32Intf;
if(sc == SC0) {
u32Intf = 0UL;
} else if(sc == SC1) {
u32Intf = 1UL;
} else {
u32Intf = 2UL;
}
/* Reset FIFO, enable auto de-activation while card removal */
sc->ALTCTL |= (SC_ALTCTL_TXRST_Msk | SC_ALTCTL_RXRST_Msk | SC_ALTCTL_ADACEN_Msk);
/* Set Rx trigger level to 1 character, longest card detect debounce period, disable error retry (EMV ATR does not use error retry) */
while(sc->CTL & SC_CTL_SYNC_Msk) {
;
}
sc->CTL &= ~(SC_CTL_RXTRGLV_Msk |
SC_CTL_CDDBSEL_Msk |
SC_CTL_TXRTY_Msk |
SC_CTL_TXRTYEN_Msk |
SC_CTL_RXRTY_Msk |
SC_CTL_RXRTYEN_Msk);
while(sc->CTL & SC_CTL_SYNC_Msk) {
;
}
/* Enable auto convention, and all three smartcard internal timers */
sc->CTL |= SC_CTL_AUTOCEN_Msk | SC_CTL_TMRSEL_Msk;
/* Disable Rx timeout */
sc->RXTOUT = 0UL;
/* 372 clocks per ETU by default */
sc->ETUCTL= 371UL;
/* Enable necessary interrupt for smartcard operation */
if(u32CardStateIgnore[u32Intf]) {/* Do not enable card detect interrupt if card present state ignore */
sc->INTEN = (SC_INTEN_RDAIEN_Msk |
SC_INTEN_TERRIEN_Msk |
SC_INTEN_TMR0IEN_Msk |
SC_INTEN_TMR1IEN_Msk |
SC_INTEN_TMR2IEN_Msk |
SC_INTEN_BGTIEN_Msk |
SC_INTEN_ACERRIEN_Msk);
} else {
sc->INTEN = (SC_INTEN_RDAIEN_Msk |
SC_INTEN_TERRIEN_Msk |
SC_INTEN_TMR0IEN_Msk |
SC_INTEN_TMR1IEN_Msk |
SC_INTEN_TMR2IEN_Msk |
SC_INTEN_BGTIEN_Msk |
SC_INTEN_CDIEN_Msk |
SC_INTEN_ACERRIEN_Msk);
}
return;
}
/**
* @brief This function block guard time (BGT) of specified smartcard module
* @param[in] sc Base address of smartcard module
* @param[in] u32BGT Block guard time using ETU as unit, valid range are between 1 ~ 32
* @return None
*/
void SC_SetBlockGuardTime(SC_T *sc, uint32_t u32BGT)
{
sc->CTL = (sc->CTL & ~SC_CTL_BGT_Msk) | ((u32BGT - 1UL) << SC_CTL_BGT_Pos);
}
/**
* @brief This function character guard time (CGT) of specified smartcard module
* @param[in] sc Base address of smartcard module
* @param[in] u32CGT Character guard time using ETU as unit, valid range are between 11 ~ 267
* @return None
*/
void SC_SetCharGuardTime(SC_T *sc, uint32_t u32CGT)
{
u32CGT -= sc->CTL & SC_CTL_NSB_Msk ? 11UL: 12UL;
sc->EGT = u32CGT;
}
/**
* @brief This function stop all smartcard timer of specified smartcard module
* @param[in] sc Base address of smartcard module
* @return None
* @note This function stop the timers within smartcard module, \b not timer module
*/
void SC_StopAllTimer(SC_T *sc)
{
while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk) {
;
}
sc->ALTCTL &= ~(SC_ALTCTL_CNTEN0_Msk | SC_ALTCTL_CNTEN1_Msk | SC_ALTCTL_CNTEN2_Msk);
}
/**
* @brief This function configure and start a smartcard timer of specified smartcard module
* @param[in] sc Base address of smartcard module
* @param[in] u32TimerNum Timer(s) to start. Valid values are 0, 1, 2.
* @param[in] u32Mode Timer operating mode, valid values are:
* - \ref SC_TMR_MODE_0
* - \ref SC_TMR_MODE_1
* - \ref SC_TMR_MODE_2
* - \ref SC_TMR_MODE_3
* - \ref SC_TMR_MODE_4
* - \ref SC_TMR_MODE_5
* - \ref SC_TMR_MODE_6
* - \ref SC_TMR_MODE_7
* - \ref SC_TMR_MODE_8
* - \ref SC_TMR_MODE_F
* @param[in] u32ETUCount Timer timeout duration, ETU based. For timer 0, valid range are between 1~0x1000000ETUs.
* For timer 1 and timer 2, valid range are between 1 ~ 0x100 ETUs
* @return None
* @note This function start the timer within smartcard module, \b not timer module
* @note Depend on the timer operating mode, timer may not start counting immediately
*/
void SC_StartTimer(SC_T *sc, uint32_t u32TimerNum, uint32_t u32Mode, uint32_t u32ETUCount)
{
uint32_t reg = u32Mode | (SC_TMRCTL0_CNT_Msk & (u32ETUCount - 1UL));
while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk) {
;
}
if(u32TimerNum == 0UL) {
while(sc->TMRCTL0 & SC_TMRCTL0_SYNC_Msk) {
;
}
sc->TMRCTL0 = reg;
sc->ALTCTL |= SC_ALTCTL_CNTEN0_Msk;
} else if(u32TimerNum == 1UL) {
while(sc->TMRCTL1 & SC_TMRCTL1_SYNC_Msk) {
;
}
sc->TMRCTL1 = reg;
sc->ALTCTL |= SC_ALTCTL_CNTEN1_Msk;
} else { /* timer 2 */
while(sc->TMRCTL2 & SC_TMRCTL2_SYNC_Msk) {
;
}
sc->TMRCTL2 = reg;
sc->ALTCTL |= SC_ALTCTL_CNTEN2_Msk;
}
}
/**
* @brief This function stop a smartcard timer of specified smartcard module
* @param[in] sc Base address of smartcard module
* @param[in] u32TimerNum Timer(s) to stop. Valid values are 0, 1, 2.
* @return None
* @note This function stop the timer within smartcard module, \b not timer module
*/
void SC_StopTimer(SC_T *sc, uint32_t u32TimerNum)
{
while(sc->ALTCTL & SC_ALTCTL_SYNC_Msk) {
;
}
if(u32TimerNum == 0UL) {
sc->ALTCTL &= ~SC_ALTCTL_CNTEN0_Msk;
} else if(u32TimerNum == 1UL) {
sc->ALTCTL &= ~SC_ALTCTL_CNTEN1_Msk;
} else { /* timer 2 */
sc->ALTCTL &= ~SC_ALTCTL_CNTEN2_Msk;
}
}
/**
* @brief This function gets smartcard clock frequency.
* @param[in] sc Base address of smartcard module
* @return Smartcard frequency in kHZ
*/
uint32_t SC_GetInterfaceClock(SC_T *sc)
{
uint32_t u32ClkSrc, u32Num, u32Clk;
if(sc == SC0) {
u32Num = 0UL;
} else if(sc == SC1) {
u32Num = 1UL;
} else {
u32Num = 2UL;
}
u32ClkSrc = (CLK->CLKSEL3 >> (2UL * u32Num)) & CLK_CLKSEL3_SC0SEL_Msk;
/* Get smartcard module clock */
if(u32ClkSrc == 0UL) {
u32Clk = __HXT;
} else if(u32ClkSrc == 1UL) {
u32Clk = CLK_GetPLLClockFreq();
} else if(u32ClkSrc == 2UL) {
if(u32Num == 1UL) {
u32Clk = CLK_GetPCLK1Freq();
} else {
u32Clk = CLK_GetPCLK0Freq();
}
} else {
u32Clk = __HIRC;
}
u32Clk /= (((CLK->CLKDIV1 >> (8UL * u32Num)) & CLK_CLKDIV1_SC0DIV_Msk) + 1UL) * 1000UL;
return u32Clk;
}
/*@}*/ /* end of group M480_SC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_SC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,261 @@
/**************************************************************************//**
* @file sc.h
* @version V1.00
* @brief M480 Smartcard (SC) driver header file
*
* @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __SC_H__
#define __SC_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_SC_Driver SC Driver
@{
*/
/** @addtogroup M480_SC_EXPORTED_CONSTANTS SC Exported Constants
@{
*/
#define SC_INTERFACE_NUM 3 /*!< Smartcard interface numbers \hideinitializer */
#define SC_PIN_STATE_HIGH 1 /*!< Smartcard pin status high \hideinitializer */
#define SC_PIN_STATE_LOW 0 /*!< Smartcard pin status low \hideinitializer */
#define SC_PIN_STATE_IGNORE 0xFFFFFFFF /*!< Ignore pin status \hideinitializer */
#define SC_CLK_ON 1 /*!< Smartcard clock on \hideinitializer */
#define SC_CLK_OFF 0 /*!< Smartcard clock off \hideinitializer */
#define SC_TMR_MODE_0 (0ul << SC_TMRCTL0_OPMODE_Pos) /*!<Timer Operation Mode 0, down count \hideinitializer */
#define SC_TMR_MODE_1 (1ul << SC_TMRCTL0_OPMODE_Pos) /*!<Timer Operation Mode 1, down count, start after detect start bit \hideinitializer */
#define SC_TMR_MODE_2 (2ul << SC_TMRCTL0_OPMODE_Pos) /*!<Timer Operation Mode 2, down count, start after receive start bit \hideinitializer */
#define SC_TMR_MODE_3 (3ul << SC_TMRCTL0_OPMODE_Pos) /*!<Timer Operation Mode 3, down count, use for activation, only timer 0 support this mode \hideinitializer */
#define SC_TMR_MODE_4 (4ul << SC_TMRCTL0_OPMODE_Pos) /*!<Timer Operation Mode 4, down count with reload after timeout \hideinitializer */
#define SC_TMR_MODE_5 (5ul << SC_TMRCTL0_OPMODE_Pos) /*!<Timer Operation Mode 5, down count, start after detect start bit, reload after timeout \hideinitializer */
#define SC_TMR_MODE_6 (6ul << SC_TMRCTL0_OPMODE_Pos) /*!<Timer Operation Mode 6, down count, start after receive start bit, reload after timeout \hideinitializer */
#define SC_TMR_MODE_7 (7ul << SC_TMRCTL0_OPMODE_Pos) /*!<Timer Operation Mode 7, down count, start and reload after detect start bit \hideinitializer */
#define SC_TMR_MODE_8 (8ul << SC_TMRCTL0_OPMODE_Pos) /*!<Timer Operation Mode 8, up count \hideinitializer */
#define SC_TMR_MODE_F (0xF << SC_TMRCTL0_OPMODE_Pos) /*!<Timer Operation Mode 15, down count, reload after detect start bit \hideinitializer */
/*@}*/ /* end of group M480_SC_EXPORTED_CONSTANTS */
/** @addtogroup M480_SC_EXPORTED_FUNCTIONS SC Exported Functions
@{
*/
/**
* @brief This macro enable smartcard interrupt
* @param[in] sc Base address of smartcard module
* @param[in] u32Mask Interrupt mask to be enabled. A combination of
* - \ref SC_INTEN_ACERRIEN_Msk
* - \ref SC_INTEN_RXTOIEN_Msk
* - \ref SC_INTEN_INITIEN_Msk
* - \ref SC_INTEN_CDIEN_Msk
* - \ref SC_INTEN_BGTIEN_Msk
* - \ref SC_INTEN_TMR2IEN_Msk
* - \ref SC_INTEN_TMR1IEN_Msk
* - \ref SC_INTEN_TMR0IEN_Msk
* - \ref SC_INTEN_TERRIEN_Msk
* - \ref SC_INTEN_TBEIEN_Msk
* - \ref SC_INTEN_RDAIEN_Msk
* @return None
* \hideinitializer
*/
#define SC_ENABLE_INT(sc, u32Mask) ((sc)->INTEN |= (u32Mask))
/**
* @brief This macro disable smartcard interrupt
* @param[in] sc Base address of smartcard module
* @param[in] u32Mask Interrupt mask to be disabled. A combination of
* - \ref SC_INTEN_ACERRIEN_Msk
* - \ref SC_INTEN_RXTOIEN_Msk
* - \ref SC_INTEN_INITIEN_Msk
* - \ref SC_INTEN_CDIEN_Msk
* - \ref SC_INTEN_BGTIEN_Msk
* - \ref SC_INTEN_TMR2IEN_Msk
* - \ref SC_INTEN_TMR1IEN_Msk
* - \ref SC_INTEN_TMR0IEN_Msk
* - \ref SC_INTEN_TERRIEN_Msk
* - \ref SC_INTEN_TBEIEN_Msk
* - \ref SC_INTEN_RDAIEN_Msk
* @return None
* \hideinitializer
*/
#define SC_DISABLE_INT(sc, u32Mask) ((sc)->INTEN &= ~(u32Mask))
/**
* @brief This macro set VCC pin state of smartcard interface
* @param[in] sc Base address of smartcard module
* @param[in] u32State Pin state of VCC pin, valid parameters are \ref SC_PIN_STATE_HIGH and \ref SC_PIN_STATE_LOW
* @return None
* \hideinitializer
*/
#define SC_SET_VCC_PIN(sc, u32State) \
do {\
while((sc)->PINCTL & SC_PINCTL_SYNC_Msk);\
if(u32State)\
(sc)->PINCTL |= SC_PINCTL_PWREN_Msk;\
else\
(sc)->PINCTL &= ~SC_PINCTL_PWREN_Msk;\
}while(0)
/**
* @brief This macro turns CLK output on or off
* @param[in] sc Base address of smartcard module
* @param[in] u32OnOff Clock on or off for selected smartcard module, valid values are \ref SC_CLK_ON and \ref SC_CLK_OFF
* @return None
* \hideinitializer
*/
#define SC_SET_CLK_PIN(sc, u32OnOff)\
do {\
while((sc)->PINCTL & SC_PINCTL_SYNC_Msk);\
if(u32OnOff)\
(sc)->PINCTL |= SC_PINCTL_CLKKEEP_Msk;\
else\
(sc)->PINCTL &= ~(SC_PINCTL_CLKKEEP_Msk);\
}while(0)
/**
* @brief This macro set I/O pin state of smartcard interface
* @param[in] sc Base address of smartcard module
* @param[in] u32State Pin state of I/O pin, valid parameters are \ref SC_PIN_STATE_HIGH and \ref SC_PIN_STATE_LOW
* @return None
* \hideinitializer
*/
#define SC_SET_IO_PIN(sc, u32State)\
do {\
while((sc)->PINCTL & SC_PINCTL_SYNC_Msk);\
if(u32State)\
(sc)->PINCTL |= SC_PINCTL_SCDATA_Msk;\
else\
(sc)->PINCTL &= ~SC_PINCTL_SCDATA_Msk;\
}while(0)
/**
* @brief This macro set RST pin state of smartcard interface
* @param[in] sc Base address of smartcard module
* @param[in] u32State Pin state of RST pin, valid parameters are \ref SC_PIN_STATE_HIGH and \ref SC_PIN_STATE_LOW
* @return None
* \hideinitializer
*/
#define SC_SET_RST_PIN(sc, u32State)\
do {\
while((sc)->PINCTL & SC_PINCTL_SYNC_Msk);\
if(u32State)\
(sc)->PINCTL |= SC_PINCTL_RSTEN_Msk;\
else\
(sc)->PINCTL &= ~SC_PINCTL_RSTEN_Msk;\
}while(0)
/**
* @brief This macro read one byte from smartcard module receive FIFO
* @param[in] sc Base address of smartcard module
* @return One byte read from receive FIFO
* \hideinitializer
*/
#define SC_READ(sc) ((char)((sc)->DAT))
/**
* @brief This macro write one byte to smartcard module transmit FIFO
* @param[in] sc Base address of smartcard module
* @param[in] u8Data Data to write to transmit FIFO
* @return None
* \hideinitializer
*/
#define SC_WRITE(sc, u8Data) ((sc)->DAT = (u8Data))
/**
* @brief This macro set smartcard stop bit length
* @param[in] sc Base address of smartcard module
* @param[in] u32Len Stop bit length, ether 1 or 2.
* @return None
* @details Stop bit length must be 1 for T = 1 protocol and 2 for T = 0 protocol.
* \hideinitializer
*/
#define SC_SET_STOP_BIT_LEN(sc, u32Len) ((sc)->CTL = ((sc)->CTL & ~SC_CTL_NSB_Msk) | ((u32Len) == 1 ? SC_CTL_NSB_Msk : 0))
/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */
__STATIC_INLINE void SC_SetTxRetry(SC_T *sc, uint32_t u32Count);
__STATIC_INLINE void SC_SetRxRetry(SC_T *sc, uint32_t u32Count);
/**
* @brief Enable/Disable Tx error retry, and set Tx error retry count
* @param[in] sc Base address of smartcard module
* @param[in] u32Count The number of times of Tx error retry count, between 0~8. 0 means disable Tx error retry
* @return None
*/
__STATIC_INLINE void SC_SetTxRetry(SC_T *sc, uint32_t u32Count)
{
while((sc)->CTL & SC_CTL_SYNC_Msk) {
;
}
/* Retry count must set while enable bit disabled, so disable it first */
(sc)->CTL &= ~(SC_CTL_TXRTY_Msk | SC_CTL_TXRTYEN_Msk);
if((u32Count) != 0UL) {
while((sc)->CTL & SC_CTL_SYNC_Msk) {
;
}
(sc)->CTL |= (((u32Count) - 1UL) << SC_CTL_TXRTY_Pos) | SC_CTL_TXRTYEN_Msk;
}
}
/**
* @brief Enable/Disable Rx error retry, and set Rx error retry count
* @param[in] sc Base address of smartcard module
* @param[in] u32Count The number of times of Rx error retry count, between 0~8. 0 means disable Rx error retry
* @return None
*/
__STATIC_INLINE void SC_SetRxRetry(SC_T *sc, uint32_t u32Count)
{
while((sc)->CTL & SC_CTL_SYNC_Msk) {
;
}
/* Retry count must set while enable bit disabled, so disable it first */
(sc)->CTL &= ~(SC_CTL_RXRTY_Msk | SC_CTL_RXRTYEN_Msk);
if((u32Count) != 0UL) {
while((sc)->CTL & SC_CTL_SYNC_Msk) {
;
}
(sc)->CTL |= (((u32Count) - 1UL) << SC_CTL_RXRTY_Pos) | SC_CTL_RXRTYEN_Msk;
}
}
uint32_t SC_IsCardInserted(SC_T *sc);
void SC_ClearFIFO(SC_T *sc);
void SC_Close(SC_T *sc);
void SC_Open(SC_T *sc, uint32_t u32CD, uint32_t u32PWR);
void SC_ResetReader(SC_T *sc);
void SC_SetBlockGuardTime(SC_T *sc, uint32_t u32BGT);
void SC_SetCharGuardTime(SC_T *sc, uint32_t u32CGT);
void SC_StopAllTimer(SC_T *sc);
void SC_StartTimer(SC_T *sc, uint32_t u32TimerNum, uint32_t u32Mode, uint32_t u32ETUCount);
void SC_StopTimer(SC_T *sc, uint32_t u32TimerNum);
uint32_t SC_GetInterfaceClock(SC_T *sc);
/*@}*/ /* end of group M480_SC_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_SC_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __SC_H__ */
/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,218 @@
/**************************************************************************//**
* @file scuart.c
* @brief M480 Smartcard UART mode (SCUART) driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
static uint32_t SCUART_GetClock(SC_T *sc);
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_SCUART_Driver SCUART Driver
@{
*/
/** @addtogroup M480_SCUART_EXPORTED_FUNCTIONS SCUART Exported Functions
@{
*/
/**
* @brief The function is used to disable smartcard interface UART mode.
* @param sc The base address of smartcard module.
* @return None
*/
void SCUART_Close(SC_T* sc)
{
sc->INTEN = 0UL;
sc->UARTCTL = 0UL;
sc->CTL = 0UL;
}
/** @cond HIDDEN_SYMBOLS */
/**
* @brief This function returns module clock of specified SC interface
* @param[in] sc The base address of smartcard module.
* @return Module clock of specified SC interface
*/
static uint32_t SCUART_GetClock(SC_T *sc)
{
uint32_t u32ClkSrc, u32Num, u32Clk;
if(sc == SC0) {
u32Num = 0UL;
} else if(sc == SC1) {
u32Num = 1UL;
} else {
u32Num = 2UL;
}
u32ClkSrc = (CLK->CLKSEL3 >> (2UL * u32Num)) & CLK_CLKSEL3_SC0SEL_Msk;
/* Get smartcard module clock */
if(u32ClkSrc == 0UL) {
u32Clk = __HXT;
} else if(u32ClkSrc == 1UL) {
u32Clk = CLK_GetPLLClockFreq();
} else if(u32ClkSrc == 2UL) {
if(u32Num == 1UL) {
u32Clk = CLK_GetPCLK1Freq();
} else {
u32Clk = CLK_GetPCLK0Freq();
}
} else {
u32Clk = __HIRC;
}
u32Clk /= (((CLK->CLKDIV1 >> (8UL * u32Num)) & CLK_CLKDIV1_SC0DIV_Msk) + 1UL);
return u32Clk;
}
/** @endcond HIDDEN_SYMBOLS */
/**
* @brief This function use to enable smartcard module UART mode and set baudrate.
* @param[in] sc The base address of smartcard module.
* @param[in] u32baudrate Target baudrate of smartcard module.
* @return Actual baudrate of smartcard mode
* @details This function configures character width to 8 bits, 1 stop bit, and no parity.
* And can use \ref SCUART_SetLineConfig function to update these settings
* The baudrate clock source comes from SC_CLK/SC_DIV, where SC_CLK is controlled
* by SCxSEL in CLKSEL3 register, SC_DIV is controlled by SCxDIV in CLKDIV1
* register. Since the baudrate divider is 12-bit wide and must be larger than 4,
* (clock source / baudrate) must be larger or equal to 5 and smaller or equal to
* 4096. Otherwise this function cannot configure SCUART to work with target baudrate.
*/
uint32_t SCUART_Open(SC_T* sc, uint32_t u32baudrate)
{
uint32_t u32Clk = SCUART_GetClock(sc), u32Div;
/* Calculate divider for target baudrate */
u32Div = (u32Clk + (u32baudrate >> 1) - 1UL) / u32baudrate - 1UL;
/* Enable smartcard interface and stop bit = 1 */
sc->CTL = SC_CTL_SCEN_Msk | SC_CTL_NSB_Msk;
/* Enable UART mode, disable parity and 8 bit per character */
sc->UARTCTL = SCUART_CHAR_LEN_8 | SCUART_PARITY_NONE | SC_UARTCTL_UARTEN_Msk;
sc->ETUCTL = u32Div;
return(u32Clk / (u32Div + 1UL));
}
/**
* @brief The function is used to read Rx data from RX FIFO.
* @param[in] sc The base address of smartcard module.
* @param[in] pu8RxBuf The buffer to store receive the data
* @param[in] u32ReadBytes Target number of characters to receive
* @return Actual character number reads to buffer
* @note This function does not block and return immediately if there's no data available
*/
uint32_t SCUART_Read(SC_T* sc, uint8_t pu8RxBuf[], uint32_t u32ReadBytes)
{
uint32_t u32Count;
for(u32Count = 0UL; u32Count < u32ReadBytes; u32Count++) {
if(SCUART_GET_RX_EMPTY(sc)) { /* no data available */
break;
}
pu8RxBuf[u32Count] = (uint8_t)SCUART_READ(sc); /* get data from FIFO */
}
return u32Count;
}
/**
* @brief This function use to configure smartcard UART mode line setting.
* @param[in] sc The base address of smartcard module.
* @param[in] u32Baudrate Target baudrate of smartcard module. If this value is 0, UART baudrate will not change.
* @param[in] u32DataWidth The data length, could be
* - \ref SCUART_CHAR_LEN_5
* - \ref SCUART_CHAR_LEN_6
* - \ref SCUART_CHAR_LEN_7
* - \ref SCUART_CHAR_LEN_8
* @param[in] u32Parity The parity setting, could be
* - \ref SCUART_PARITY_NONE
* - \ref SCUART_PARITY_ODD
* - \ref SCUART_PARITY_EVEN
* @param[in] u32StopBits The stop bit length, could be
* - \ref SCUART_STOP_BIT_1
* - \ref SCUART_STOP_BIT_2
* @return Actual baudrate of smartcard
* @details The baudrate clock source comes from SC_CLK/SC_DIV, where SC_CLK is controlled
* by SCxSEL in CLKSEL3 register, SC_DIV is controlled by SCxDIV in CLKDIV1
* register. Since the baudrate divider is 12-bit wide and must be larger than 4,
* (clock source / baudrate) must be larger or equal to 5 and smaller or equal to
* 4096. Otherwise this function cannot configure SCUART to work with target baudrate.
*/
uint32_t SCUART_SetLineConfig(SC_T* sc, uint32_t u32Baudrate, uint32_t u32DataWidth, uint32_t u32Parity, uint32_t u32StopBits)
{
uint32_t u32Clk = SCUART_GetClock(sc), u32Div;
if(u32Baudrate == 0UL) { /* keep original baudrate setting */
u32Div = sc->ETUCTL & SC_ETUCTL_ETURDIV_Msk;
} else {
/* Calculate divider for target baudrate */
u32Div = (u32Clk + (u32Baudrate >> 1) - 1UL)/ u32Baudrate - 1UL;
sc->ETUCTL = u32Div;
}
/* Set stop bit */
sc->CTL = u32StopBits | SC_CTL_SCEN_Msk;
/* Set character width and parity */
sc->UARTCTL = u32Parity | u32DataWidth | SC_UARTCTL_UARTEN_Msk;
return(u32Clk / (u32Div + 1UL));
}
/**
* @brief This function use to set receive timeout count.
* @param[in] sc The base address of smartcard module.
* @param[in] u32TOC Rx timeout counter, using baudrate as counter unit. Valid range are 0~0x1FF,
* set this value to 0 will disable timeout counter
* @return None
* @details The time-out counter resets and starts counting whenever the RX buffer received a
* new data word. Once the counter decrease to 1 and no new data is received or CPU
* does not read any data from FIFO, a receiver time-out interrupt will be generated.
*/
void SCUART_SetTimeoutCnt(SC_T* sc, uint32_t u32TOC)
{
sc->RXTOUT= u32TOC;
}
/**
* @brief This function is to write data into transmit FIFO to send data out.
* @param[in] sc The base address of smartcard module.
* @param[in] pu8TxBuf The buffer containing data to send to transmit FIFO.
* @param[in] u32WriteBytes Number of data to send.
* @return None
* @note This function blocks until all data write into FIFO
*/
void SCUART_Write(SC_T* sc,uint8_t pu8TxBuf[], uint32_t u32WriteBytes)
{
uint32_t u32Count;
for(u32Count = 0UL; u32Count != u32WriteBytes; u32Count++) {
/* Wait 'til FIFO not full */
while(SCUART_GET_TX_FULL(sc)) {
;
}
/* Write 1 byte to FIFO */
sc->DAT = pu8TxBuf[u32Count];
}
}
/*@}*/ /* end of group M480_SCUART_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_SCUART_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,266 @@
/**************************************************************************//**
* @file scuart.h
* @version V1.00
* @brief M480 Smartcard UART mode (SCUART) driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __SCUART_H__
#define __SCUART_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_SCUART_Driver SCUART Driver
@{
*/
/** @addtogroup M480_SCUART_EXPORTED_CONSTANTS SCUART Exported Constants
@{
*/
#define SCUART_CHAR_LEN_5 (0x3ul << SC_UARTCTL_WLS_Pos) /*!< Set SCUART word length to 5 bits \hideinitializer */
#define SCUART_CHAR_LEN_6 (0x2ul << SC_UARTCTL_WLS_Pos) /*!< Set SCUART word length to 6 bits \hideinitializer */
#define SCUART_CHAR_LEN_7 (0x1ul << SC_UARTCTL_WLS_Pos) /*!< Set SCUART word length to 7 bits \hideinitializer */
#define SCUART_CHAR_LEN_8 (0UL) /*!< Set SCUART word length to 8 bits \hideinitializer */
#define SCUART_PARITY_NONE (SC_UARTCTL_PBOFF_Msk) /*!< Set SCUART transfer with no parity \hideinitializer */
#define SCUART_PARITY_ODD (SC_UARTCTL_OPE_Msk) /*!< Set SCUART transfer with odd parity \hideinitializer */
#define SCUART_PARITY_EVEN (0UL) /*!< Set SCUART transfer with even parity \hideinitializer */
#define SCUART_STOP_BIT_1 (SC_CTL_NSB_Msk) /*!< Set SCUART transfer with one stop bit \hideinitializer */
#define SCUART_STOP_BIT_2 (0UL) /*!< Set SCUART transfer with two stop bits \hideinitializer */
/*@}*/ /* end of group M480_SCUART_EXPORTED_CONSTANTS */
/** @addtogroup M480_SCUART_EXPORTED_FUNCTIONS SCUART Exported Functions
@{
*/
/* TX Macros */
/**
* @brief Write Data to Tx data register
* @param[in] sc The base address of smartcard module.
* @param[in] u8Data Data byte to transmit
* @return None
* \hideinitializer
*/
#define SCUART_WRITE(sc, u8Data) ((sc)->DAT = (u8Data))
/**
* @brief Get TX FIFO empty flag status from register
* @param[in] sc The base address of smartcard module
* @return Transmit FIFO empty status
* @retval 0 Transmit FIFO is not empty
* @retval SC_STATUS_TXEMPTY_Msk Transmit FIFO is empty
* \hideinitializer
*/
#define SCUART_GET_TX_EMPTY(sc) ((sc)->STATUS & SC_STATUS_TXEMPTY_Msk)
/**
* @brief Get TX FIFO full flag status from register
* @param[in] sc The base address of smartcard module
* @return Transmit FIFO full status
* @retval 0 Transmit FIFO is not full
* @retval SC_STATUS_TXFULL_Msk Transmit FIFO is full
* \hideinitializer
*/
#define SCUART_GET_TX_FULL(sc) ((sc)->STATUS & SC_STATUS_TXFULL_Msk)
/**
* @brief Wait specified smartcard port transmission complete
* @param[in] sc The base address of smartcard module
* @return None
* @note This Macro blocks until transmit complete.
* \hideinitializer
*/
#define SCUART_WAIT_TX_EMPTY(sc) while((sc)->STATUS & SC_STATUS_TXACT_Msk)
/**
* @brief Check specified smartcard port transmit FIFO is full or not
* @param[in] sc The base address of smartcard module
* @return Transmit FIFO full status
* @retval 0 Transmit FIFO is not full
* @retval 1 Transmit FIFO is full
* \hideinitializer
*/
#define SCUART_IS_TX_FULL(sc) ((sc)->STATUS & SC_STATUS_TXFULL_Msk ? 1 : 0)
/**
* @brief Check specified smartcard port transmission is over
* @param[in] sc The base address of smartcard module
* @return Transmit complete status
* @retval 0 Transmit is not complete
* @retval 1 Transmit complete
* \hideinitializer
*/
#define SCUART_IS_TX_EMPTY(sc) ((sc)->STATUS & SC_STATUS_TXACT_Msk ? 0 : 1)
/**
* @brief Check specified Smartcard port Transmission Status
* @param[in] sc The pointer of smartcard module.
* @retval 0 Transmit is completed
* @retval 1 Transmit is active
* @details TXACT (SC_STATUS[31]) is set by hardware when Tx transfer is in active and the STOP bit of the last byte has been transmitted.
* \hideinitializer
*/
#define SCUART_IS_TX_ACTIVE(sc) (((sc)->STATUS & SC_STATUS_TXACT_Msk)? 1 : 0)
/* RX Macros */
/**
* @brief Read Rx data register
* @param[in] sc The base address of smartcard module
* @return The oldest data byte in RX FIFO
* \hideinitializer
*/
#define SCUART_READ(sc) ((sc)->DAT)
/**
* @brief Get RX FIFO empty flag status from register
* @param[in] sc The base address of smartcard module
* @return Receive FIFO empty status
* @retval 0 Receive FIFO is not empty
* @retval SC_STATUS_RXEMPTY_Msk Receive FIFO is empty
* \hideinitializer
*/
#define SCUART_GET_RX_EMPTY(sc) ((sc)->STATUS & SC_STATUS_RXEMPTY_Msk)
/**
* @brief Get RX FIFO full flag status from register
* @param[in] sc The base address of smartcard module
* @return Receive FIFO full status
* @retval 0 Receive FIFO is not full
* @retval SC_STATUS_RXFULLF_Msk Receive FIFO is full
* \hideinitializer
*/
#define SCUART_GET_RX_FULL(sc) ((sc)->STATUS & SC_STATUS_RXFULL_Msk)
/**
* @brief Check if receive data number in FIFO reach FIFO trigger level or not
* @param[in] sc The base address of smartcard module
* @return Receive FIFO data status
* @retval 0 The number of bytes in receive FIFO is less than trigger level
* @retval 1 The number of bytes in receive FIFO equals or larger than trigger level
* @note If receive trigger level is \b not 1 byte, this macro return 0 does not necessary indicates there is \b no data in FIFO
* \hideinitializer
*/
#define SCUART_IS_RX_READY(sc) ((sc)->INTSTS & SC_INTSTS_RDAIF_Msk ? 1 : 0)
/**
* @brief Check specified smartcard port receive FIFO is full or not
* @param[in] sc The base address of smartcard module
* @return Receive FIFO full status
* @retval 0 Receive FIFO is not full
* @retval 1 Receive FIFO is full
* \hideinitializer
*/
#define SCUART_IS_RX_FULL(sc) ((sc)->STATUS & SC_STATUS_RXFULL_Msk ? 1 : 0)
/* Interrupt Macros */
/**
* @brief Enable specified interrupts
* @param[in] sc The base address of smartcard module
* @param[in] u32Mask Interrupt masks to enable, a combination of following bits
* - \ref SC_INTEN_RXTOIEN_Msk
* - \ref SC_INTEN_TERRIEN_Msk
* - \ref SC_INTEN_TBEIEN_Msk
* - \ref SC_INTEN_RDAIEN_Msk
* @return None
* \hideinitializer
*/
#define SCUART_ENABLE_INT(sc, u32Mask) ((sc)->INTEN |= (u32Mask))
/**
* @brief Disable specified interrupts
* @param[in] sc The base address of smartcard module
* @param[in] u32Mask Interrupt masks to disable, a combination of following bits
* - \ref SC_INTEN_RXTOIEN_Msk
* - \ref SC_INTEN_TERRIEN_Msk
* - \ref SC_INTEN_TBEIEN_Msk
* - \ref SC_INTEN_RDAIEN_Msk
* @return None
* \hideinitializer
*/
#define SCUART_DISABLE_INT(sc, u32Mask) ((sc)->INTEN &= ~(u32Mask))
/**
* @brief Get specified interrupt flag/status
* @param[in] sc The base address of smartcard module
* @param[in] u32Type Interrupt flag/status to check, could be one of following value
* - \ref SC_INTSTS_RXTOIF_Msk
* - \ref SC_INTSTS_TERRIF_Msk
* - \ref SC_INTSTS_TBEIF_Msk
* - \ref SC_INTSTS_RDAIF_Msk
* @return The status of specified interrupt
* @retval 0 Specified interrupt does not happened
* @retval 1 Specified interrupt happened
* \hideinitializer
*/
#define SCUART_GET_INT_FLAG(sc, u32Type) ((sc)->INTSTS & (u32Type) ? 1 : 0)
/**
* @brief Clear specified interrupt flag/status
* @param[in] sc The base address of smartcard module
* @param[in] u32Type Interrupt flag/status to clear, could be the combination of following values
* - \ref SC_INTSTS_RXTOIF_Msk
* - \ref SC_INTSTS_TERRIF_Msk
* - \ref SC_INTSTS_TBEIF_Msk
* @return None
* \hideinitializer
*/
#define SCUART_CLR_INT_FLAG(sc, u32Type) ((sc)->INTSTS = (u32Type))
/**
* @brief Get receive error flag/status
* @param[in] sc The base address of smartcard module
* @return Current receive error status, could one of following errors:
* @retval SC_STATUS_PEF_Msk Parity error
* @retval SC_STATUS_FEF_Msk Frame error
* @retval SC_STATUS_BEF_Msk Break error
* \hideinitializer
*/
#define SCUART_GET_ERR_FLAG(sc) ((sc)->STATUS & (SC_STATUS_PEF_Msk | SC_STATUS_FEF_Msk | SC_STATUS_BEF_Msk))
/**
* @brief Clear specified receive error flag/status
* @param[in] sc The base address of smartcard module
* @param[in] u32Mask Receive error flag/status to clear, combination following values
* - \ref SC_STATUS_PEF_Msk
* - \ref SC_STATUS_FEF_Msk
* - \ref SC_STATUS_BEF_Msk
* @return None
* \hideinitializer
*/
#define SCUART_CLR_ERR_FLAG(sc, u32Mask) ((sc)->STATUS = (u32Mask))
void SCUART_Close(SC_T* sc);
uint32_t SCUART_Open(SC_T* sc, uint32_t u32baudrate);
uint32_t SCUART_Read(SC_T* sc, uint8_t pu8RxBuf[], uint32_t u32ReadBytes);
uint32_t SCUART_SetLineConfig(SC_T* sc, uint32_t u32Baudrate, uint32_t u32DataWidth, uint32_t u32Parity, uint32_t u32StopBits);
void SCUART_SetTimeoutCnt(SC_T* sc, uint32_t u32TOC);
void SCUART_Write(SC_T* sc,uint8_t pu8TxBuf[], uint32_t u32WriteBytes);
/*@}*/ /* end of group M480_SCUART_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_SCUART_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __SCUART_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,197 @@
/**************************************************************************//**
* @file sdh.h
* @version V1.00
* @brief M480 SDH driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#ifndef __SDH_H__
#define __SDH_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_SDH_Driver SDH Driver
@{
*/
/** @addtogroup M480_SDH_EXPORTED_CONSTANTS SDH Exported Constants
@{
*/
#define SDH_ERR_ID 0xFFFF0100ul /*!< SDH error ID \hideinitializer */
#define SDH_TIMEOUT (SDH_ERR_ID|0x01ul) /*!< Timeout \hideinitializer */
#define SDH_NO_MEMORY (SDH_ERR_ID|0x02ul) /*!< OOM \hideinitializer */
/*-- function return value */
#define Successful 0ul /*!< Success \hideinitializer */
#define Fail 1ul /*!< Failed \hideinitializer */
/*--- define type of SD card or MMC */
#define SDH_TYPE_UNKNOWN 0ul /*!< Unknown card type \hideinitializer */
#define SDH_TYPE_SD_HIGH 1ul /*!< SD card \hideinitializer */
#define SDH_TYPE_SD_LOW 2ul /*!< SDHC card \hideinitializer */
#define SDH_TYPE_MMC 3ul /*!< MMC card \hideinitializer */
#define SDH_TYPE_EMMC 4ul /*!< eMMC card \hideinitializer */
/* SD error */
#define SDH_NO_SD_CARD (SDH_ERR_ID|0x10ul) /*!< Card removed \hideinitializer */
#define SDH_ERR_DEVICE (SDH_ERR_ID|0x11ul) /*!< Device error \hideinitializer */
#define SDH_INIT_TIMEOUT (SDH_ERR_ID|0x12ul) /*!< Card init timeout \hideinitializer */
#define SDH_SELECT_ERROR (SDH_ERR_ID|0x13ul) /*!< Card select error \hideinitializer */
#define SDH_WRITE_PROTECT (SDH_ERR_ID|0x14ul) /*!< Card write protect \hideinitializer */
#define SDH_INIT_ERROR (SDH_ERR_ID|0x15ul) /*!< Card init error \hideinitializer */
#define SDH_CRC7_ERROR (SDH_ERR_ID|0x16ul) /*!< CRC 7 error \hideinitializer */
#define SDH_CRC16_ERROR (SDH_ERR_ID|0x17ul) /*!< CRC 16 error \hideinitializer */
#define SDH_CRC_ERROR (SDH_ERR_ID|0x18ul) /*!< CRC error \hideinitializer */
#define SDH_CMD8_ERROR (SDH_ERR_ID|0x19ul) /*!< Command 8 error \hideinitializer */
#define MMC_FREQ 20000ul /*!< output 20MHz to MMC \hideinitializer */
#define SD_FREQ 25000ul /*!< output 25MHz to SD \hideinitializer */
#define SDHC_FREQ 50000ul /*!< output 50MHz to SDH \hideinitializer */
#define SD_PORT0 (1 << 0) /*!< Card select SD0 \hideinitializer */
#define SD_PORT1 (1 << 2) /*!< Card select SD1 \hideinitializer */
#define CardDetect_From_GPIO (1ul << 8) /*!< Card detection pin is GPIO \hideinitializer */
#define CardDetect_From_DAT3 (1ul << 9) /*!< Card detection pin is DAT3 \hideinitializer */
/*@}*/ /* end of group M480_SDH_EXPORTED_CONSTANTS */
/** @addtogroup M480_SDH_EXPORTED_TYPEDEF SDH Exported Type Defines
@{
*/
typedef struct SDH_info_t {
unsigned int CardType; /*!< SDHC, SD, or MMC */
unsigned int RCA; /*!< Relative card address */
unsigned char IsCardInsert; /*!< Card insert state */
unsigned int totalSectorN; /*!< Total sector number */
unsigned int diskSize; /*!< Disk size in K bytes */
int sectorSize; /*!< Sector size in bytes */
} SDH_INFO_T; /*!< Structure holds SD card info */
/*@}*/ /* end of group M480_SDH_EXPORTED_TYPEDEF */
/** @cond HIDDEN_SYMBOLS */
extern SDH_INFO_T SD0, SD1;
/** @endcond HIDDEN_SYMBOLS */
/** @addtogroup M480_SDH_EXPORTED_FUNCTIONS SDH Exported Functions
@{
*/
/**
* @brief Enable specified interrupt.
*
* @param[in] sdh Select SDH0 or SDH1.
* @param[in] u32IntMask Interrupt type mask:
* \ref SDH_INTEN_BLKDIEN_Msk / \ref SDH_INTEN_CRCIEN_Msk / \ref SDH_INTEN_CDIEN_Msk /
* \ref SDH_INTEN_CDSRC_Msk \ref SDH_INTEN_RTOIEN_Msk / \ref SDH_INTEN_DITOIEN_Msk /
* \ref SDH_INTEN_WKIEN_Msk
*
* @return None.
* \hideinitializer
*/
#define SDH_ENABLE_INT(sdh, u32IntMask) ((sdh)->INTEN |= (u32IntMask))
/**
* @brief Disable specified interrupt.
*
* @param[in] sdh Select SDH0 or SDH1.
* @param[in] u32IntMask Interrupt type mask:
* \ref SDH_INTEN_BLKDIEN_Msk / \ref SDH_INTEN_CRCIEN_Msk / \ref SDH_INTEN_CDIEN_Msk /
* \ref SDH_INTEN_RTOIEN_Msk / \ref SDH_INTEN_DITOIEN_Msk / \ref SDH_INTEN_WKIEN_Msk / \ref SDH_INTEN_CDSRC_Msk /
*
* @return None.
* \hideinitializer
*/
#define SDH_DISABLE_INT(sdh, u32IntMask) ((sdh)->INTEN &= ~(u32IntMask))
/**
* @brief Get specified interrupt flag/status.
*
* @param[in] sdh Select SDH0 or SDH1.
* @param[in] u32IntMask Interrupt type mask:
* \ref SDH_INTSTS_BLKDIF_Msk / \ref SDH_INTSTS_CRCIF_Msk / \ref SDH_INTSTS_CRC7_Msk /
* \ref SDH_INTSTS_CRC16_Msk / \ref SDH_INTSTS_CRCSTS_Msk / \ref SDH_INTSTS_DAT0STS_Msk /
* \ref SDH_INTSTS_CDIF_Msk \ref SDH_INTSTS_RTOIF_Msk /
* \ref SDH_INTSTS_DITOIF_Msk / \ref SDH_INTSTS_CDSTS_Msk /
* \ref SDH_INTSTS_DAT1STS_Msk
*
*
* @return 0 = The specified interrupt is not happened.
* 1 = The specified interrupt is happened.
* \hideinitializer
*/
#define SDH_GET_INT_FLAG(sdh, u32IntMask) (((sdh)->INTSTS & (u32IntMask))?1:0)
/**
* @brief Clear specified interrupt flag/status.
*
* @param[in] sdh Select SDH0 or SDH1.
* @param[in] u32IntMask Interrupt type mask:
* \ref SDH_INTSTS_BLKDIF_Msk / \ref SDH_INTSTS_CRCIF_Msk / \ref SDH_INTSTS_CDIF_Msk /
* \ref SDH_INTSTS_RTOIF_Msk / \ref SDH_INTSTS_DITOIF_Msk
*
*
* @return None.
* \hideinitializer
*/
#define SDH_CLR_INT_FLAG(sdh, u32IntMask) ((sdh)->INTSTS = (u32IntMask))
/**
* @brief Check SD Card inserted or removed.
*
* @param[in] sdh Select SDH0 or SDH1.
*
* @return 1: Card inserted.
* 0: Card removed.
* \hideinitializer
*/
#define SDH_IS_CARD_PRESENT(sdh) (((sdh) == SDH0)? SD0.IsCardInsert : SD1.IsCardInsert)
/**
* @brief Get SD Card capacity.
*
* @param[in] sdh Select SDH0 or SDH1.
*
* @return SD Card capacity. (unit: KByte)
* \hideinitializer
*/
#define SDH_GET_CARD_CAPACITY(sdh) (((sdh) == SDH0)? SD0.diskSize : SD1.diskSize)
void SDH_Open(SDH_T *sdh, uint32_t u32CardDetSrc);
uint32_t SDH_Probe(SDH_T *sdh);
uint32_t SDH_Read(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount);
uint32_t SDH_Write(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount);
uint32_t SDH_CardDetection(SDH_T *sdh);
void SDH_Open_Disk(SDH_T *sdh, unsigned int u32CardDetSrc);
void SDH_Close_Disk(SDH_T *sdh);
/*@}*/ /* end of group M480_SDH_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_SDH_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __SDH_H__ */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,636 @@
/**************************************************************************//**
* @file spi.h
* @version V3.00
* @brief M480 series SPI driver header file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __SPI_H__
#define __SPI_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_SPI_Driver SPI Driver
@{
*/
/** @addtogroup M480_SPI_EXPORTED_CONSTANTS SPI Exported Constants
@{
*/
#define SPI_MODE_0 (SPI_CTL_TXNEG_Msk) /*!< CLKPOL=0; RXNEG=0; TXNEG=1 \hideinitializer */
#define SPI_MODE_1 (SPI_CTL_RXNEG_Msk) /*!< CLKPOL=0; RXNEG=1; TXNEG=0 \hideinitializer */
#define SPI_MODE_2 (SPI_CTL_CLKPOL_Msk | SPI_CTL_RXNEG_Msk) /*!< CLKPOL=1; RXNEG=1; TXNEG=0 \hideinitializer */
#define SPI_MODE_3 (SPI_CTL_CLKPOL_Msk | SPI_CTL_TXNEG_Msk) /*!< CLKPOL=1; RXNEG=0; TXNEG=1 \hideinitializer */
#define SPI_SLAVE (SPI_CTL_SLAVE_Msk) /*!< Set as slave \hideinitializer */
#define SPI_MASTER (0x0U) /*!< Set as master \hideinitializer */
#define SPI_SS (SPI_SSCTL_SS_Msk) /*!< Set SS \hideinitializer */
#define SPI_SS_ACTIVE_HIGH (SPI_SSCTL_SSACTPOL_Msk) /*!< SS active high \hideinitializer */
#define SPI_SS_ACTIVE_LOW (0x0U) /*!< SS active low \hideinitializer */
/* SPI Interrupt Mask */
#define SPI_UNIT_INT_MASK (0x001U) /*!< Unit transfer interrupt mask \hideinitializer */
#define SPI_SSACT_INT_MASK (0x002U) /*!< Slave selection signal active interrupt mask \hideinitializer */
#define SPI_SSINACT_INT_MASK (0x004U) /*!< Slave selection signal inactive interrupt mask \hideinitializer */
#define SPI_SLVUR_INT_MASK (0x008U) /*!< Slave under run interrupt mask \hideinitializer */
#define SPI_SLVBE_INT_MASK (0x010U) /*!< Slave bit count error interrupt mask \hideinitializer */
#define SPI_TXUF_INT_MASK (0x040U) /*!< Slave TX underflow interrupt mask \hideinitializer */
#define SPI_FIFO_TXTH_INT_MASK (0x080U) /*!< FIFO TX threshold interrupt mask \hideinitializer */
#define SPI_FIFO_RXTH_INT_MASK (0x100U) /*!< FIFO RX threshold interrupt mask \hideinitializer */
#define SPI_FIFO_RXOV_INT_MASK (0x200U) /*!< FIFO RX overrun interrupt mask \hideinitializer */
#define SPI_FIFO_RXTO_INT_MASK (0x400U) /*!< FIFO RX time-out interrupt mask \hideinitializer */
/* SPI Status Mask */
#define SPI_BUSY_MASK (0x01U) /*!< Busy status mask \hideinitializer */
#define SPI_RX_EMPTY_MASK (0x02U) /*!< RX empty status mask \hideinitializer */
#define SPI_RX_FULL_MASK (0x04U) /*!< RX full status mask \hideinitializer */
#define SPI_TX_EMPTY_MASK (0x08U) /*!< TX empty status mask \hideinitializer */
#define SPI_TX_FULL_MASK (0x10U) /*!< TX full status mask \hideinitializer */
#define SPI_TXRX_RESET_MASK (0x20U) /*!< TX or RX reset status mask \hideinitializer */
#define SPI_SPIEN_STS_MASK (0x40U) /*!< SPIEN status mask \hideinitializer */
#define SPI_SSLINE_STS_MASK (0x80U) /*!< SPIx_SS line status mask \hideinitializer */
/* I2S Data Width */
#define SPII2S_DATABIT_8 (0U << SPI_I2SCTL_WDWIDTH_Pos) /*!< I2S data width is 8-bit \hideinitializer */
#define SPII2S_DATABIT_16 (1U << SPI_I2SCTL_WDWIDTH_Pos) /*!< I2S data width is 16-bit \hideinitializer */
#define SPII2S_DATABIT_24 (2U << SPI_I2SCTL_WDWIDTH_Pos) /*!< I2S data width is 24-bit \hideinitializer */
#define SPII2S_DATABIT_32 (3U << SPI_I2SCTL_WDWIDTH_Pos) /*!< I2S data width is 32-bit \hideinitializer */
/* I2S Audio Format */
#define SPII2S_MONO SPI_I2SCTL_MONO_Msk /*!< Monaural channel \hideinitializer */
#define SPII2S_STEREO (0U) /*!< Stereo channel \hideinitializer */
/* I2S Data Format */
#define SPII2S_FORMAT_I2S (0U<<SPI_I2SCTL_FORMAT_Pos) /*!< I2S data format \hideinitializer */
#define SPII2S_FORMAT_MSB (1U<<SPI_I2SCTL_FORMAT_Pos) /*!< MSB justified data format \hideinitializer */
#define SPII2S_FORMAT_PCMA (2U<<SPI_I2SCTL_FORMAT_Pos) /*!< PCM mode A data format \hideinitializer */
#define SPII2S_FORMAT_PCMB (3U<<SPI_I2SCTL_FORMAT_Pos) /*!< PCM mode B data format \hideinitializer */
/* I2S Operation mode */
#define SPII2S_MODE_SLAVE SPI_I2SCTL_SLAVE_Msk /*!< As slave mode \hideinitializer */
#define SPII2S_MODE_MASTER (0U) /*!< As master mode \hideinitializer */
/* I2S TX FIFO Threshold */
#define SPII2S_FIFO_TX_LEVEL_WORD_0 (0U) /*!< TX threshold is 0 word \hideinitializer */
#define SPII2S_FIFO_TX_LEVEL_WORD_1 (1U << SPI_FIFOCTL_TXTH_Pos) /*!< TX threshold is 1 word \hideinitializer */
#define SPII2S_FIFO_TX_LEVEL_WORD_2 (2U << SPI_FIFOCTL_TXTH_Pos) /*!< TX threshold is 2 words \hideinitializer */
#define SPII2S_FIFO_TX_LEVEL_WORD_3 (3U << SPI_FIFOCTL_TXTH_Pos) /*!< TX threshold is 3 words \hideinitializer */
/* I2S RX FIFO Threshold */
#define SPII2S_FIFO_RX_LEVEL_WORD_1 (0U) /*!< RX threshold is 1 word \hideinitializer */
#define SPII2S_FIFO_RX_LEVEL_WORD_2 (1U << SPI_FIFOCTL_RXTH_Pos) /*!< RX threshold is 2 words \hideinitializer */
#define SPII2S_FIFO_RX_LEVEL_WORD_3 (2U << SPI_FIFOCTL_RXTH_Pos) /*!< RX threshold is 3 words \hideinitializer */
#define SPII2S_FIFO_RX_LEVEL_WORD_4 (3U << SPI_FIFOCTL_RXTH_Pos) /*!< RX threshold is 4 words \hideinitializer */
/* I2S Record Channel */
#define SPII2S_MONO_RIGHT (0U) /*!< Record mono right channel \hideinitializer */
#define SPII2S_MONO_LEFT SPI_I2SCTL_RXLCH_Msk /*!< Record mono left channel \hideinitializer */
/* I2S Channel */
#define SPII2S_RIGHT (0U) /*!< Select right channel \hideinitializer */
#define SPII2S_LEFT (1U) /*!< Select left channel \hideinitializer */
/* I2S Interrupt Mask */
#define SPII2S_FIFO_TXTH_INT_MASK (0x01U) /*!< TX FIFO threshold interrupt mask \hideinitializer */
#define SPII2S_FIFO_RXTH_INT_MASK (0x02U) /*!< RX FIFO threshold interrupt mask \hideinitializer */
#define SPII2S_FIFO_RXOV_INT_MASK (0x04U) /*!< RX FIFO overrun interrupt mask \hideinitializer */
#define SPII2S_FIFO_RXTO_INT_MASK (0x08U) /*!< RX FIFO time-out interrupt mask \hideinitializer */
#define SPII2S_TXUF_INT_MASK (0x10U) /*!< TX FIFO underflow interrupt mask \hideinitializer */
#define SPII2S_RIGHT_ZC_INT_MASK (0x20U) /*!< Right channel zero cross interrupt mask \hideinitializer */
#define SPII2S_LEFT_ZC_INT_MASK (0x40U) /*!< Left channel zero cross interrupt mask \hideinitializer */
/*@}*/ /* end of group M480_SPI_EXPORTED_CONSTANTS */
/** @addtogroup M480_SPI_EXPORTED_FUNCTIONS SPI Exported Functions
@{
*/
/**
* @brief Clear the unit transfer interrupt flag.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Write 1 to UNITIF bit of SPI_STATUS register to clear the unit transfer interrupt flag.
* \hideinitializer
*/
#define SPI_CLR_UNIT_TRANS_INT_FLAG(spi) ((spi)->STATUS = SPI_STATUS_UNITIF_Msk)
/**
* @brief Trigger RX PDMA function.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Set RXPDMAEN bit of SPI_PDMACTL register to enable RX PDMA transfer function.
* \hideinitializer
*/
#define SPI_TRIGGER_RX_PDMA(spi) ((spi)->PDMACTL |= SPI_PDMACTL_RXPDMAEN_Msk)
/**
* @brief Trigger TX PDMA function.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Set TXPDMAEN bit of SPI_PDMACTL register to enable TX PDMA transfer function.
* \hideinitializer
*/
#define SPI_TRIGGER_TX_PDMA(spi) ((spi)->PDMACTL |= SPI_PDMACTL_TXPDMAEN_Msk)
/**
* @brief Disable RX PDMA transfer.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Clear RXPDMAEN bit of SPI_PDMACTL register to disable RX PDMA transfer function.
* \hideinitializer
*/
#define SPI_DISABLE_RX_PDMA(spi) ( (spi)->PDMACTL &= ~SPI_PDMACTL_RXPDMAEN_Msk )
/**
* @brief Disable TX PDMA transfer.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Clear TXPDMAEN bit of SPI_PDMACTL register to disable TX PDMA transfer function.
* \hideinitializer
*/
#define SPI_DISABLE_TX_PDMA(spi) ( (spi)->PDMACTL &= ~SPI_PDMACTL_TXPDMAEN_Msk )
/**
* @brief Get the count of available data in RX FIFO.
* @param[in] spi The pointer of the specified SPI module.
* @return The count of available data in RX FIFO.
* @details Read RXCNT (SPI_STATUS[27:24]) to get the count of available data in RX FIFO.
* \hideinitializer
*/
#define SPI_GET_RX_FIFO_COUNT(spi) (((spi)->STATUS & SPI_STATUS_RXCNT_Msk) >> SPI_STATUS_RXCNT_Pos)
/**
* @brief Get the RX FIFO empty flag.
* @param[in] spi The pointer of the specified SPI module.
* @retval 0 RX FIFO is not empty.
* @retval 1 RX FIFO is empty.
* @details Read RXEMPTY bit of SPI_STATUS register to get the RX FIFO empty flag.
* \hideinitializer
*/
#define SPI_GET_RX_FIFO_EMPTY_FLAG(spi) (((spi)->STATUS & SPI_STATUS_RXEMPTY_Msk)>>SPI_STATUS_RXEMPTY_Pos)
/**
* @brief Get the TX FIFO empty flag.
* @param[in] spi The pointer of the specified SPI module.
* @retval 0 TX FIFO is not empty.
* @retval 1 TX FIFO is empty.
* @details Read TXEMPTY bit of SPI_STATUS register to get the TX FIFO empty flag.
* \hideinitializer
*/
#define SPI_GET_TX_FIFO_EMPTY_FLAG(spi) (((spi)->STATUS & SPI_STATUS_TXEMPTY_Msk)>>SPI_STATUS_TXEMPTY_Pos)
/**
* @brief Get the TX FIFO full flag.
* @param[in] spi The pointer of the specified SPI module.
* @retval 0 TX FIFO is not full.
* @retval 1 TX FIFO is full.
* @details Read TXFULL bit of SPI_STATUS register to get the TX FIFO full flag.
* \hideinitializer
*/
#define SPI_GET_TX_FIFO_FULL_FLAG(spi) (((spi)->STATUS & SPI_STATUS_TXFULL_Msk)>>SPI_STATUS_TXFULL_Pos)
/**
* @brief Get the datum read from RX register.
* @param[in] spi The pointer of the specified SPI module.
* @return Data in RX register.
* @details Read SPI_RX register to get the received datum.
* \hideinitializer
*/
#define SPI_READ_RX(spi) ((spi)->RX)
/**
* @brief Write datum to TX register.
* @param[in] spi The pointer of the specified SPI module.
* @param[in] u32TxData The datum which user attempt to transfer through SPI bus.
* @return None.
* @details Write u32TxData to SPI_TX register.
* \hideinitializer
*/
#define SPI_WRITE_TX(spi, u32TxData) ((spi)->TX = (u32TxData))
/**
* @brief Set SPIx_SS pin to high state.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Disable automatic slave selection function and set SPIx_SS pin to high state.
* \hideinitializer
*/
#define SPI_SET_SS_HIGH(spi) ((spi)->SSCTL = ((spi)->SSCTL & (~SPI_SSCTL_AUTOSS_Msk)) | (SPI_SSCTL_SSACTPOL_Msk | SPI_SSCTL_SS_Msk))
/**
* @brief Set SPIx_SS pin to low state.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Disable automatic slave selection function and set SPIx_SS pin to low state.
* \hideinitializer
*/
#define SPI_SET_SS_LOW(spi) ((spi)->SSCTL = ((spi)->SSCTL & (~(SPI_SSCTL_AUTOSS_Msk | SPI_SSCTL_SSACTPOL_Msk))) | SPI_SSCTL_SS_Msk)
/**
* @brief Enable Byte Reorder function.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Enable Byte Reorder function. The suspend interval depends on the setting of SUSPITV (SPI_CTL[7:4]).
* \hideinitializer
*/
#define SPI_ENABLE_BYTE_REORDER(spi) ((spi)->CTL |= SPI_CTL_REORDER_Msk)
/**
* @brief Disable Byte Reorder function.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Clear REORDER bit field of SPI_CTL register to disable Byte Reorder function.
* \hideinitializer
*/
#define SPI_DISABLE_BYTE_REORDER(spi) ((spi)->CTL &= ~SPI_CTL_REORDER_Msk)
/**
* @brief Set the length of suspend interval.
* @param[in] spi The pointer of the specified SPI module.
* @param[in] u32SuspCycle Decides the length of suspend interval. It could be 0 ~ 15.
* @return None.
* @details Set the length of suspend interval according to u32SuspCycle.
* The length of suspend interval is ((u32SuspCycle + 0.5) * the length of one SPI bus clock cycle).
* \hideinitializer
*/
#define SPI_SET_SUSPEND_CYCLE(spi, u32SuspCycle) ((spi)->CTL = ((spi)->CTL & ~SPI_CTL_SUSPITV_Msk) | ((u32SuspCycle) << SPI_CTL_SUSPITV_Pos))
/**
* @brief Set the SPI transfer sequence with LSB first.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Set LSB bit of SPI_CTL register to set the SPI transfer sequence with LSB first.
* \hideinitializer
*/
#define SPI_SET_LSB_FIRST(spi) ((spi)->CTL |= SPI_CTL_LSB_Msk)
/**
* @brief Set the SPI transfer sequence with MSB first.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Clear LSB bit of SPI_CTL register to set the SPI transfer sequence with MSB first.
* \hideinitializer
*/
#define SPI_SET_MSB_FIRST(spi) ((spi)->CTL &= ~SPI_CTL_LSB_Msk)
/**
* @brief Set the data width of a SPI transaction.
* @param[in] spi The pointer of the specified SPI module.
* @param[in] u32Width The bit width of one transaction.
* @return None.
* @details The data width can be 8 ~ 32 bits.
* \hideinitializer
*/
#define SPI_SET_DATA_WIDTH(spi, u32Width) ((spi)->CTL = ((spi)->CTL & ~SPI_CTL_DWIDTH_Msk) | (((u32Width)&0x1F) << SPI_CTL_DWIDTH_Pos))
/**
* @brief Get the SPI busy state.
* @param[in] spi The pointer of the specified SPI module.
* @retval 0 SPI controller is not busy.
* @retval 1 SPI controller is busy.
* @details This macro will return the busy state of SPI controller.
* \hideinitializer
*/
#define SPI_IS_BUSY(spi) ( ((spi)->STATUS & SPI_STATUS_BUSY_Msk)>>SPI_STATUS_BUSY_Pos )
/**
* @brief Enable SPI controller.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Set SPIEN (SPI_CTL[0]) to enable SPI controller.
* \hideinitializer
*/
#define SPI_ENABLE(spi) ((spi)->CTL |= SPI_CTL_SPIEN_Msk)
/**
* @brief Disable SPI controller.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Clear SPIEN (SPI_CTL[0]) to disable SPI controller.
* \hideinitializer
*/
#define SPI_DISABLE(spi) ((spi)->CTL &= ~SPI_CTL_SPIEN_Msk)
/**
* @brief Disable SPI Dual IO function.
* @param[in] spi is the base address of SPI module.
* @return none
* \hideinitializer
*/
#define SPI_DISABLE_DUAL_MODE(spi) ( (spi)->CTL &= ~SPI_CTL_DUALIOEN_Msk )
/**
* @brief Enable Dual IO function and set SPI Dual IO direction to input.
* @param[in] spi is the base address of SPI module.
* @return none
* \hideinitializer
*/
#define SPI_ENABLE_DUAL_INPUT_MODE(spi) ( (spi)->CTL = ((spi)->CTL & ~SPI_CTL_DATDIR_Msk) | SPI_CTL_DUALIOEN_Msk )
/**
* @brief Enable Dual IO function and set SPI Dual IO direction to output.
* @param[in] spi is the base address of SPI module.
* @return none
* \hideinitializer
*/
#define SPI_ENABLE_DUAL_OUTPUT_MODE(spi) ( (spi)->CTL |= SPI_CTL_DATDIR_Msk | SPI_CTL_DUALIOEN_Msk )
/**
* @brief Disable SPI Dual IO function.
* @param[in] spi is the base address of SPI module.
* @return none
* \hideinitializer
*/
#define SPI_DISABLE_QUAD_MODE(spi) ( (spi)->CTL &= ~SPI_CTL_QUADIOEN_Msk )
/**
* @brief Set SPI Quad IO direction to input.
* @param[in] spi is the base address of SPI module.
* @return none
* \hideinitializer
*/
#define SPI_ENABLE_QUAD_INPUT_MODE(spi) ( (spi)->CTL = ((spi)->CTL & ~SPI_CTL_DATDIR_Msk) | SPI_CTL_QUADIOEN_Msk )
/**
* @brief Set SPI Quad IO direction to output.
* @param[in] spi is the base address of SPI module.
* @return none
* \hideinitializer
*/
#define SPI_ENABLE_QUAD_OUTPUT_MODE(spi) ( (spi)->CTL |= SPI_CTL_DATDIR_Msk | SPI_CTL_QUADIOEN_Msk )
/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */
static __INLINE void SPII2S_ENABLE_TX_ZCD(SPI_T *i2s, uint32_t u32ChMask);
static __INLINE void SPII2S_DISABLE_TX_ZCD(SPI_T *i2s, uint32_t u32ChMask);
static __INLINE void SPII2S_SET_MONO_RX_CHANNEL(SPI_T *i2s, uint32_t u32Ch);
/**
* @brief Enable zero cross detection function.
* @param[in] i2s The pointer of the specified I2S module.
* @param[in] u32ChMask The mask for left or right channel. Valid values are:
* - \ref SPII2S_RIGHT
* - \ref SPII2S_LEFT
* @return None
* @details This function will set RZCEN or LZCEN bit of SPI_I2SCTL register to enable zero cross detection function.
*/
static __INLINE void SPII2S_ENABLE_TX_ZCD(SPI_T *i2s, uint32_t u32ChMask)
{
if(u32ChMask == SPII2S_RIGHT) {
i2s->I2SCTL |= SPI_I2SCTL_RZCEN_Msk;
} else {
i2s->I2SCTL |= SPI_I2SCTL_LZCEN_Msk;
}
}
/**
* @brief Disable zero cross detection function.
* @param[in] i2s The pointer of the specified I2S module.
* @param[in] u32ChMask The mask for left or right channel. Valid values are:
* - \ref SPII2S_RIGHT
* - \ref SPII2S_LEFT
* @return None
* @details This function will clear RZCEN or LZCEN bit of SPI_I2SCTL register to disable zero cross detection function.
*/
static __INLINE void SPII2S_DISABLE_TX_ZCD(SPI_T *i2s, uint32_t u32ChMask)
{
if(u32ChMask == SPII2S_RIGHT) {
i2s->I2SCTL &= ~SPI_I2SCTL_RZCEN_Msk;
} else {
i2s->I2SCTL &= ~SPI_I2SCTL_LZCEN_Msk;
}
}
/**
* @brief Enable I2S TX DMA function.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will set TXPDMAEN bit of SPI_PDMACTL register to transmit data with PDMA.
* \hideinitializer
*/
#define SPII2S_ENABLE_TXDMA(i2s) ( (i2s)->PDMACTL |= SPI_PDMACTL_TXPDMAEN_Msk )
/**
* @brief Disable I2S TX DMA function.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will clear TXPDMAEN bit of SPI_PDMACTL register to disable TX DMA function.
* \hideinitializer
*/
#define SPII2S_DISABLE_TXDMA(i2s) ( (i2s)->PDMACTL &= ~SPI_PDMACTL_TXPDMAEN_Msk )
/**
* @brief Enable I2S RX DMA function.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will set RXPDMAEN bit of SPI_PDMACTL register to receive data with PDMA.
* \hideinitializer
*/
#define SPII2S_ENABLE_RXDMA(i2s) ( (i2s)->PDMACTL |= SPI_PDMACTL_RXPDMAEN_Msk )
/**
* @brief Disable I2S RX DMA function.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will clear RXPDMAEN bit of SPI_PDMACTL register to disable RX DMA function.
* \hideinitializer
*/
#define SPII2S_DISABLE_RXDMA(i2s) ( (i2s)->PDMACTL &= ~SPI_PDMACTL_RXPDMAEN_Msk )
/**
* @brief Enable I2S TX function.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will set TXEN bit of SPI_I2SCTL register to enable I2S TX function.
* \hideinitializer
*/
#define SPII2S_ENABLE_TX(i2s) ( (i2s)->I2SCTL |= SPI_I2SCTL_TXEN_Msk )
/**
* @brief Disable I2S TX function.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will clear TXEN bit of SPI_I2SCTL register to disable I2S TX function.
* \hideinitializer
*/
#define SPII2S_DISABLE_TX(i2s) ( (i2s)->I2SCTL &= ~SPI_I2SCTL_TXEN_Msk )
/**
* @brief Enable I2S RX function.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will set RXEN bit of SPI_I2SCTL register to enable I2S RX function.
* \hideinitializer
*/
#define SPII2S_ENABLE_RX(i2s) ( (i2s)->I2SCTL |= SPI_I2SCTL_RXEN_Msk )
/**
* @brief Disable I2S RX function.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will clear RXEN bit of SPI_I2SCTL register to disable I2S RX function.
* \hideinitializer
*/
#define SPII2S_DISABLE_RX(i2s) ( (i2s)->I2SCTL &= ~SPI_I2SCTL_RXEN_Msk )
/**
* @brief Enable TX Mute function.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will set MUTE bit of SPI_I2SCTL register to enable I2S TX mute function.
* \hideinitializer
*/
#define SPII2S_ENABLE_TX_MUTE(i2s) ( (i2s)->I2SCTL |= SPI_I2SCTL_MUTE_Msk )
/**
* @brief Disable TX Mute function.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will clear MUTE bit of SPI_I2SCTL register to disable I2S TX mute function.
* \hideinitializer
*/
#define SPII2S_DISABLE_TX_MUTE(i2s) ( (i2s)->I2SCTL &= ~SPI_I2SCTL_MUTE_Msk )
/**
* @brief Clear TX FIFO.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will clear TX FIFO. The internal TX FIFO pointer will be reset to FIFO start point.
* \hideinitializer
*/
#define SPII2S_CLR_TX_FIFO(i2s) ( (i2s)->FIFOCTL |= SPI_FIFOCTL_TXFBCLR_Msk )
/**
* @brief Clear RX FIFO.
* @param[in] i2s The pointer of the specified I2S module.
* @return None
* @details This macro will clear RX FIFO. The internal RX FIFO pointer will be reset to FIFO start point.
* \hideinitializer
*/
#define SPII2S_CLR_RX_FIFO(i2s) ( (i2s)->FIFOCTL |= SPI_FIFOCTL_RXFBCLR_Msk )
/**
* @brief This function sets the recording source channel when mono mode is used.
* @param[in] i2s The pointer of the specified I2S module.
* @param[in] u32Ch left or right channel. Valid values are:
* - \ref SPII2S_MONO_LEFT
* - \ref SPII2S_MONO_RIGHT
* @return None
* @details This function selects the recording source channel of monaural mode.
* \hideinitializer
*/
static __INLINE void SPII2S_SET_MONO_RX_CHANNEL(SPI_T *i2s, uint32_t u32Ch)
{
u32Ch == SPII2S_MONO_LEFT ?
(i2s->I2SCTL |= SPI_I2SCTL_RXLCH_Msk) :
(i2s->I2SCTL &= ~SPI_I2SCTL_RXLCH_Msk);
}
/**
* @brief Write data to I2S TX FIFO.
* @param[in] i2s The pointer of the specified I2S module.
* @param[in] u32Data The value written to TX FIFO.
* @return None
* @details This macro will write a value to TX FIFO.
* \hideinitializer
*/
#define SPII2S_WRITE_TX_FIFO(i2s, u32Data) ( (i2s)->TX = (u32Data) )
/**
* @brief Read RX FIFO.
* @param[in] i2s The pointer of the specified I2S module.
* @return The value read from RX FIFO.
* @details This function will return a value read from RX FIFO.
* \hideinitializer
*/
#define SPII2S_READ_RX_FIFO(i2s) ( (i2s)->RX )
/**
* @brief Get the interrupt flag.
* @param[in] i2s The pointer of the specified I2S module.
* @param[in] u32Mask The mask value for all interrupt flags.
* @return The interrupt flags specified by the u32mask parameter.
* @details This macro will return the combination interrupt flags of SPI_I2SSTS register. The flags are specified by the u32mask parameter.
* \hideinitializer
*/
#define SPII2S_GET_INT_FLAG(i2s, u32Mask) ( (i2s)->I2SSTS & (u32Mask) )
/**
* @brief Clear the interrupt flag.
* @param[in] i2s The pointer of the specified I2S module.
* @param[in] u32Mask The mask value for all interrupt flags.
* @return None
* @details This macro will clear the interrupt flags specified by the u32mask parameter.
* @note Except TX and RX FIFO threshold interrupt flags, the other interrupt flags can be cleared by writing 1 to itself.
* \hideinitializer
*/
#define SPII2S_CLR_INT_FLAG(i2s, u32Mask) ( (i2s)->I2SSTS = (u32Mask) )
/**
* @brief Get transmit FIFO level
* @param[in] i2s The pointer of the specified I2S module.
* @return TX FIFO level
* @details This macro will return the number of available words in TX FIFO.
* \hideinitializer
*/
#define SPII2S_GET_TX_FIFO_LEVEL(i2s) ( ((i2s)->I2SSTS & SPI_I2SSTS_TXCNT_Msk) >> SPI_I2SSTS_TXCNT_Pos )
/**
* @brief Get receive FIFO level
* @param[in] i2s The pointer of the specified I2S module.
* @return RX FIFO level
* @details This macro will return the number of available words in RX FIFO.
* \hideinitializer
*/
#define SPII2S_GET_RX_FIFO_LEVEL(i2s) ( ((i2s)->I2SSTS & SPI_I2SSTS_RXCNT_Msk) >> SPI_I2SSTS_RXCNT_Pos )
/* Function prototype declaration */
uint32_t SPI_Open(SPI_T *spi, uint32_t u32MasterSlave, uint32_t u32SPIMode, uint32_t u32DataWidth, uint32_t u32BusClock);
void SPI_Close(SPI_T *spi);
void SPI_ClearRxFIFO(SPI_T *spi);
void SPI_ClearTxFIFO(SPI_T *spi);
void SPI_DisableAutoSS(SPI_T *spi);
void SPI_EnableAutoSS(SPI_T *spi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel);
uint32_t SPI_SetBusClock(SPI_T *spi, uint32_t u32BusClock);
void SPI_SetFIFO(SPI_T *spi, uint32_t u32TxThreshold, uint32_t u32RxThreshold);
uint32_t SPI_GetBusClock(SPI_T *spi);
void SPI_EnableInt(SPI_T *spi, uint32_t u32Mask);
void SPI_DisableInt(SPI_T *spi, uint32_t u32Mask);
uint32_t SPI_GetIntFlag(SPI_T *spi, uint32_t u32Mask);
void SPI_ClearIntFlag(SPI_T *spi, uint32_t u32Mask);
uint32_t SPI_GetStatus(SPI_T *spi, uint32_t u32Mask);
uint32_t SPII2S_Open(SPI_T *i2s, uint32_t u32MasterSlave, uint32_t u32SampleRate, uint32_t u32WordWidth, uint32_t u32Channels, uint32_t u32DataFormat);
void SPII2S_Close(SPI_T *i2s);
void SPII2S_EnableInt(SPI_T *i2s, uint32_t u32Mask);
void SPII2S_DisableInt(SPI_T *i2s, uint32_t u32Mask);
uint32_t SPII2S_EnableMCLK(SPI_T *i2s, uint32_t u32BusClock);
void SPII2S_DisableMCLK(SPI_T *i2s);
void SPII2S_SetFIFO(SPI_T *i2s, uint32_t u32TxThreshold, uint32_t u32RxThreshold);
/*@}*/ /* end of group M480_SPI_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_SPI_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,630 @@
/**************************************************************************//**
* @file spim.h
* @version V1.00
* @brief M480 series SPIM driver header file
*
* @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __SPIM_H__
#define __SPIM_H__
/*---------------------------------------------------------------------------------------------------------*/
/* Include related headers */
/*---------------------------------------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_SPIM_Driver SPIM Driver
@{
*/
/** @addtogroup M480_SPIM_EXPORTED_CONSTANTS SPIM Exported Constants
@{
*/
#define SPIM_DMM_MAP_ADDR 0x8000000UL /*!< DMM mode memory map base address \hideinitializer */
#define SPIM_DMM_SIZE 0x2000000UL /*!< DMM mode memory mapping size \hideinitializer */
#define SPIM_CCM_ADDR 0x20020000UL /*!< CCM mode memory map base address \hideinitializer */
#define SPIM_CCM_SIZE 0x8000UL /*!< CCM mode memory size \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* SPIM_CTL0 constant definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define SPIM_CTL0_RW_IN(x) ((x) ? 0UL : (0x1UL << SPIM_CTL0_QDIODIR_Pos)) /*!< SPIM_CTL0: SPI Interface Direction Select \hideinitializer */
#define SPIM_CTL0_BITMODE_SING (0UL << SPIM_CTL0_BITMODE_Pos) /*!< SPIM_CTL0: One bit mode (SPI Interface including DO, DI, HOLD, WP) \hideinitializer */
#define SPIM_CTL0_BITMODE_DUAL (1UL << SPIM_CTL0_BITMODE_Pos) /*!< SPIM_CTL0: Two bits mode (SPI Interface including D0, D1, HOLD, WP) \hideinitializer */
#define SPIM_CTL0_BITMODE_QUAD (2UL << SPIM_CTL0_BITMODE_Pos) /*!< SPIM_CTL0: Four bits mode (SPI Interface including D0, D1, D2, D3) \hideinitializer */
#define SPIM_CTL0_OPMODE_IO (0UL << SPIM_CTL0_OPMODE_Pos) /*!< SPIM_CTL0: I/O Mode \hideinitializer */
#define SPIM_CTL0_OPMODE_PAGEWRITE (1UL << SPIM_CTL0_OPMODE_Pos) /*!< SPIM_CTL0: Page Write Mode \hideinitializer */
#define SPIM_CTL0_OPMODE_PAGEREAD (2UL << SPIM_CTL0_OPMODE_Pos) /*!< SPIM_CTL0: Page Read Mode \hideinitializer */
#define SPIM_CTL0_OPMODE_DIRECTMAP (3UL << SPIM_CTL0_OPMODE_Pos) /*!< SPIM_CTL0: Direct Map Mode \hideinitializer */
#define CMD_NORMAL_PAGE_PROGRAM (0x02UL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Page Program (Page Write Mode Use) \hideinitializer */
#define CMD_NORMAL_PAGE_PROGRAM_4B (0x12UL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Page Program (Page Write Mode Use) \hideinitializer */
#define CMD_QUAD_PAGE_PROGRAM_WINBOND (0x32UL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Quad Page program (for Winbond) (Page Write Mode Use) \hideinitializer */
#define CMD_QUAD_PAGE_PROGRAM_MXIC (0x38UL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Quad Page program (for MXIC) (Page Write Mode Use) \hideinitializer */
#define CMD_QUAD_PAGE_PROGRAM_EON (0x40UL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Quad Page Program (for EON) (Page Write Mode Use) \hideinitializer */
#define CMD_DMA_NORMAL_READ (0x03UL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Read Data (Page Read Mode Use) \hideinitializer */
#define CMD_DMA_FAST_READ (0x0BUL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Fast Read (Page Read Mode Use) \hideinitializer */
#define CMD_DMA_NORMAL_DUAL_READ (0x3BUL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Fast Read Dual Output (Page Read Mode Use) \hideinitializer */
#define CMD_DMA_FAST_READ_DUAL_OUTPUT (0x3BUL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Fast Read Dual Output (Page Read Mode Use) \hideinitializer */
#define CMD_DMA_FAST_READ_QUAD_OUTPUT (0x6BUL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Fast Read Dual Output (Page Read Mode Use) \hideinitializer */
#define CMD_DMA_FAST_DUAL_READ (0xBBUL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Fast Read Dual Output (Page Read Mode Use) \hideinitializer */
#define CMD_DMA_NORMAL_QUAD_READ (0xE7UL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Fast Read Quad I/O (Page Read Mode Use) \hideinitializer */
#define CMD_DMA_FAST_QUAD_READ (0xEBUL << SPIM_CTL0_CMDCODE_Pos) /*!< SPIM_CTL0: Fast Read Quad I/O (Page Read Mode Use) \hideinitializer */
/** @cond HIDDEN_SYMBOLS */
typedef enum {
MFGID_UNKNOW = 0x00U,
MFGID_SPANSION = 0x01U,
MFGID_EON = 0x1CU,
MFGID_ISSI = 0x7FU,
MFGID_MXIC = 0xC2U,
MFGID_WINBOND = 0xEFU
}
E_MFGID;
/* Flash opcodes. */
#define OPCODE_WREN 0x06U /* Write enable */
#define OPCODE_RDSR 0x05U /* Read status register #1*/
#define OPCODE_WRSR 0x01U /* Write status register #1 */
#define OPCODE_RDSR2 0x35U /* Read status register #2*/
#define OPCODE_WRSR2 0x31U /* Write status register #2 */
#define OPCODE_RDSR3 0x15U /* Read status register #3*/
#define OPCODE_WRSR3 0x11U /* Write status register #3 */
#define OPCODE_PP 0x02U /* Page program (up to 256 bytes) */
#define OPCODE_SE_4K 0x20U /* Erase 4KB sector */
#define OPCODE_BE_32K 0x52U /* Erase 32KB block */
#define OPCODE_CHIP_ERASE 0xc7U /* Erase whole flash chip */
#define OPCODE_BE_64K 0xd8U /* Erase 64KB block */
#define OPCODE_READ_ID 0x90U /* Read ID */
#define OPCODE_RDID 0x9fU /* Read JEDEC ID */
#define OPCODE_BRRD 0x16U /* SPANSION flash - Bank Register Read command */
#define OPCODE_BRWR 0x17U /* SPANSION flash - Bank Register write command */
#define OPCODE_NORM_READ 0x03U /* Read data bytes */
#define OPCODE_FAST_READ 0x0bU /* Read data bytes */
#define OPCODE_FAST_DUAL_READ 0x3bU /* Read data bytes */
#define OPCODE_FAST_QUAD_READ 0x6bU /* Read data bytes */
/* Used for SST flashes only. */
#define OPCODE_BP 0x02U /* Byte program */
#define OPCODE_WRDI 0x04U /* Write disable */
#define OPCODE_AAI_WP 0xadU /* Auto u32Address increment word program */
/* Used for Macronix flashes only. */
#define OPCODE_EN4B 0xb7U /* Enter 4-byte mode */
#define OPCODE_EX4B 0xe9U /* Exit 4-byte mode */
#define OPCODE_RDSCUR 0x2bU
#define OPCODE_WRSCUR 0x2fU
#define OPCODE_RSTEN 0x66U
#define OPCODE_RST 0x99U
#define OPCODE_ENQPI 0x38U
#define OPCODE_EXQPI 0xFFU
/* Status Register bits. */
#define SR_WIP 0x1U /* Write in progress */
#define SR_WEL 0x2U /* Write enable latch */
#define SR_QE 0x40U /* Quad Enable for MXIC */
/* Status Register #2 bits. */
#define SR2_QE 0x2U /* Quad Enable for Winbond */
/* meaning of other SR_* bits may differ between vendors */
#define SR_BP0 0x4U /* Block protect 0 */
#define SR_BP1 0x8U /* Block protect 1 */
#define SR_BP2 0x10U /* Block protect 2 */
#define SR_SRWD 0x80U /* SR write protect */
#define SR3_ADR 0x01U /* 4-byte u32Address mode */
#define SCUR_4BYTE 0x04U /* 4-byte u32Address mode */
/** @endcond HIDDEN_SYMBOLS */
/*@}*/ /* end of group M480_SPIM_EXPORTED_CONSTANTS */
/** @addtogroup M480_SPIM_EXPORTED_FUNCTIONS SPIM Exported Functions
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* Define Macros and functions */
/*---------------------------------------------------------------------------------------------------------*/
/**
* @details Enable cipher.
* \hideinitializer
*/
#define SPIM_ENABLE_CIPHER() (SPIM->CTL0 &= ~SPIM_CTL0_CIPHOFF_Msk)
/**
* @details Disable cipher.
* \hideinitializer
*/
#define SPIM_DISABLE_CIPHER() (SPIM->CTL0 |= SPIM_CTL0_CIPHOFF_Msk)
/**
* @details Enable cipher balance
* \hideinitializer
*/
#define SPIM_ENABLE_BALEN() (SPIM->CTL0 |= SPIM_CTL0_BALEN_Msk)
/**
* @details Disable cipher balance
* \hideinitializer
*/
#define SPIM_DISABLE_BALEN() (SPIM->CTL0 &= ~SPIM_CTL0_BALEN_Msk)
/**
* @details Set 4-byte address to be enabled/disabled.
* \hideinitializer
*/
#define SPIM_SET_4BYTE_ADDR_EN(x) \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~SPIM_CTL0_B4ADDREN_Msk)) | (((x) ? 1UL : 0UL) << SPIM_CTL0_B4ADDREN_Pos); \
} while (0)
/**
* @details Enable SPIM interrupt
* \hideinitializer
*/
#define SPIM_ENABLE_INT() (SPIM->CTL0 |= SPIM_CTL0_IEN_Msk)
/**
* @details Disable SPIM interrupt
* \hideinitializer
*/
#define SPIM_DISABLE_INT() (SPIM->CTL0 &= ~SPIM_CTL0_IEN_Msk)
/**
* @details Is interrupt flag on.
* \hideinitializer
*/
#define SPIM_IS_IF_ON() ((SPIM->CTL0 & SPIM_CTL0_IF_Msk) != 0UL)
/**
* @details Clear interrupt flag.
* \hideinitializer
*/
#define SPIM_CLR_INT() \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~SPIM_CTL0_IF_Msk)) | (1UL << SPIM_CTL0_IF_Pos); \
} while (0)
/**
* @details Set transmit/receive bit length
* \hideinitializer
*/
#define SPIM_SET_DATA_WIDTH(x) \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~SPIM_CTL0_DWIDTH_Msk)) | (((x) - 1U) << SPIM_CTL0_DWIDTH_Pos); \
} while (0)
/**
* @details Get data transmit/receive bit length setting
* \hideinitializer
*/
#define SPIM_GET_DATA_WIDTH() \
(((SPIM->CTL0 & SPIM_CTL0_DWIDTH_Msk) >> SPIM_CTL0_DWIDTH_Pos)+1U)
/**
* @details Set data transmit/receive burst number
* \hideinitializer
*/
#define SPIM_SET_DATA_NUM(x) \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~SPIM_CTL0_BURSTNUM_Msk)) | (((x) - 1U) << SPIM_CTL0_BURSTNUM_Pos); \
} while (0)
/**
* @details Get data transmit/receive burst number
* \hideinitializer
*/
#define SPIM_GET_DATA_NUM() \
(((SPIM->CTL0 & SPIM_CTL0_BURSTNUM_Msk) >> SPIM_CTL0_BURSTNUM_Pos)+1U)
/**
* @details Enable Single Input mode.
* \hideinitializer
*/
#define SPIM_ENABLE_SING_INPUT_MODE() \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~(SPIM_CTL0_BITMODE_Msk | SPIM_CTL0_QDIODIR_Msk))) | (SPIM_CTL0_BITMODE_SING | SPIM_CTL0_RW_IN(1)); \
} while (0)
/**
* @details Enable Single Output mode.
* \hideinitializer
*/
#define SPIM_ENABLE_SING_OUTPUT_MODE() \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~(SPIM_CTL0_BITMODE_Msk | SPIM_CTL0_QDIODIR_Msk))) | (SPIM_CTL0_BITMODE_SING | SPIM_CTL0_RW_IN(0)); \
} while (0)
/**
* @details Enable Dual Input mode.
* \hideinitializer
*/
#define SPIM_ENABLE_DUAL_INPUT_MODE() \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~(SPIM_CTL0_BITMODE_Msk | SPIM_CTL0_QDIODIR_Msk))) | (SPIM_CTL0_BITMODE_DUAL | SPIM_CTL0_RW_IN(1U)); \
} while (0)
/**
* @details Enable Dual Output mode.
* \hideinitializer
*/
#define SPIM_ENABLE_DUAL_OUTPUT_MODE() \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~(SPIM_CTL0_BITMODE_Msk | SPIM_CTL0_QDIODIR_Msk))) | (SPIM_CTL0_BITMODE_DUAL | SPIM_CTL0_RW_IN(0U)); \
} while (0)
/**
* @details Enable Quad Input mode.
* \hideinitializer
*/
#define SPIM_ENABLE_QUAD_INPUT_MODE() \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~(SPIM_CTL0_BITMODE_Msk | SPIM_CTL0_QDIODIR_Msk))) | (SPIM_CTL0_BITMODE_QUAD | SPIM_CTL0_RW_IN(1U)); \
} while (0)
/**
* @details Enable Quad Output mode.
* \hideinitializer
*/
#define SPIM_ENABLE_QUAD_OUTPUT_MODE() \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~(SPIM_CTL0_BITMODE_Msk | SPIM_CTL0_QDIODIR_Msk))) | (SPIM_CTL0_BITMODE_QUAD | SPIM_CTL0_RW_IN(0U)); \
} while (0)
/**
* @details Set suspend interval which ranges between 0 and 15.
* \hideinitializer
*/
#define SPIM_SET_SUSP_INTVL(x) \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~SPIM_CTL0_SUSPITV_Msk)) | ((x) << SPIM_CTL0_SUSPITV_Pos); \
} while (0)
/**
* @details Get suspend interval setting
* \hideinitializer
*/
#define SPIM_GET_SUSP_INTVL() \
((SPIM->CTL0 & SPIM_CTL0_SUSPITV_Msk) >> SPIM_CTL0_SUSPITV_Pos)
/**
* @details Set operation mode.
* \hideinitializer
*/
#define SPIM_SET_OPMODE(x) \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~SPIM_CTL0_OPMODE_Msk)) | (x); \
} while (0)
/**
* @details Get operation mode.
* \hideinitializer
*/
#define SPIM_GET_OP_MODE() (SPIM->CTL0 & SPIM_CTL0_OPMODE_Msk)
/**
* @details Set SPIM mode.
* \hideinitializer
*/
#define SPIM_SET_SPIM_MODE(x) \
do { \
SPIM->CTL0 = (SPIM->CTL0 & (~SPIM_CTL0_CMDCODE_Msk)) | (x); \
} while (0)
/**
* @details Get SPIM mode.
* \hideinitializer
*/
#define SPIM_GET_SPIM_MODE() (SPIM->CTL0 & SPIM_CTL0_CMDCODE_Msk)
/**
* @details Start operation.
* \hideinitializer
*/
#define SPIM_SET_GO() (SPIM->CTL1 |= SPIM_CTL1_SPIMEN_Msk)
/**
* @details Is engine busy.
* \hideinitializer
*/
#define SPIM_IS_BUSY() (SPIM->CTL1 & SPIM_CTL1_SPIMEN_Msk)
/**
* @details Wait for free.
* \hideinitializer
*/
#define SPIM_WAIT_FREE() \
do { \
while (SPIM->CTL1 & SPIM_CTL1_SPIMEN_Msk) { } \
} while (0)
/**
* @details Enable cache.
* \hideinitializer
*/
#define SPIM_ENABLE_CACHE() (SPIM->CTL1 &= ~SPIM_CTL1_CACHEOFF_Msk)
/**
* @details Disable cache.
* \hideinitializer
*/
#define SPIM_DISABLE_CACHE() (SPIM->CTL1 |= SPIM_CTL1_CACHEOFF_Msk)
/**
* @details Is cache enabled.
* \hideinitializer
*/
#define SPIM_IS_CACHE_EN() ((SPIM->CTL1 & SPIM_CTL1_CACHEOFF_Msk) ? 0 : 1)
/**
* @details Enable CCM
* \hideinitializer
*/
#define SPIM_ENABLE_CCM() (SPIM->CTL1 |= SPIM_CTL1_CCMEN_Msk)
/**
* @details Disable CCM.
* \hideinitializer
*/
#define SPIM_DISABLE_CCM() (SPIM->CTL1 &= ~SPIM_CTL1_CCMEN_Msk)
/**
* @details Is CCM enabled.
* \hideinitializer
*/
#define SPIM_IS_CCM_EN() ((SPIM->CTL1 & SPIM_CTL1_CCMEN_Msk) >> SPIM_CTL1_CCMEN_Pos)
/**
* @details Invalidate cache.
* \hideinitializer
*/
#define SPIM_INVALID_CACHE() (SPIM->CTL1 |= SPIM_CTL1_CDINVAL_Msk)
/**
* @details Set SS(Select Active) to active level.
* \hideinitializer
*/
#define SPIM_SET_SS_EN(x) \
do { \
(SPIM->CTL1 = (SPIM->CTL1 & (~SPIM_CTL1_SS_Msk)) | ((! (x) ? 1UL : 0UL) << SPIM_CTL1_SS_Pos)); \
} while (0)
/**
* @details Is SS(Select Active) in active level.
* \hideinitializer
*/
#define SPIM_GET_SS_EN() \
(!(SPIM->CTL1 & SPIM_CTL1_SS_Msk))
/**
* @details Set active level of slave select to be high/low.
* \hideinitializer
*/
#define SPIM_SET_SS_ACTLVL(x) \
do { \
(SPIM->CTL1 = (SPIM->CTL1 & (~SPIM_CTL1_SSACTPOL_Msk)) | ((!! (x) ? 1UL : 0UL) << SPIM_CTL1_SSACTPOL_Pos)); \
} while (0)
/**
* @details Set idle time interval
* \hideinitializer
*/
#define SPIM_SET_IDL_INTVL(x) \
do { \
SPIM->CTL1 = (SPIM->CTL1 & (~SPIM_CTL1_IDLETIME_Msk)) | ((x) << SPIM_CTL1_IDLETIME_Pos); \
} while (0)
/**
* @details Get idle time interval setting
* \hideinitializer
*/
#define SPIM_GET_IDL_INTVL() \
((SPIM->CTL1 & SPIM_CTL1_IDLETIME_Msk) >> SPIM_CTL1_IDLETIME_Pos)
/**
* @details Set SPIM clock divider
* \hideinitializer
*/
#define SPIM_SET_CLOCK_DIVIDER(x) \
do { \
SPIM->CTL1 = (SPIM->CTL1 & (~SPIM_CTL1_DIVIDER_Msk)) | ((x) << SPIM_CTL1_DIVIDER_Pos); \
} while (0)
/**
* @details Get SPIM current clock divider setting
* \hideinitializer
*/
#define SPIM_GET_CLOCK_DIVIDER() \
((SPIM->CTL1 & SPIM_CTL1_DIVIDER_Msk) >> SPIM_CTL1_DIVIDER_Pos)
/**
* @details Set SPI flash deselect time interval of DMA write mode
* \hideinitializer
*/
#define SPIM_SET_RXCLKDLY_DWDELSEL(x) \
do { \
(SPIM->RXCLKDLY = (SPIM->RXCLKDLY & (~SPIM_RXCLKDLY_DWDELSEL_Msk)) | ((x) << SPIM_RXCLKDLY_DWDELSEL_Pos)); \
} while (0)
/**
* @details Get SPI flash deselect time interval of DMA write mode
* \hideinitializer
*/
#define SPIM_GET_RXCLKDLY_DWDELSEL() \
((SPIM->RXCLKDLY & SPIM_RXCLKDLY_DWDELSEL_Msk) >> SPIM_RXCLKDLY_DWDELSEL_Pos)
/**
* @details Set sampling clock delay selection for received data
* \hideinitializer
*/
#define SPIM_SET_RXCLKDLY_RDDLYSEL(x) \
do { \
(SPIM->RXCLKDLY = (SPIM->RXCLKDLY & (~SPIM_RXCLKDLY_RDDLYSEL_Msk)) | ((x) << SPIM_RXCLKDLY_RDDLYSEL_Pos)); \
} while (0)
/**
* @details Get sampling clock delay selection for received data
* \hideinitializer
*/
#define SPIM_GET_RXCLKDLY_RDDLYSEL() \
((SPIM->RXCLKDLY & SPIM_RXCLKDLY_RDDLYSEL_Msk) >> SPIM_RXCLKDLY_RDDLYSEL_Pos)
/**
* @details Set sampling clock edge selection for received data
* \hideinitializer
*/
#define SPIM_SET_RXCLKDLY_RDEDGE() \
(SPIM->RXCLKDLY |= SPIM_RXCLKDLY_RDEDGE_Msk); \
/**
* @details Get sampling clock edge selection for received data
* \hideinitializer
*/
#define SPIM_CLR_RXCLKDLY_RDEDGE() \
(SPIM->RXCLKDLY &= ~SPIM_RXCLKDLY_RDEDGE_Msk)
/**
* @details Set mode bits data for continuous read mode
* \hideinitializer
*/
#define SPIM_SET_DMMCTL_CRMDAT(x) \
do { \
(SPIM->DMMCTL = (SPIM->DMMCTL & (~SPIM_DMMCTL_CRMDAT_Msk)) | ((x) << SPIM_DMMCTL_CRMDAT_Pos)) | SPIM_DMMCTL_CREN_Msk; \
} while (0)
/**
* @details Get mode bits data for continuous read mode
* \hideinitializer
*/
#define SPIM_GET_DMMCTL_CRMDAT() \
((SPIM->DMMCTL & SPIM_DMMCTL_CRMDAT_Msk) >> SPIM_DMMCTL_CRMDAT_Pos)
/**
* @details Set DMM mode SPI flash deselect time
* \hideinitializer
*/
#define SPIM_DMM_SET_DESELTIM(x) \
do { \
SPIM->DMMCTL = (SPIM->DMMCTL & ~SPIM_DMMCTL_DESELTIM_Msk) | (((x) & 0x1FUL) << SPIM_DMMCTL_DESELTIM_Pos); \
} while (0)
/**
* @details Get current DMM mode SPI flash deselect time setting
* \hideinitializer
*/
#define SPIM_DMM_GET_DESELTIM() \
((SPIM->DMMCTL & SPIM_DMMCTL_DESELTIM_Msk) >> SPIM_DMMCTL_DESELTIM_Pos)
/**
* @details Enable DMM mode burst wrap mode
* \hideinitializer
*/
#define SPIM_DMM_ENABLE_BWEN() (SPIM->DMMCTL |= SPIM_DMMCTL_BWEN_Msk)
/**
* @details Disable DMM mode burst wrap mode
* \hideinitializer
*/
#define SPIM_DMM_DISABLE_BWEN() (SPIM->DMMCTL &= ~SPIM_DMMCTL_BWEN_Msk)
/**
* @details Enable DMM mode continuous read mode
* \hideinitializer
*/
#define SPIM_DMM_ENABLE_CREN() (SPIM->DMMCTL |= SPIM_DMMCTL_CREN_Msk)
/**
* @details Disable DMM mode continuous read mode
* \hideinitializer
*/
#define SPIM_DMM_DISABLE_CREN() (SPIM->DMMCTL &= ~SPIM_DMMCTL_CREN_Msk)
/**
* @details Set DMM mode SPI flash active SCLK time
* \hideinitializer
*/
#define SPIM_DMM_SET_ACTSCLKT(x) \
do { \
SPIM->DMMCTL = (SPIM->DMMCTL & ~SPIM_DMMCTL_ACTSCLKT_Msk) | (((x) & 0xFUL) << SPIM_DMMCTL_ACTSCLKT_Pos) | SPIM_DMMCTL_UACTSCLK_Msk; \
} while (0)
/**
* @details Set SPI flash active SCLK time as SPIM default
* \hideinitializer
*/
#define SPIM_DMM_SET_DEFAULT_ACTSCLK() (SPIM->DMMCTL &= ~SPIM_DMMCTL_UACTSCLK_Msk)
/**
* @details Set dummy cycle number (Only for DMM mode and DMA mode)
* \hideinitializer
*/
#define SPIM_SET_DCNUM(x) \
do { \
SPIM->CTL2 = (SPIM->CTL2 & ~SPIM_CTL2_DCNUM_Msk) | (((x) & 0x1FUL) << SPIM_CTL2_DCNUM_Pos) | SPIM_CTL2_USETEN_Msk; \
} while (0)
/**
* @details Set dummy cycle number (Only for DMM mode and DMA mode) as SPIM default
* \hideinitializer
*/
#define SPIM_SET_DEFAULT_DCNUM(x) (SPIM->CTL2 &= ~SPIM_CTL2_USETEN_Msk)
/*---------------------------------------------------------------------------------------------------------*/
/* Define Function Prototypes */
/*---------------------------------------------------------------------------------------------------------*/
int SPIM_InitFlash(int clrWP);
uint32_t SPIM_GetSClkFreq(void);
void SPIM_ReadJedecId(uint8_t idBuf[], uint32_t u32NRx, uint32_t u32NBit);
int SPIM_Enable_4Bytes_Mode(int isEn, uint32_t u32NBit);
int SPIM_Is4ByteModeEnable(uint32_t u32NBit);
void SPIM_ChipErase(uint32_t u32NBit, int isSync);
void SPIM_EraseBlock(uint32_t u32Addr, int is4ByteAddr, uint8_t u8ErsCmd, uint32_t u32NBit, int isSync);
void SPIM_IO_Write(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx, uint8_t pu8TxBuf[], uint8_t wrCmd, uint32_t u32NBitCmd, uint32_t u32NBitAddr, uint32_t u32NBitDat);
void SPIM_IO_Read(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NRx, uint8_t pu8RxBuf[], uint8_t rdCmd, uint32_t u32NBitCmd, uint32_t u32NBitAddr, uint32_t u32NBitDat, int u32NDummy);
void SPIM_DMA_Write(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NTx, uint8_t pu8TxBuf[], uint32_t wrCmd);
void SPIM_DMA_Read(uint32_t u32Addr, int is4ByteAddr, uint32_t u32NRx, uint8_t pu8RxBuf[], uint32_t u32RdCmd, int isSync);
void SPIM_EnterDirectMapMode(int is4ByteAddr, uint32_t u32RdCmd, uint32_t u32IdleIntvl);
void SPIM_ExitDirectMapMode(void);
void SPIM_SetQuadEnable(int isEn, uint32_t u32NBit);
/*@}*/ /* end of group M480_SPIM_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_SPIM_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __SPIM_H__ */
/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,245 @@
/**************************************************************************//**
* @file sys.c
* @version V1.00
* $Revision: 1 $
* $Date: 16/06/14 10:32a $
* @brief M480 series SYS driver source file
*
* @note
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_SYS_Driver SYS Driver
@{
*/
/** @addtogroup M480_SYS_EXPORTED_FUNCTIONS SYS Exported Functions
@{
*/
/**
* @brief Clear reset source
* @param[in] u32Src is system reset source. Including :
* - \ref SYS_RSTSTS_CPULKRF_Msk
* - \ref SYS_RSTSTS_CPURF_Msk
* - \ref SYS_RSTSTS_SYSRF_Msk
* - \ref SYS_RSTSTS_BODRF_Msk
* - \ref SYS_RSTSTS_LVRF_Msk
* - \ref SYS_RSTSTS_WDTRF_Msk
* - \ref SYS_RSTSTS_PINRF_Msk
* - \ref SYS_RSTSTS_PORF_Msk
* @return None
* @details This function clear the selected system reset source.
*/
void SYS_ClearResetSrc(uint32_t u32Src)
{
SYS->RSTSTS |= u32Src;
}
/**
* @brief Get Brown-out detector output status
* @param None
* @retval 0 System voltage is higher than BOD_VL setting or BOD_EN is 0.
* @retval 1 System voltage is lower than BOD_VL setting.
* @details This function get Brown-out detector output status.
*/
uint32_t SYS_GetBODStatus(void)
{
return ((SYS->BODCTL & SYS_BODCTL_BODOUT_Msk) >> SYS_BODCTL_BODOUT_Pos);
}
/**
* @brief Get reset status register value
* @param None
* @return Reset source
* @details This function get the system reset status register value.
*/
uint32_t SYS_GetResetSrc(void)
{
return (SYS->RSTSTS);
}
/**
* @brief Check if register is locked nor not
* @param None
* @retval 0 Write-protection function is disabled.
* 1 Write-protection function is enabled.
* @details This function check register write-protection bit setting.
*/
uint32_t SYS_IsRegLocked(void)
{
return SYS->REGLCTL & 1UL ? 0UL : 1UL;
}
/**
* @brief Get product ID
* @param None
* @return Product ID
* @details This function get product ID.
*/
uint32_t SYS_ReadPDID(void)
{
return SYS->PDID;
}
/**
* @brief Reset chip with chip reset
* @param None
* @return None
* @details This function reset chip with chip reset.
* The register write-protection function should be disabled before using this function.
*/
void SYS_ResetChip(void)
{
SYS->IPRST0 |= SYS_IPRST0_CHIPRST_Msk;
}
/**
* @brief Reset chip with CPU reset
* @param None
* @return None
* @details This function reset CPU with CPU reset.
* The register write-protection function should be disabled before using this function.
*/
void SYS_ResetCPU(void)
{
SYS->IPRST0 |= SYS_IPRST0_CPURST_Msk;
}
/**
* @brief Reset selected module
* @param[in] u32ModuleIndex is module index. Including :
* - \ref PDMA_RST
* - \ref EBI_RST
* - \ref EMAC_RST
* - \ref SDH0_RST
* - \ref CRC_RST
* - \ref HSUSBD_RST
* - \ref CRPT_RST
* - \ref SPIM_RST
* - \ref USBH_RST
* - \ref SDH1_RST
* - \ref GPIO_RST
* - \ref TMR0_RST
* - \ref TMR1_RST
* - \ref TMR2_RST
* - \ref TMR3_RST
* - \ref ACMP01_RST
* - \ref I2C0_RST
* - \ref I2C1_RST
* - \ref I2C2_RST
* - \ref SPI0_RST
* - \ref SPI1_RST
* - \ref SPI2_RST
* - \ref SPI3_RST
* - \ref UART0_RST
* - \ref UART1_RST
* - \ref UART2_RST
* - \ref UART3_RST
* - \ref UART4_RST
* - \ref UART5_RST
* - \ref CAN0_RST
* - \ref CAN1_RST
* - \ref USBD_RST
* - \ref EADC_RST
* - \ref I2S0_RST
* - \ref SC0_RST
* - \ref SC1_RST
* - \ref SC2_RST
* - \ref SPI4_RST
* - \ref USCI0_RST
* - \ref USCI1_RST
* - \ref DAC_RST
* - \ref EPWM0_RST
* - \ref EPWM1_RST
* - \ref BPWM0_RST
* - \ref BPWM1_RST
* - \ref QEI0_RST
* - \ref QEI1_RST
* - \ref ECAP0_RST
* - \ref ECAP1_RST
* - \ref OPA_RST
* @return None
* @details This function reset selected module.
*/
void SYS_ResetModule(uint32_t u32ModuleIndex)
{
uint32_t u32tmpVal = 0UL, u32tmpAddr = 0UL;
/* Generate reset signal to the corresponding module */
u32tmpVal = (1UL << (u32ModuleIndex & 0x00ffffffUL));
u32tmpAddr = (uint32_t)&SYS->IPRST0 + ((u32ModuleIndex >> 24UL));
*(uint32_t *)u32tmpAddr |= u32tmpVal;
/* Release corresponding module from reset state */
u32tmpVal = ~(1UL << (u32ModuleIndex & 0x00ffffffUL));
*(uint32_t *)u32tmpAddr &= u32tmpVal;
}
/**
* @brief Enable and configure Brown-out detector function
* @param[in] i32Mode is reset or interrupt mode. Including :
* - \ref SYS_BODCTL_BOD_RST_EN
* - \ref SYS_BODCTL_BOD_INTERRUPT_EN
* @param[in] u32BODLevel is Brown-out voltage level. Including :
* - \ref SYS_BODCTL_BODVL_3_0V
* - \ref SYS_BODCTL_BODVL_2_8V
* - \ref SYS_BODCTL_BODVL_2_6V
* - \ref SYS_BODCTL_BODVL_2_4V
* - \ref SYS_BODCTL_BODVL_2_2V
* - \ref SYS_BODCTL_BODVL_2_0V
* - \ref SYS_BODCTL_BODVL_1_8V
* - \ref SYS_BODCTL_BODVL_1_6V
* @return None
* @details This function configure Brown-out detector reset or interrupt mode, enable Brown-out function and set Brown-out voltage level.
* The register write-protection function should be disabled before using this function.
*/
void SYS_EnableBOD(int32_t i32Mode, uint32_t u32BODLevel)
{
/* Enable Brown-out Detector function */
SYS->BODCTL |= SYS_BODCTL_BODEN_Msk;
/* Enable Brown-out interrupt or reset function */
SYS->BODCTL = (SYS->BODCTL & ~SYS_BODCTL_BODRSTEN_Msk) | (uint32_t)i32Mode;
/* Select Brown-out Detector threshold voltage */
SYS->BODCTL = (SYS->BODCTL & ~SYS_BODCTL_BODVL_Msk) | u32BODLevel;
}
/**
* @brief Disable Brown-out detector function
* @param None
* @return None
* @details This function disable Brown-out detector function.
* The register write-protection function should be disabled before using this function.
*/
void SYS_DisableBOD(void)
{
SYS->BODCTL &= ~SYS_BODCTL_BODEN_Msk;
}
/*@}*/ /* end of group M480_SYS_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_SYS_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,351 @@
/**************************************************************************//**
* @file timer.c
* @brief M480 Timer Controller(Timer) driver source file
*
* @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_TIMER_Driver TIMER Driver
@{
*/
/** @addtogroup M480_TIMER_EXPORTED_FUNCTIONS TIMER Exported Functions
@{
*/
/**
* @brief Open Timer with Operate Mode and Frequency
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32Mode Operation mode. Possible options are
* - \ref TIMER_ONESHOT_MODE
* - \ref TIMER_PERIODIC_MODE
* - \ref TIMER_TOGGLE_MODE
* - \ref TIMER_CONTINUOUS_MODE
* @param[in] u32Freq Target working frequency
*
* @return Real timer working frequency
*
* @details This API is used to configure timer to operate in specified mode and frequency.
* If timer cannot work in target frequency, a closest frequency will be chose and returned.
* @note After calling this API, Timer is \b NOT running yet. But could start timer running be calling
* \ref TIMER_Start macro or program registers directly.
*/
uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq)
{
uint32_t u32Clk = TIMER_GetModuleClock(timer);
uint32_t u32Cmpr = 0UL, u32Prescale = 0UL;
/* Fastest possible timer working freq is (u32Clk / 2). While cmpr = 2, prescaler = 0. */
if(u32Freq > (u32Clk / 2UL)) {
u32Cmpr = 2UL;
} else {
if(u32Clk > 128000000UL) {
u32Prescale = 15UL; /* real prescaler value is 16 */
u32Clk >>= 4;
} else if(u32Clk > 64000000UL) {
u32Prescale = 7UL; /* real prescaler value is 8 */
u32Clk >>= 3;
} else if(u32Clk > 32000000UL) {
u32Prescale = 3UL; /* real prescaler value is 4 */
u32Clk >>= 2;
} else if(u32Clk > 16000000UL) {
u32Prescale = 1UL; /* real prescaler value is 2 */
u32Clk >>= 1;
}
u32Cmpr = u32Clk / u32Freq;
}
timer->CTL = u32Mode | u32Prescale;
timer->CMP = u32Cmpr;
return(u32Clk / (u32Cmpr * (u32Prescale + 1UL)));
}
/**
* @brief Stop Timer Counting
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This API stops timer counting and disable all timer interrupt function.
*/
void TIMER_Close(TIMER_T *timer)
{
timer->CTL = 0UL;
timer->EXTCTL = 0UL;
}
/**
* @brief Create a specify Delay Time
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32Usec Delay period in micro seconds. Valid values are between 100~1000000 (100 micro second ~ 1 second).
*
* @return None
*
* @details This API is used to create a delay loop for u32usec micro seconds by using timer one-shot mode.
* @note This API overwrites the register setting of the timer used to count the delay time.
* @note This API use polling mode. So there is no need to enable interrupt for the timer module used to generate delay.
*/
void TIMER_Delay(TIMER_T *timer, uint32_t u32Usec)
{
uint32_t u32Clk = TIMER_GetModuleClock(timer);
uint32_t u32Prescale = 0UL, delay = (SystemCoreClock / u32Clk) + 1UL;
uint32_t u32Cmpr, u32NsecPerTick;
/* Clear current timer configuration */
timer->CTL = 0UL;
timer->EXTCTL = 0UL;
if(u32Clk <= 1000000UL) { /* min delay is 1000 us if timer clock source is <= 1 MHz */
if(u32Usec < 1000UL) {
u32Usec = 1000UL;
}
if(u32Usec > 1000000UL) {
u32Usec = 1000000UL;
}
} else {
if(u32Usec < 100UL) {
u32Usec = 100UL;
}
if(u32Usec > 1000000UL) {
u32Usec = 1000000UL;
}
}
if(u32Clk <= 1000000UL) {
u32Prescale = 0UL;
u32NsecPerTick = 1000000000UL / u32Clk;
u32Cmpr = (u32Usec * 1000UL) / u32NsecPerTick;
} else {
if(u32Clk > 128000000UL) {
u32Prescale = 15UL; /* real prescaler value is 16 */
u32Clk >>= 4;
} else if(u32Clk > 64000000UL) {
u32Prescale = 7UL; /* real prescaler value is 8 */
u32Clk >>= 3;
} else if(u32Clk > 32000000UL) {
u32Prescale = 3UL; /* real prescaler value is 4 */
u32Clk >>= 2;
} else if(u32Clk > 16000000UL) {
u32Prescale = 1UL; /* real prescaler value is 2 */
u32Clk >>= 1;
}
if(u32Usec < 250UL) {
u32Cmpr = (u32Usec * u32Clk) / 1000000UL;
} else {
u32NsecPerTick = 1000000000UL / u32Clk;
u32Cmpr = (u32Usec * 1000UL) / u32NsecPerTick;
}
}
timer->CMP = u32Cmpr;
timer->CTL = TIMER_CTL_CNTEN_Msk | TIMER_ONESHOT_MODE | u32Prescale;
/* When system clock is faster than timer clock, it is possible timer active bit cannot set in time while we check it.
And the while loop below return immediately, so put a tiny delay here allowing timer start counting and raise active flag. */
for(; delay > 0UL; delay--) {
__NOP();
}
while(timer->CTL & TIMER_CTL_ACTSTS_Msk) {
;
}
}
/**
* @brief Enable Timer Capture Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32CapMode Timer capture mode. Could be
* - \ref TIMER_CAPTURE_FREE_COUNTING_MODE
* - \ref TIMER_CAPTURE_COUNTER_RESET_MODE
* @param[in] u32Edge Timer capture trigger edge. Possible values are
* - \ref TIMER_CAPTURE_EVENT_FALLING
* - \ref TIMER_CAPTURE_EVENT_RISING
* - \ref TIMER_CAPTURE_EVENT_FALLING_RISING
* - \ref TIMER_CAPTURE_EVENT_RISING_FALLING
*
* @return None
*
* @details This API is used to enable timer capture function with specify capture trigger edge \n
* to get current counter value or reset counter value to 0.
* @note Timer frequency should be configured separately by using \ref TIMER_Open API, or program registers directly.
*/
void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge)
{
timer->EXTCTL = (timer->EXTCTL & ~(TIMER_EXTCTL_CAPFUNCS_Msk | TIMER_EXTCTL_CAPEDGE_Msk)) |
u32CapMode | u32Edge | TIMER_EXTCTL_CAPEN_Msk;
}
/**
* @brief Disable Timer Capture Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This API is used to disable the timer capture function.
*/
void TIMER_DisableCapture(TIMER_T *timer)
{
timer->EXTCTL &= ~TIMER_EXTCTL_CAPEN_Msk;
}
/**
* @brief Enable Timer Counter Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32Edge Detection edge of counter pin. Could be ether
* - \ref TIMER_COUNTER_EVENT_FALLING, or
* - \ref TIMER_COUNTER_EVENT_RISING
*
* @return None
*
* @details This function is used to enable the timer counter function with specify detection edge.
* @note Timer compare value should be configured separately by using \ref TIMER_SET_CMP_VALUE macro or program registers directly.
* @note While using event counter function, \ref TIMER_TOGGLE_MODE cannot set as timer operation mode.
*/
void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge)
{
timer->EXTCTL = (timer->EXTCTL & ~TIMER_EXTCTL_CNTPHASE_Msk) | u32Edge;
timer->CTL |= TIMER_CTL_EXTCNTEN_Msk;
}
/**
* @brief Disable Timer Counter Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This API is used to disable the timer event counter function.
*/
void TIMER_DisableEventCounter(TIMER_T *timer)
{
timer->CTL &= ~TIMER_CTL_EXTCNTEN_Msk;
}
/**
* @brief Get Timer Clock Frequency
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return Timer clock frequency
*
* @details This API is used to get the timer clock frequency.
* @note This API cannot return correct clock rate if timer source is from external clock input.
*/
uint32_t TIMER_GetModuleClock(TIMER_T *timer)
{
uint32_t u32Src, u32Clk;
const uint32_t au32Clk[] = {__HXT, __LXT, 0UL, 0UL, 0UL, __LIRC, 0UL, __HIRC};
if(timer == TIMER0) {
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR0SEL_Msk) >> CLK_CLKSEL1_TMR0SEL_Pos;
} else if(timer == TIMER1) {
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1SEL_Msk) >> CLK_CLKSEL1_TMR1SEL_Pos;
} else if(timer == TIMER2) {
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR2SEL_Msk) >> CLK_CLKSEL1_TMR2SEL_Pos;
} else { /* Timer 3 */
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR3SEL_Msk) >> CLK_CLKSEL1_TMR3SEL_Pos;
}
if(u32Src == 2UL) {
if((timer == TIMER0) || (timer == TIMER1)) {
u32Clk = CLK_GetPCLK0Freq();
} else {
u32Clk = CLK_GetPCLK1Freq();
}
} else {
u32Clk = au32Clk[u32Src];
}
return u32Clk;
}
/**
* @brief This function is used to enable the Timer frequency counter function
* @param[in] timer The base address of Timer module. Can be \ref TIMER0 or \ref TIMER2
* @param[in] u32DropCount This parameter has no effect in M480 series BSP
* @param[in] u32Timeout This parameter has no effect in M480 series BSP
* @param[in] u32EnableInt Enable interrupt assertion after capture complete or not. Valid values are TRUE and FALSE
* @return None
* @details This function is used to calculate input event frequency. After enable
* this function, a pair of timers, TIMER0 and TIMER1, or TIMER2 and TIMER3
* will be configured for this function. The mode used to calculate input
* event frequency is mentioned as "Inter Timer Trigger Mode" in Technical
* Reference Manual
*/
void TIMER_EnableFreqCounter(TIMER_T *timer,
uint32_t u32DropCount,
uint32_t u32Timeout,
uint32_t u32EnableInt)
{
TIMER_T *t; /* store the timer base to configure compare value */
t = (timer == TIMER0) ? TIMER1 : TIMER3;
t->CMP = 0xFFFFFFUL;
t->EXTCTL = u32EnableInt ? TIMER_EXTCTL_CAPIEN_Msk : 0UL;
timer->CTL = TIMER_CTL_INTRGEN_Msk | TIMER_CTL_CNTEN_Msk;
return;
}
/**
* @brief This function is used to disable the Timer frequency counter function.
* @param[in] timer The base address of Timer module
* @return None
*/
void TIMER_DisableFreqCounter(TIMER_T *timer)
{
timer->CTL &= ~TIMER_CTL_INTRGEN_Msk;
}
/**
* @brief This function is used to select the interrupt source used to trigger other modules.
* @param[in] timer The base address of Timer module
* @param[in] u32Src Selects the interrupt source to trigger other modules. Could be:
* - \ref TIMER_TRGSRC_TIMEOUT_EVENT
* - \ref TIMER_TRGSRC_CAPTURE_EVENT
* @return None
*/
void TIMER_SetTriggerSource(TIMER_T *timer, uint32_t u32Src)
{
timer->TRGCTL = (timer->TRGCTL & ~TIMER_TRGCTL_TRGSSEL_Msk) | u32Src;
}
/**
* @brief This function is used to set modules trigger by timer interrupt
* @param[in] timer The base address of Timer module
* @param[in] u32Mask The mask of modules (EPWM, EADC, DAC and PDMA) trigger by timer. Is the combination of
* - \ref TIMER_TRG_TO_EPWM,
* - \ref TIMER_TRG_TO_EADC,
* - \ref TIMER_TRG_TO_DAC, and
* - \ref TIMER_TRG_TO_PDMA
* @return None
*/
void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask)
{
timer->TRGCTL = (timer->TRGCTL & ~(TIMER_TRGCTL_TRGEPWM_Msk | TIMER_TRGCTL_TRGDAC_Msk | TIMER_TRGCTL_TRGEADC_Msk | TIMER_TRGCTL_TRGPDMA_Msk)) | u32Mask;
}
/*@}*/ /* end of group M480_TIMER_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_TIMER_Driver */
/*@}*/ /* end of group M480_Device_Driver */

View File

@ -0,0 +1,506 @@
/**************************************************************************//**
* @file timer.h
* @version V1.00
* @brief M480 series Timer Controller(Timer) driver header file
*
* @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __TIMER_H__
#define __TIMER_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_TIMER_Driver TIMER Driver
@{
*/
/** @addtogroup M480_TIMER_EXPORTED_CONSTANTS TIMER Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* TIMER Operation Mode, External Counter and Capture Mode Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TIMER_ONESHOT_MODE (0UL << TIMER_CTL_OPMODE_Pos) /*!< Timer working in one-shot mode \hideinitializer */
#define TIMER_PERIODIC_MODE (1UL << TIMER_CTL_OPMODE_Pos) /*!< Timer working in periodic mode \hideinitializer */
#define TIMER_TOGGLE_MODE (2UL << TIMER_CTL_OPMODE_Pos) /*!< Timer working in toggle-output mode \hideinitializer */
#define TIMER_CONTINUOUS_MODE (3UL << TIMER_CTL_OPMODE_Pos) /*!< Timer working in continuous counting mode \hideinitializer */
#define TIMER_TOUT_PIN_FROM_TMX (0UL << TIMER_CTL_TGLPINSEL_Pos) /*!< Timer toggle-output pin is from TMx pin \hideinitializer */
#define TIMER_TOUT_PIN_FROM_TMX_EXT (1UL << TIMER_CTL_TGLPINSEL_Pos) /*!< Timer toggle-output pin is from TMx_EXT pin \hideinitializer */
#define TIMER_COUNTER_EVENT_FALLING (0UL << TIMER_EXTCTL_CNTPHASE_Pos) /*!< Counter increase on falling edge detection \hideinitializer */
#define TIMER_COUNTER_EVENT_RISING (1UL << TIMER_EXTCTL_CNTPHASE_Pos) /*!< Counter increase on rising edge detection \hideinitializer */
#define TIMER_CAPTURE_FREE_COUNTING_MODE (0UL << TIMER_EXTCTL_CAPFUNCS_Pos) /*!< Timer capture event to get timer counter value \hideinitializer */
#define TIMER_CAPTURE_COUNTER_RESET_MODE (1UL << TIMER_EXTCTL_CAPFUNCS_Pos) /*!< Timer capture event to reset timer counter \hideinitializer */
#define TIMER_CAPTURE_EVENT_FALLING (0UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< Falling edge detection to trigger capture event \hideinitializer */
#define TIMER_CAPTURE_EVENT_RISING (1UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< Rising edge detection to trigger capture event \hideinitializer */
#define TIMER_CAPTURE_EVENT_FALLING_RISING (2UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< Both falling and rising edge detection to trigger capture event, and first event at falling edge \hideinitializer */
#define TIMER_CAPTURE_EVENT_RISING_FALLING (3UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< Both rising and falling edge detection to trigger capture event, and first event at rising edge \hideinitializer */
#define TIMER_CAPTURE_EVENT_GET_LOW_PERIOD (6UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< First capture event is at falling edge, follows are at at rising edge \hideinitializer */
#define TIMER_CAPTURE_EVENT_GET_HIGH_PERIOD (7UL << TIMER_EXTCTL_CAPEDGE_Pos) /*!< First capture event is at rising edge, follows are at at falling edge \hideinitializer */
#define TIMER_TRGSRC_TIMEOUT_EVENT (0UL << TIMER_TRGCTL_TRGSSEL_Pos) /*!< Select internal trigger source from timer time-out event \hideinitializer */
#define TIMER_TRGSRC_CAPTURE_EVENT (1UL << TIMER_TRGCTL_TRGSSEL_Pos) /*!< Select internal trigger source from timer capture event \hideinitializer */
#define TIMER_TRG_TO_EPWM (TIMER_TRGCTL_TRGEPWM_Msk) /*!< Each timer event as EPWM counter clock source \hideinitializer */
#define TIMER_TRG_TO_EADC (TIMER_TRGCTL_TRGEADC_Msk) /*!< Each timer event to start ADC conversion \hideinitializer */
#define TIMER_TRG_TO_DAC (TIMER_TRGCTL_TRGDAC_Msk) /*!< Each timer event to start DAC conversion \hideinitializer */
#define TIMER_TRG_TO_PDMA (TIMER_TRGCTL_TRGPDMA_Msk) /*!< Each timer event to trigger PDMA transfer \hideinitializer */
/*@}*/ /* end of group M480_TIMER_EXPORTED_CONSTANTS */
/** @addtogroup M480_TIMER_EXPORTED_FUNCTIONS TIMER Exported Functions
@{
*/
/**
* @brief Set Timer Compared Value
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32Value Timer compare value. Valid values are between 2 to 0xFFFFFF.
*
* @return None
*
* @details This macro is used to set timer compared value to adjust timer time-out interval.
* @note 1. Never write 0x0 or 0x1 in this field, or the core will run into unknown state. \n
* 2. If update timer compared value in continuous counting mode, timer counter value will keep counting continuously. \n
* But if timer is operating at other modes, the timer up counter will restart counting and start from 0.
* \hideinitializer
*/
#define TIMER_SET_CMP_VALUE(timer, u32Value) ((timer)->CMP = (u32Value))
/**
* @brief Set Timer Prescale Value
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32Value Timer prescale value. Valid values are between 0 to 0xFF.
*
* @return None
*
* @details This macro is used to set timer prescale value and timer source clock will be divided by (prescale + 1) \n
* before it is fed into timer.
* \hideinitializer
*/
#define TIMER_SET_PRESCALE_VALUE(timer, u32Value) ((timer)->CTL = ((timer)->CTL & ~TIMER_CTL_PSC_Msk) | (u32Value))
/**
* @brief Check specify Timer Status
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @retval 0 Timer 24-bit up counter is inactive
* @retval 1 Timer 24-bit up counter is active
*
* @details This macro is used to check if specify Timer counter is inactive or active.
* \hideinitializer
*/
#define TIMER_IS_ACTIVE(timer) (((timer)->CTL & TIMER_CTL_ACTSTS_Msk)? 1 : 0)
/**
* @brief Select Toggle-output Pin
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32ToutSel Toggle-output pin selection, valid values are:
* - \ref TIMER_TOUT_PIN_FROM_TMX
* - \ref TIMER_TOUT_PIN_FROM_TMX_EXT
*
* @return None
*
* @details This macro is used to select timer toggle-output pin is output on TMx or TMx_EXT pin.
* \hideinitializer
*/
#define TIMER_SELECT_TOUT_PIN(timer, u32ToutSel) ((timer)->CTL = ((timer)->CTL & ~TIMER_CTL_TGLPINSEL_Msk) | (u32ToutSel))
/* Declare these inline functions here to avoid MISRA C 2004 rule 8.1 error */
static __INLINE void TIMER_Start(TIMER_T *timer);
static __INLINE void TIMER_Stop(TIMER_T *timer);
static __INLINE void TIMER_EnableWakeup(TIMER_T *timer);
static __INLINE void TIMER_DisableWakeup(TIMER_T *timer);
static __INLINE void TIMER_StartCapture(TIMER_T *timer);
static __INLINE void TIMER_StopCapture(TIMER_T *timer);
static __INLINE void TIMER_EnableCaptureDebounce(TIMER_T *timer);
static __INLINE void TIMER_DisableCaptureDebounce(TIMER_T *timer);
static __INLINE void TIMER_EnableEventCounterDebounce(TIMER_T *timer);
static __INLINE void TIMER_DisableEventCounterDebounce(TIMER_T *timer);
static __INLINE void TIMER_EnableInt(TIMER_T *timer);
static __INLINE void TIMER_DisableInt(TIMER_T *timer);
static __INLINE void TIMER_EnableCaptureInt(TIMER_T *timer);
static __INLINE void TIMER_DisableCaptureInt(TIMER_T *timer);
static __INLINE uint32_t TIMER_GetIntFlag(TIMER_T *timer);
static __INLINE void TIMER_ClearIntFlag(TIMER_T *timer);
static __INLINE uint32_t TIMER_GetCaptureIntFlag(TIMER_T *timer);
static __INLINE void TIMER_ClearCaptureIntFlag(TIMER_T *timer);
static __INLINE uint32_t TIMER_GetWakeupFlag(TIMER_T *timer);
static __INLINE void TIMER_ClearWakeupFlag(TIMER_T *timer);
static __INLINE uint32_t TIMER_GetCaptureData(TIMER_T *timer);
static __INLINE uint32_t TIMER_GetCounter(TIMER_T *timer);
static __INLINE void TIMER_ResetCounter(TIMER_T *timer);
/**
* @brief Start Timer Counting
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to start Timer counting.
*/
static __INLINE void TIMER_Start(TIMER_T *timer)
{
timer->CTL |= TIMER_CTL_CNTEN_Msk;
}
/**
* @brief Stop Timer Counting
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to stop/suspend Timer counting.
*/
static __INLINE void TIMER_Stop(TIMER_T *timer)
{
timer->CTL &= ~TIMER_CTL_CNTEN_Msk;
}
/**
* @brief Enable Timer Interrupt Wake-up Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to enable the timer interrupt wake-up function and interrupt source could be time-out interrupt, \n
* counter event interrupt or capture trigger interrupt.
* @note To wake the system from Power-down mode, timer clock source must be ether LXT or LIRC.
*/
static __INLINE void TIMER_EnableWakeup(TIMER_T *timer)
{
timer->CTL |= TIMER_CTL_WKEN_Msk;
}
/**
* @brief Disable Timer Wake-up Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to disable the timer interrupt wake-up function.
*/
static __INLINE void TIMER_DisableWakeup(TIMER_T *timer)
{
timer->CTL &= ~TIMER_CTL_WKEN_Msk;
}
/**
* @brief Start Timer Capture Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to start Timer capture function.
*/
static __INLINE void TIMER_StartCapture(TIMER_T *timer)
{
timer->EXTCTL |= TIMER_EXTCTL_CAPEN_Msk;
}
/**
* @brief Stop Timer Capture Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to stop Timer capture function.
*/
static __INLINE void TIMER_StopCapture(TIMER_T *timer)
{
timer->EXTCTL &= ~TIMER_EXTCTL_CAPEN_Msk;
}
/**
* @brief Enable Capture Pin De-bounce
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to enable the detect de-bounce function of capture pin.
*/
static __INLINE void TIMER_EnableCaptureDebounce(TIMER_T *timer)
{
timer->EXTCTL |= TIMER_EXTCTL_CAPDBEN_Msk;
}
/**
* @brief Disable Capture Pin De-bounce
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to disable the detect de-bounce function of capture pin.
*/
static __INLINE void TIMER_DisableCaptureDebounce(TIMER_T *timer)
{
timer->EXTCTL &= ~TIMER_EXTCTL_CAPDBEN_Msk;
}
/**
* @brief Enable Counter Pin De-bounce
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to enable the detect de-bounce function of counter pin.
*/
static __INLINE void TIMER_EnableEventCounterDebounce(TIMER_T *timer)
{
timer->EXTCTL |= TIMER_EXTCTL_CNTDBEN_Msk;
}
/**
* @brief Disable Counter Pin De-bounce
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to disable the detect de-bounce function of counter pin.
*/
static __INLINE void TIMER_DisableEventCounterDebounce(TIMER_T *timer)
{
timer->EXTCTL &= ~TIMER_EXTCTL_CNTDBEN_Msk;
}
/**
* @brief Enable Timer Time-out Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to enable the timer time-out interrupt function.
*/
static __INLINE void TIMER_EnableInt(TIMER_T *timer)
{
timer->CTL |= TIMER_CTL_INTEN_Msk;
}
/**
* @brief Disable Timer Time-out Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to disable the timer time-out interrupt function.
*/
static __INLINE void TIMER_DisableInt(TIMER_T *timer)
{
timer->CTL &= ~TIMER_CTL_INTEN_Msk;
}
/**
* @brief Enable Capture Trigger Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to enable the timer capture trigger interrupt function.
*/
static __INLINE void TIMER_EnableCaptureInt(TIMER_T *timer)
{
timer->EXTCTL |= TIMER_EXTCTL_CAPIEN_Msk;
}
/**
* @brief Disable Capture Trigger Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to disable the timer capture trigger interrupt function.
*/
static __INLINE void TIMER_DisableCaptureInt(TIMER_T *timer)
{
timer->EXTCTL &= ~TIMER_EXTCTL_CAPIEN_Msk;
}
/**
* @brief Get Timer Time-out Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @retval 0 Timer time-out interrupt did not occur
* @retval 1 Timer time-out interrupt occurred
*
* @details This function indicates timer time-out interrupt occurred or not.
*/
static __INLINE uint32_t TIMER_GetIntFlag(TIMER_T *timer)
{
return ((timer->INTSTS & TIMER_INTSTS_TIF_Msk) ? 1UL : 0UL);
}
/**
* @brief Clear Timer Time-out Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function clears timer time-out interrupt flag to 0.
*/
static __INLINE void TIMER_ClearIntFlag(TIMER_T *timer)
{
timer->INTSTS = TIMER_INTSTS_TIF_Msk;
}
/**
* @brief Get Timer Capture Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @retval 0 Timer capture interrupt did not occur
* @retval 1 Timer capture interrupt occurred
*
* @details This function indicates timer capture trigger interrupt occurred or not.
*/
static __INLINE uint32_t TIMER_GetCaptureIntFlag(TIMER_T *timer)
{
return timer->EINTSTS;
}
/**
* @brief Clear Timer Capture Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function clears timer capture trigger interrupt flag to 0.
*/
static __INLINE void TIMER_ClearCaptureIntFlag(TIMER_T *timer)
{
timer->EINTSTS = TIMER_EINTSTS_CAPIF_Msk;
}
/**
* @brief Get Timer Wake-up Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @retval 0 Timer does not cause CPU wake-up
* @retval 1 Timer interrupt event cause CPU wake-up
*
* @details This function indicates timer interrupt event has waked up system or not.
*/
static __INLINE uint32_t TIMER_GetWakeupFlag(TIMER_T *timer)
{
return (timer->INTSTS & TIMER_INTSTS_TWKF_Msk ? 1UL : 0UL);
}
/**
* @brief Clear Timer Wake-up Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function clears the timer wake-up system flag to 0.
*/
static __INLINE void TIMER_ClearWakeupFlag(TIMER_T *timer)
{
timer->INTSTS = TIMER_INTSTS_TWKF_Msk;
}
/**
* @brief Get Capture value
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return 24-bit Capture Value
*
* @details This function reports the current 24-bit timer capture value.
*/
static __INLINE uint32_t TIMER_GetCaptureData(TIMER_T *timer)
{
return timer->CAP;
}
/**
* @brief Get Counter value
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return 24-bit Counter Value
*
* @details This function reports the current 24-bit timer counter value.
*/
static __INLINE uint32_t TIMER_GetCounter(TIMER_T *timer)
{
return timer->CNT;
}
/**
* @brief Reset Counter
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to reset current counter value and internal prescale counter value.
*/
static __INLINE void TIMER_ResetCounter(TIMER_T *timer)
{
timer->CNT = 0UL;
while((timer->CNT&TIMER_CNT_RSTACT_Msk) == TIMER_CNT_RSTACT_Msk) {
;
}
}
uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq);
void TIMER_Close(TIMER_T *timer);
void TIMER_Delay(TIMER_T *timer, uint32_t u32Usec);
void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge);
void TIMER_DisableCapture(TIMER_T *timer);
void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge);
void TIMER_DisableEventCounter(TIMER_T *timer);
uint32_t TIMER_GetModuleClock(TIMER_T *timer);
void TIMER_EnableFreqCounter(TIMER_T *timer,
uint32_t u32DropCount,
uint32_t u32Timeout,
uint32_t u32EnableInt);
void TIMER_DisableFreqCounter(TIMER_T *timer);
void TIMER_SetTriggerSource(TIMER_T *timer, uint32_t u32Src);
void TIMER_SetTriggerTarget(TIMER_T *timer, uint32_t u32Mask);
/*@}*/ /* end of group M480_TIMER_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_TIMER_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __TIMER_H__ */

View File

@ -0,0 +1,434 @@
/**************************************************************************//**
* @file timer.c
* @brief M480 Timer PWM Controller(Timer PWM) driver source file
*
* @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_TIMER_PWM_Driver TIMER PWM Driver
@{
*/
/** @addtogroup M480_TIMER_PWM_EXPORTED_FUNCTIONS TIMER PWM Exported Functions
@{
*/
/**
* @brief Set PWM Counter Clock Source
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32CntClkSrc PWM counter clock source, could be one of following source
* - \ref TPWM_CNTR_CLKSRC_TMR_CLK
* - \ref TPWM_CNTR_CLKSRC_TIMER0_INT
* - \ref TPWM_CNTR_CLKSRC_TIMER1_INT
* - \ref TPWM_CNTR_CLKSRC_TIMER2_INT
* - \ref TPWM_CNTR_CLKSRC_TIMER3_INT
*
* @return None
*
* @details This function is used to set PWM counter clock source.
*/
void TPWM_SetCounterClockSource(TIMER_T *timer, uint32_t u32CntClkSrc)
{
(timer)->PWMCLKSRC = ((timer)->PWMCLKSRC & ~TIMER_PWMCLKSRC_CLKSRC_Msk) | u32CntClkSrc;
}
/**
* @brief Configure PWM Output Frequency and Duty Cycle
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32Frequency Target generator frequency.
* @param[in] u32DutyCycle Target generator duty cycle percentage. Valid range are between 0~100. 10 means 10%, 20 means 20%...
*
* @return Nearest frequency clock in nano second
*
* @details This API is used to configure PWM output frequency and duty cycle in up count type and auto-reload operation mode.
* @note This API is only available if Timer PWM counter clock source is from TMRx_CLK.
*/
uint32_t TPWM_ConfigOutputFreqAndDuty(TIMER_T *timer, uint32_t u32Frequency, uint32_t u32DutyCycle)
{
uint32_t u32PWMClockFreq, u32TargetFreq;
uint32_t u32Prescaler = 0x1000UL, u32Period, u32CMP;
if((timer == TIMER0) || (timer == TIMER1)) {
u32PWMClockFreq = CLK_GetPCLK0Freq();
} else {
u32PWMClockFreq = CLK_GetPCLK1Freq();
}
/* Calculate u16PERIOD and u16PSC */
for(u32Prescaler = 1UL; u32Prescaler <= 0x1000UL; u32Prescaler++) {
u32Period = (u32PWMClockFreq / u32Prescaler) / u32Frequency;
/* If target u32Period is larger than 0x10000, need to use a larger prescaler */
if(u32Period <= 0x10000UL) {
break;
}
}
/* Store return value here 'cos we're gonna change u32Prescaler & u32Period to the real value to fill into register */
u32TargetFreq = (u32PWMClockFreq / u32Prescaler) / u32Period;
/* Set PWM to up count type */
timer->PWMCTL = (timer->PWMCTL & ~TIMER_PWMCTL_CNTTYPE_Msk) | (TPWM_UP_COUNT << TIMER_PWMCTL_CNTTYPE_Pos);
/* Set PWM to auto-reload mode */
timer->PWMCTL = (timer->PWMCTL & ~TIMER_PWMCTL_CNTMODE_Msk) | TPWM_AUTO_RELOAD_MODE;
/* Convert to real register value */
TPWM_SET_PRESCALER(timer, (u32Prescaler - 1UL));
TPWM_SET_PERIOD(timer, (u32Period - 1UL));
if(u32DutyCycle) {
u32CMP = (u32DutyCycle * u32Period) / 100UL;
} else {
u32CMP = 0UL;
}
TPWM_SET_CMPDAT(timer, u32CMP);
return (u32TargetFreq);
}
/**
* @brief Enable Dead-Time Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32DTCount Dead-Time duration in PWM clock count, valid values are between 0x0~0xFFF, but 0x0 means there is no Dead-Time insertion.
*
* @return None
*
* @details This function is used to enable Dead-Time function and counter source is the same as Timer PWM clock source.
* @note The register write-protection function should be disabled before using this function.
*/
void TPWM_EnableDeadTime(TIMER_T *timer, uint32_t u32DTCount)
{
timer->PWMDTCTL = TIMER_PWMDTCTL_DTEN_Msk | u32DTCount;
}
/**
* @brief Enable Dead-Time Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32DTCount Dead-Time duration in PWM clock count, valid values are between 0x0~0xFFF, but 0x0 means there is no Dead-Time insertion.
*
* @return None
*
* @details This function is used to enable Dead-Time function and counter source is the Timer PWM clock source with prescale.
* @note The register write-protection function should be disabled before using this function.
*/
void TPWM_EnableDeadTimeWithPrescale(TIMER_T *timer, uint32_t u32DTCount)
{
timer->PWMDTCTL = TIMER_PWMDTCTL_DTCKSEL_Msk | TIMER_PWMDTCTL_DTEN_Msk | u32DTCount;
}
/**
* @brief Disable Dead-Time Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to enable Dead-time of selected channel.
* @note The register write-protection function should be disabled before using this function.
*/
void TPWM_DisableDeadTime(TIMER_T *timer)
{
timer->PWMDTCTL = 0x0UL;
}
/**
* @brief Enable PWM Counter
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to enable PWM generator and start counter counting.
*/
void TPWM_EnableCounter(TIMER_T *timer)
{
timer->PWMCTL |= TIMER_PWMCTL_CNTEN_Msk;
}
/**
* @brief Disable PWM Generator
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to disable PWM counter immediately by clear CNTEN (TIMERx_PWMCTL[0]) bit.
*/
void TPWM_DisableCounter(TIMER_T *timer)
{
timer->PWMCTL &= ~TIMER_PWMCTL_CNTEN_Msk;
}
/**
* @brief Enable Trigger EADC
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32Condition The condition to trigger EADC. It could be one of following conditions:
* - \ref TPWM_TRIGGER_EADC_AT_ZERO_POINT
* - \ref TPWM_TRIGGER_EADC_AT_PERIOD_POINT
* - \ref TPWM_TRIGGER_EADC_AT_ZERO_OR_PERIOD_POINT
* - \ref TPWM_TRIGGER_EADC_AT_COMPARE_UP_COUNT_POINT
* - \ref TPWM_TRIGGER_EADC_AT_COMPARE_DOWN_COUNT_POINT
*
* @return None
*
* @details This function is used to enable specified counter compare event to trigger EADC.
*/
void TPWM_EnableTriggerEADC(TIMER_T *timer, uint32_t u32Condition)
{
timer->PWMEADCTS = TIMER_PWMEADCTS_TRGEN_Msk | u32Condition;
}
/**
* @brief Disable Trigger EADC
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to disable counter compare event to trigger EADC.
*/
void TPWM_DisableTriggerEADC(TIMER_T *timer)
{
timer->PWMEADCTS = 0x0UL;
}
/**
* @brief Enable Fault Brake Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32CH0Level PWMx_CH0 output level while fault brake event occurs. Valid value is one of following setting
* - \ref TPWM_OUTPUT_TOGGLE
* - \ref TPWM_OUTPUT_NOTHING
* - \ref TPWM_OUTPUT_LOW
* - \ref TPWM_OUTPUT_HIGH
* @param[in] u32CH1Level PWMx_CH1 output level while fault brake event occurs. Valid value is one of following setting
* - \ref TPWM_OUTPUT_TOGGLE
* - \ref TPWM_OUTPUT_NOTHING
* - \ref TPWM_OUTPUT_LOW
* - \ref TPWM_OUTPUT_HIGH
* @param[in] u32BrakeSource Fault brake source, combination of following source
* - \ref TPWM_BRAKE_SOURCE_EDGE_ACMP0
* - \ref TPWM_BRAKE_SOURCE_EDGE_ACMP1
* - \ref TPWM_BRAKE_SOURCE_EDGE_BKPIN
* - \ref TPWM_BRAKE_SOURCE_EDGE_SYS_CSS
* - \ref TPWM_BRAKE_SOURCE_EDGE_SYS_BOD
* - \ref TPWM_BRAKE_SOURCE_EDGE_SYS_COR
* - \ref TPWM_BRAKE_SOURCE_EDGE_SYS_RAM
* - \ref TPWM_BRAKE_SOURCE_LEVEL_ACMP0
* - \ref TPWM_BRAKE_SOURCE_LEVEL_ACMP1
* - \ref TPWM_BRAKE_SOURCE_LEVEL_BKPIN
* - \ref TPWM_BRAKE_SOURCE_LEVEL_SYS_CSS
* - \ref TPWM_BRAKE_SOURCE_LEVEL_SYS_BOD
* - \ref TPWM_BRAKE_SOURCE_LEVEL_SYS_COR
* - \ref TPWM_BRAKE_SOURCE_LEVEL_SYS_RAM
*
* @return None
*
* @details This function is used to enable fault brake function.
* @note The register write-protection function should be disabled before using this function.
*/
void TPWM_EnableFaultBrake(TIMER_T *timer, uint32_t u32CH0Level, uint32_t u32CH1Level, uint32_t u32BrakeSource)
{
timer->PWMFAILBRK |= ((u32BrakeSource >> 16) & 0xFUL);
timer->PWMBRKCTL = (timer->PWMBRKCTL & ~(TIMER_PWMBRKCTL_BRKAEVEN_Msk | TIMER_PWMBRKCTL_BRKAODD_Msk)) |
(u32BrakeSource & 0xFFFFUL) | (u32CH0Level << TIMER_PWMBRKCTL_BRKAEVEN_Pos) | (u32CH1Level << TIMER_PWMBRKCTL_BRKAODD_Pos);
}
/**
* @brief Enable Fault Brake Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32IntSource Interrupt source, could be one of following source
* - \ref TPWM_BRAKE_EDGE
* - \ref TPWM_BRAKE_LEVEL
*
* @return None
*
* @details This function is used to enable fault brake interrupt.
* @note The register write-protection function should be disabled before using this function.
*/
void TPWM_EnableFaultBrakeInt(TIMER_T *timer, uint32_t u32IntSource)
{
timer->PWMINTEN1 |= u32IntSource;
}
/**
* @brief Disable Fault Brake Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32IntSource Interrupt source, could be one of following source
* - \ref TPWM_BRAKE_EDGE
* - \ref TPWM_BRAKE_LEVEL
*
* @return None
*
* @details This function is used to disable fault brake interrupt.
* @note The register write-protection function should be disabled before using this function.
*/
void TPWM_DisableFaultBrakeInt(TIMER_T *timer, uint32_t u32IntSource)
{
timer->PWMINTEN1 &= ~u32IntSource;
}
/**
* @brief Indicate Fault Brake Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32IntSource Interrupt source, could be one of following source
* - \ref TPWM_BRAKE_EDGE
* - \ref TPWM_BRAKE_LEVEL
*
* @return Fault brake interrupt flag of specified source
* @retval 0 Fault brake interrupt did not occurred
* @retval 1 Fault brake interrupt occurred
*
* @details This function is used to indicate fault brake interrupt flag occurred or not of selected source.
*/
uint32_t TPWM_GetFaultBrakeIntFlag(TIMER_T *timer, uint32_t u32IntSource)
{
return ((timer->PWMINTSTS1 & (0x3UL << u32IntSource))? 1UL : 0UL);
}
/**
* @brief Clear Fault Brake Interrupt Flags
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32IntSource Interrupt source, could be one of following source
* - \ref TPWM_BRAKE_EDGE
* - \ref TPWM_BRAKE_LEVEL
*
* @return None
*
* @details This function is used to clear fault brake interrupt flags of selected source.
* @note The register write-protection function should be disabled before using this function.
*/
void TPWM_ClearFaultBrakeIntFlag(TIMER_T *timer, uint32_t u32IntSource)
{
timer->PWMINTSTS1 = (0x3UL << u32IntSource);
}
/**
* @brief Enable load mode of selected channel
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32LoadMode Timer PWM counter loading mode, could be one of following mode
* - \ref TPWM_LOAD_MODE_PERIOD
* - \ref TPWM_LOAD_MODE_IMMEDIATE
* - \ref TPWM_LOAD_MODE_CENTER
*
* @return None
*
* @details This function is used to enable load mode of selected channel.
* @note The default loading mode is period loading mode.
*/
void TPWM_SetLoadMode(TIMER_T *timer, uint32_t u32LoadMode)
{
timer->PWMCTL = (timer->PWMCTL & ~(TIMER_PWMCTL_IMMLDEN_Msk | TIMER_PWMCTL_CTRLD_Msk)) | u32LoadMode;
}
/**
* @brief Enable brake pin noise filter function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32BrakePinSrc The external brake pin source, could be one of following source
* - \ref TPWM_TM_BRAKE0
* - \ref TPWM_TM_BRAKE1
* - \ref TPWM_TM_BRAKE2
* - \ref TPWM_TM_BRAKE3
* @param[in] u32DebounceCnt This value controls the real debounce sample time.
* The target debounce sample time is (debounce sample clock period) * (u32DebounceCnt).
* @param[in] u32ClkSrcSel Brake pin detector debounce clock source, could be one of following source
* - \ref TPWM_BKP_DBCLK_PCLK_DIV_1
* - \ref TPWM_BKP_DBCLK_PCLK_DIV_2
* - \ref TPWM_BKP_DBCLK_PCLK_DIV_4
* - \ref TPWM_BKP_DBCLK_PCLK_DIV_8
* - \ref TPWM_BKP_DBCLK_PCLK_DIV_16
* - \ref TPWM_BKP_DBCLK_PCLK_DIV_32
* - \ref TPWM_BKP_DBCLK_PCLK_DIV_64
* - \ref TPWM_BKP_DBCLK_PCLK_DIV_128
*
* @return None
*
* @details This function is used to enable external brake pin detector noise filter function.
*/
void TPWM_EnableBrakePinDebounce(TIMER_T *timer, uint32_t u32BrakePinSrc, uint32_t u32DebounceCnt, uint32_t u32ClkSrcSel)
{
timer->PWMBNF = (timer->PWMBNF & ~(TIMER_PWMBNF_BKPINSRC_Msk | TIMER_PWMBNF_BRKFCNT_Msk | TIMER_PWMBNF_BRKNFSEL_Msk)) |
(u32BrakePinSrc << TIMER_PWMBNF_BKPINSRC_Pos) |
(u32DebounceCnt << TIMER_PWMBNF_BRKFCNT_Pos) |
(u32ClkSrcSel << TIMER_PWMBNF_BRKNFSEL_Pos) | TIMER_PWMBNF_BRKNFEN_Msk;
}
/**
* @brief Disable brake pin noise filter function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This function is used to disable external brake pin detector noise filter function.
*/
void TPWM_DisableBrakePinDebounce(TIMER_T *timer)
{
timer->PWMBNF &= ~TIMER_PWMBNF_BRKNFEN_Msk;
}
/**
* @brief Enable brake pin inverse function
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @return None
* @details This function is used to enable PWM brake pin inverse function.
*/
void TPWM_EnableBrakePinInverse(TIMER_T *timer)
{
timer->PWMBNF |= TIMER_PWMBNF_BRKPINV_Msk;
}
/**
* @brief Disable brake pin inverse function
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @return None
* @details This function is used to disable PWM brake pin inverse function.
*/
void TPWM_DisableBrakePinInverse(TIMER_T *timer)
{
timer->PWMBNF &= ~TIMER_PWMBNF_BRKPINV_Msk;
}
/**
* @brief Set brake pin source
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] u32BrakePinNum Brake pin selection. One of the following:
* - \ref TPWM_TM_BRAKE0
* - \ref TPWM_TM_BRAKE1
* - \ref TPWM_TM_BRAKE2
* - \ref TPWM_TM_BRAKE3
* @return None
* @details This function is used to set PWM brake pin source.
*/
void TPWM_SetBrakePinSource(TIMER_T *timer, uint32_t u32BrakePinNum)
{
timer->PWMBNF = (((timer)->PWMBNF & ~TIMER_PWMBNF_BKPINSRC_Msk) | (u32BrakePinNum << TIMER_PWMBNF_BKPINSRC_Pos));
}
/*@}*/ /* end of group M480_TIMER_PWM_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_TIMER_PWM_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/

View File

@ -0,0 +1,745 @@
/**************************************************************************//**
* @file timer.h
* @version V1.00
* @brief M480 series Timer PWM Controller(Timer PWM) driver header file
*
* @copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#ifndef __TIMER_PWM_H__
#define __TIMER_PWM_H__
#ifdef __cplusplus
extern "C"
{
#endif
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_TIMER_PWM_Driver TIMER PWM Driver
@{
*/
/** @addtogroup M480_TIMER_PWM_EXPORTED_CONSTANTS TIMER PWM Exported Constants
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* Output Channel Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TPWM_CH0 (BIT0) /*!< Indicate PWMx_CH0 \hideinitializer */
#define TPWM_CH1 (BIT1) /*!< Indicate PWMx_CH1 \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Counter Type Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TPWM_UP_COUNT (0UL << TIMER_PWMCTL_CNTTYPE_Pos) /*!< Up count type \hideinitializer */
#define TPWM_DOWN_COUNT (1UL << TIMER_PWMCTL_CNTTYPE_Pos) /*!< Down count type \hideinitializer */
#define TPWM_UP_DOWN_COUNT (2UL << TIMER_PWMCTL_CNTTYPE_Pos) /*!< Up-Down count type \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Counter Mode Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TPWM_AUTO_RELOAD_MODE (0UL) /*!< Auto-reload mode \hideinitializer */
#define TPWM_ONE_SHOT_MODE (TIMER_PWMCTL_CNTMODE_Msk) /*!< One-shot mode \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Output Level Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TPWM_OUTPUT_TOGGLE (0UL) /*!< Timer PWM output toggle \hideinitializer */
#define TPWM_OUTPUT_NOTHING (1UL) /*!< Timer PWM output nothing \hideinitializer */
#define TPWM_OUTPUT_LOW (2UL) /*!< Timer PWM output low \hideinitializer */
#define TPWM_OUTPUT_HIGH (3UL) /*!< Timer PWM output high \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Trigger EADC Source Select Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TPWM_TRIGGER_EADC_AT_ZERO_POINT (0UL << TIMER_PWMEADCTS_TRGSEL_Pos) /*!< Timer PWM trigger EADC while counter zero point event occurred \hideinitializer */
#define TPWM_TRIGGER_EADC_AT_PERIOD_POINT (1UL << TIMER_PWMEADCTS_TRGSEL_Pos) /*!< Timer PWM trigger EADC while counter period point event occurred \hideinitializer */
#define TPWM_TRIGGER_EADC_AT_ZERO_OR_PERIOD_POINT (2UL << TIMER_PWMEADCTS_TRGSEL_Pos) /*!< Timer PWM trigger EADC while counter zero or period point event occurred \hideinitializer */
#define TPWM_TRIGGER_EADC_AT_COMPARE_UP_COUNT_POINT (3UL << TIMER_PWMEADCTS_TRGSEL_Pos) /*!< Timer PWM trigger EADC while counter up count compare point event occurred \hideinitializer */
#define TPWM_TRIGGER_EADC_AT_COMPARE_DOWN_COUNT_POINT (4UL << TIMER_PWMEADCTS_TRGSEL_Pos) /*!< Timer PWM trigger EADC while counter down count compare point event occurred \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Brake Control Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TPWM_BRAKE_SOURCE_EDGE_ACMP0 (TIMER_PWMBRKCTL_CPO0EBEN_Msk) /*!< Comparator 0 as edge-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_EDGE_ACMP1 (TIMER_PWMBRKCTL_CPO1EBEN_Msk) /*!< Comparator 1 as edge-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_EDGE_BKPIN (TIMER_PWMBRKCTL_BRKPEEN_Msk) /*!< Brake pin as edge-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_EDGE_SYS_CSS (TIMER_PWMBRKCTL_SYSEBEN_Msk | (TIMER_PWMFAILBRK_CSSBRKEN_Msk << 16)) /*!< System fail condition: clock security system detection as edge-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_EDGE_SYS_BOD (TIMER_PWMBRKCTL_SYSEBEN_Msk | (TIMER_PWMFAILBRK_BODBRKEN_Msk << 16)) /*!< System fail condition: brown-out detection as edge-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_EDGE_SYS_COR (TIMER_PWMBRKCTL_SYSEBEN_Msk | (TIMER_PWMFAILBRK_CORBRKEN_Msk << 16)) /*!< System fail condition: core lockup detection as edge-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_EDGE_SYS_RAM (TIMER_PWMBRKCTL_SYSEBEN_Msk | (TIMER_PWMFAILBRK_RAMBRKEN_Msk << 16)) /*!< System fail condition: SRAM parity error detection as edge-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_LEVEL_ACMP0 (TIMER_PWMBRKCTL_CPO0LBEN_Msk) /*!< Comparator 0 as level-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_LEVEL_ACMP1 (TIMER_PWMBRKCTL_CPO1LBEN_Msk) /*!< Comparator 1 as level-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_LEVEL_BKPIN (TIMER_PWMBRKCTL_BRKPLEN_Msk) /*!< Brake pin as level-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_LEVEL_SYS_CSS (TIMER_PWMBRKCTL_SYSLBEN_Msk | (TIMER_PWMFAILBRK_CSSBRKEN_Msk << 16)) /*!< System fail condition: clock security system detection as level-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_LEVEL_SYS_BOD (TIMER_PWMBRKCTL_SYSLBEN_Msk | (TIMER_PWMFAILBRK_BODBRKEN_Msk << 16)) /*!< System fail condition: brown-out detection as level-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_LEVEL_SYS_COR (TIMER_PWMBRKCTL_SYSLBEN_Msk | (TIMER_PWMFAILBRK_CORBRKEN_Msk << 16)) /*!< System fail condition: core lockup detection as level-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_SOURCE_LEVEL_SYS_RAM (TIMER_PWMBRKCTL_SYSLBEN_Msk | (TIMER_PWMFAILBRK_RAMBRKEN_Msk << 16)) /*!< System fail condition: SRAM parity error detection as level-detect fault brake source \hideinitializer */
#define TPWM_BRAKE_EDGE (TIMER_PWMSWBRK_BRKETRG_Msk) /*!< Edge-detect fault brake \hideinitializer */
#define TPWM_BRAKE_LEVEL (TIMER_PWMSWBRK_BRKLTRG_Msk) /*!< Level-detect fault brake \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Load Mode Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TPWM_LOAD_MODE_PERIOD (0UL) /*!< Timer PWM period load mode \hideinitializer \hideinitializer */
#define TPWM_LOAD_MODE_IMMEDIATE (TIMER_PWMCTL_IMMLDEN_Msk) /*!< Timer PWM immediately load mode \hideinitializer \hideinitializer */
#define TPWM_LOAD_MODE_CENTER (TIMER_PWMCTL_CTRLD_Msk) /*!< Timer PWM center load mode \hideinitializer \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Brake Pin De-bounce Clock Source Select Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TPWM_BKP_DBCLK_PCLK_DIV_1 (0UL) /*!< De-bounce clock is PCLK divide by 1 \hideinitializer \hideinitializer */
#define TPWM_BKP_DBCLK_PCLK_DIV_2 (1UL) /*!< De-bounce clock is PCLK divide by 2 \hideinitializer \hideinitializer */
#define TPWM_BKP_DBCLK_PCLK_DIV_4 (2UL) /*!< De-bounce clock is PCLK divide by 4 \hideinitializer \hideinitializer */
#define TPWM_BKP_DBCLK_PCLK_DIV_8 (3UL) /*!< De-bounce clock is PCLK divide by 8 \hideinitializer \hideinitializer */
#define TPWM_BKP_DBCLK_PCLK_DIV_16 (4UL) /*!< De-bounce clock is PCLK divide by 16 \hideinitializer \hideinitializer */
#define TPWM_BKP_DBCLK_PCLK_DIV_32 (5UL) /*!< De-bounce clock is PCLK divide by 32 \hideinitializer \hideinitializer */
#define TPWM_BKP_DBCLK_PCLK_DIV_64 (6UL) /*!< De-bounce clock is PCLK divide by 64 \hideinitializer \hideinitializer */
#define TPWM_BKP_DBCLK_PCLK_DIV_128 (7UL) /*!< De-bounce clock is PCLK divide by 128 \hideinitializer \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Brake Pin Source Select Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TPWM_TM_BRAKE0 (0UL) /*!< Brake pin source comes from TM_BRAKE0 \hideinitializer \hideinitializer */
#define TPWM_TM_BRAKE1 (1UL) /*!< Brake pin source comes from TM_BRAKE1 \hideinitializer \hideinitializer */
#define TPWM_TM_BRAKE2 (2UL) /*!< Brake pin source comes from TM_BRAKE2 \hideinitializer \hideinitializer */
#define TPWM_TM_BRAKE3 (3UL) /*!< Brake pin source comes from TM_BRAKE3 \hideinitializer \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Counter Clock Source Select Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TPWM_CNTR_CLKSRC_TMR_CLK (0UL) /*!< Timer PWM Clock source selects to TMR_CLK \hideinitializer \hideinitializer */
#define TPWM_CNTR_CLKSRC_TIMER0_INT (1UL) /*!< Timer PWM Clock source selects to TIMER0 interrupt event \hideinitializer \hideinitializer */
#define TPWM_CNTR_CLKSRC_TIMER1_INT (2UL) /*!< Timer PWM Clock source selects to TIMER1 interrupt event \hideinitializer \hideinitializer */
#define TPWM_CNTR_CLKSRC_TIMER2_INT (3UL) /*!< Timer PWM Clock source selects to TIMER2 interrupt event \hideinitializer \hideinitializer */
#define TPWM_CNTR_CLKSRC_TIMER3_INT (4UL) /*!< Timer PWM Clock source selects to TIMER3 interrupt event \hideinitializer \hideinitializer */
/*---------------------------------------------------------------------------------------------------------*/
/* Counter Synchronous Mode Constant Definitions */
/*---------------------------------------------------------------------------------------------------------*/
#define TPWM_CNTR_SYNC_DISABLE (0UL) /*!< Disable TIMER PWM synchronous function \hideinitializer \hideinitializer */
#define TPWM_CNTR_SYNC_START_BY_TIMER0 ((0<<TIMER_PWMSCTL_SYNCSRC_Pos) | (1<<TIMER_PWMSCTL_SYNCMODE_Pos)) /*!< PWM counter synchronous start by TIMER0 PWM \hideinitializer \hideinitializer */
#define TPWM_CNTR_SYNC_CLEAR_BY_TIMER0 ((0<<TIMER_PWMSCTL_SYNCSRC_Pos) | (3<<TIMER_PWMSCTL_SYNCMODE_Pos)) /*!< PWM counter synchronous clear by TIMER0 PWM \hideinitializer \hideinitializer */
#define TPWM_CNTR_SYNC_START_BY_TIMER2 ((1<<TIMER_PWMSCTL_SYNCSRC_Pos) | (1<<TIMER_PWMSCTL_SYNCMODE_Pos)) /*!< PWM counter synchronous start by TIMER2 PWM \hideinitializer \hideinitializer */
#define TPWM_CNTR_SYNC_CLEAR_BY_TIMER2 ((1<<TIMER_PWMSCTL_SYNCSRC_Pos) | (3<<TIMER_PWMSCTL_SYNCMODE_Pos)) /*!< PWM counter synchronous clear by TIMER2 PWM \hideinitializer \hideinitializer */
/*@}*/ /* end of group M480_TIMER_PWM_EXPORTED_CONSTANTS */
/** @addtogroup M480_TIMER_PWM_EXPORTED_FUNCTIONS TIMER PWM Exported Functions
@{
*/
/**
* @brief Enable PWM Counter Mode
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to enable specified Timer channel as PWM counter mode, then timer counter mode is invalid.
* @note All registers about time counter function will be cleared to 0 and timer clock source will be changed to PCLKx automatically after executing this macro.
* \hideinitializer
*/
#define TPWM_ENABLE_PWM_MODE(timer) ((timer)->ALTCTL = (1 << TIMER_ALTCTL_FUNCSEL_Pos))
/**
* @brief Disable PWM Counter Mode
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to disable specified Timer channel as PWM counter mode, then timer counter mode is available.
* @note All registers about PWM counter function will be cleared to 0 after executing this macro.
* \hideinitializer
*/
#define TPWM_DISABLE_PWM_MODE(timer) ((timer)->ALTCTL = (0 << TIMER_ALTCTL_FUNCSEL_Pos))
/**
* @brief Enable Independent Mode
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to enable independent mode of TIMER PWM module and complementary mode will be disabled.
* \hideinitializer
*/
#define TPWM_ENABLE_INDEPENDENT_MODE(timer) ((timer)->PWMCTL &= ~(1 << TIMER_PWMCTL_OUTMODE_Pos))
/**
* @brief Enable Complementary Mode
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to enable complementary mode of Timer PWM module and independent mode will be disabled.
* \hideinitializer
*/
#define TPWM_ENABLE_COMPLEMENTARY_MODE(timer) ((timer)->PWMCTL |= (1 << TIMER_PWMCTL_OUTMODE_Pos))
/**
* @brief Set Counter Type
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] type Timer PWM count type, could be one of the following type
* - \ref TPWM_UP_COUNT
* - \ref TPWM_DOWN_COUNT
* - \ref TPWM_UP_DOWN_COUNT
*
* @return None
*
* @details This macro is used to set Timer PWM counter type.
* \hideinitializer
*/
#define TPWM_SET_COUNTER_TYPE(timer, type) ((timer)->PWMCTL = ((timer)->PWMCTL & ~TIMER_PWMCTL_CNTTYPE_Msk) | (type))
/**
* @brief Start PWM Counter
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to enable PWM generator and start counter counting.
* \hideinitializer
*/
#define TPWM_START_COUNTER(timer) ((timer)->PWMCTL |= TIMER_PWMCTL_CNTEN_Msk)
/**
* @brief Stop PWM Counter
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to stop PWM counter after current period is completed.
* \hideinitializer
*/
#define TPWM_STOP_COUNTER(timer) ((timer)->PWMPERIOD = 0x0)
/**
* @brief Set Counter Clock Prescaler
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @param[in] prescaler Clock prescaler of specified channel. Valid values are between 0x0~0xFFF.
*
* @return None
*
* @details This macro is used to set the prescaler of specified TIMER PWM.
* @note If prescaler is 0, then there is no scaling in counter clock source.
* \hideinitializer
*/
#define TPWM_SET_PRESCALER(timer, prescaler) ((timer)->PWMCLKPSC = (prescaler))
/**
* @brief Get Counter Clock Prescaler
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return Target prescaler setting, CLKPSC (TIMERx_PWMCLKPSC[11:0])
*
* @details Get the prescaler setting, the target counter clock divider is (CLKPSC + 1).
* \hideinitializer
*/
#define TPWM_GET_PRESCALER(timer) ((timer)->PWMCLKPSC)
/**
* @brief Set Counter Period
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @param[in] period Period of specified channel. Valid values are between 0x0~0xFFFF.
*
* @return None
*
* @details This macro is used to set the period of specified TIMER PWM.
* \hideinitializer
*/
#define TPWM_SET_PERIOD(timer, period) ((timer)->PWMPERIOD = (period))
/**
* @brief Get Counter Period
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return Target period setting, PERIOD (TIMERx_PWMPERIOD[15:0])
*
* @details This macro is used to get the period of specified TIMER PWM.
* \hideinitializer
*/
#define TPWM_GET_PERIOD(timer) ((timer)->PWMPERIOD)
/**
* @brief Set Comparator Value
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @param[in] cmp Comparator of specified channel. Valid values are between 0x0~0xFFFF.
*
* @return None
*
* @details This macro is used to set the comparator value of specified TIMER PWM.
* \hideinitializer
*/
#define TPWM_SET_CMPDAT(timer, cmp) ((timer)->PWMCMPDAT = (cmp))
/**
* @brief Get Comparator Value
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return Target comparator setting, CMPDAT (TIMERx_PWMCMPDAT[15:0])
*
* @details This macro is used to get the comparator value of specified TIMER PWM.
* \hideinitializer
*/
#define TPWM_GET_CMPDAT(timer) ((timer)->PWMCMPDAT)
/**
* @brief Clear Counter
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to clear counter of specified TIMER PWM.
* \hideinitializer
*/
#define TPWM_CLEAR_COUNTER(timer) ((timer)->PWMCNTCLR = TIMER_PWMCNTCLR_CNTCLR_Msk)
/**
* @brief Software Trigger Brake Event
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @param[in] type Type of brake trigger. Valid values are:
* - \ref TPWM_BRAKE_EDGE
* - \ref TPWM_BRAKE_LEVEL
*
* @return None
*
* @details This macro is used to trigger brake event by writing PWMSWBRK register.
* \hideinitializer
*/
#define TPWM_SW_TRIGGER_BRAKE(timer, type) ((timer)->PWMSWBRK = (type))
/**
* @brief Enable Output Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @param[in] ch Enable specified channel output function. Valid values are:
* - \ref TPWM_CH0
* - \ref TPWM_CH1
*
* @return None
*
* @details This macro is used to enable output function of specified output pins.
* @note If the corresponding bit in u32ChMask parameter is 0, then output function will be disabled in this channel.
* \hideinitializer
*/
#define TPWM_ENABLE_OUTPUT(timer, ch) ((timer)->PWMPOEN = (ch))
/**
* @brief Set Output Inverse
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @param[in] ch Set specified channel output is inversed or not. Valid values are:
* - \ref TPWM_CH0
* - \ref TPWM_CH1
*
* @return None
*
* @details This macro is used to enable output inverse of specified output pins.
* @note If u32ChMask parameter is 0, then output inverse function will be disabled.
* \hideinitializer
*/
#define TPWM_SET_OUTPUT_INVERSE(timer, ch) ((timer)->PWMPOLCTL = (ch))
/**
* @brief Enable Output Function
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @param[in] ch Enable specified channel output mask function. Valid values are:
* - \ref TPWM_CH0
* - \ref TPWM_CH1
*
* @param[in] level Output to high or low on specified mask channel.
*
* @return None
*
* @details This macro is used to enable output function of specified output pins.
* @note If u32ChMask parameter is 0, then output mask function will be disabled.
* \hideinitializer
*/
#define TPWM_SET_MASK_OUTPUT(timer, ch, level) do {(timer)->PWMMSKEN = (ch); (timer)->PWMMSK = (level); }while(0)
/**
* @brief Set Counter Synchronous Mode
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @param[in] mode Synchronous mode. Possible options are:
* - \ref TPWM_CNTR_SYNC_DISABLE
* - \ref TPWM_CNTR_SYNC_START_BY_TIMER0
* - \ref TPWM_CNTR_SYNC_CLEAR_BY_TIMER0
* - \ref TPWM_CNTR_SYNC_START_BY_TIMER2
* - \ref TPWM_CNTR_SYNC_CLEAR_BY_TIMER2
*
* @return None
*
* @details This macro is used to set counter synchronous mode of specified Timer PWM module.
* @note Only support all PWM counters are synchronous by TIMER0 PWM or TIMER0~1 PWM counter synchronous by TIMER0 PWM and
* TIMER2~3 PWM counter synchronous by TIMER2 PWM.
* \hideinitializer
*/
#define TPWM_SET_COUNTER_SYNC_MODE(timer, mode) ((timer)->PWMSCTL = (mode))
/**
* @brief Trigger Counter Synchronous
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to trigger synchronous event by specified TIMER PWM.
* @note 1. This macro is only available for TIMER0 PWM and TIMER2 PWM. \n
* 2. STRGEN (PWMSTRG[0]) is write only and always read as 0.
* \hideinitializer
*/
#define TPWM_TRIGGER_COUNTER_SYNC(timer) ((timer)->PWMSTRG = TIMER_PWMSTRG_STRGEN_Msk)
/**
* @brief Enable Zero Event Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to enable the zero event interrupt function.
* \hideinitializer
*/
#define TPWM_ENABLE_ZERO_INT(timer) ((timer)->PWMINTEN0 |= TIMER_PWMINTEN0_ZIEN_Msk)
/**
* @brief Disable Zero Event Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to disable the zero event interrupt function.
* \hideinitializer
*/
#define TPWM_DISABLE_ZERO_INT(timer) ((timer)->PWMINTEN0 &= ~TIMER_PWMINTEN0_ZIEN_Msk)
/**
* @brief Get Zero Event Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @retval 0 Zero event interrupt did not occur
* @retval 1 Zero event interrupt occurred
*
* @details This macro indicates zero event occurred or not.
* \hideinitializer
*/
#define TPWM_GET_ZERO_INT_FLAG(timer) (((timer)->PWMINTSTS0 & TIMER_PWMINTSTS0_ZIF_Msk)? 1 : 0)
/**
* @brief Clear Zero Event Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro clears zero event interrupt flag.
* \hideinitializer
*/
#define TPWM_CLEAR_ZERO_INT_FLAG(timer) ((timer)->PWMINTSTS0 = TIMER_PWMINTSTS0_ZIF_Msk)
/**
* @brief Enable Period Event Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to enable the period event interrupt function.
* \hideinitializer
*/
#define TPWM_ENABLE_PERIOD_INT(timer) ((timer)->PWMINTEN0 |= TIMER_PWMINTEN0_PIEN_Msk)
/**
* @brief Disable Period Event Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to disable the period event interrupt function.
* \hideinitializer
*/
#define TPWM_DISABLE_PERIOD_INT(timer) ((timer)->PWMINTEN0 &= ~TIMER_PWMINTEN0_PIEN_Msk)
/**
* @brief Get Period Event Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @retval 0 Period event interrupt did not occur
* @retval 1 Period event interrupt occurred
*
* @details This macro indicates period event occurred or not.
* \hideinitializer
*/
#define TPWM_GET_PERIOD_INT_FLAG(timer) (((timer)->PWMINTSTS0 & TIMER_PWMINTSTS0_PIF_Msk)? 1 : 0)
/**
* @brief Clear Period Event Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro clears period event interrupt flag.
* \hideinitializer
*/
#define TPWM_CLEAR_PERIOD_INT_FLAG(timer) ((timer)->PWMINTSTS0 = TIMER_PWMINTSTS0_PIF_Msk)
/**
* @brief Enable Compare Up Event Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to enable the compare up event interrupt function.
* \hideinitializer
*/
#define TPWM_ENABLE_CMP_UP_INT(timer) ((timer)->PWMINTEN0 |= TIMER_PWMINTEN0_CMPUIEN_Msk)
/**
* @brief Disable Compare Up Event Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to disable the compare up event interrupt function.
* \hideinitializer
*/
#define TPWM_DISABLE_CMP_UP_INT(timer) ((timer)->PWMINTEN0 &= ~TIMER_PWMINTEN0_CMPUIEN_Msk)
/**
* @brief Get Compare Up Event Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @retval 0 Compare up event interrupt did not occur
* @retval 1 Compare up event interrupt occurred
*
* @details This macro indicates compare up event occurred or not.
* \hideinitializer
*/
#define TPWM_GET_CMP_UP_INT_FLAG(timer) (((timer)->PWMINTSTS0 & TIMER_PWMINTSTS0_CMPUIF_Msk)? 1 : 0)
/**
* @brief Clear Compare Up Event Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro clears compare up event interrupt flag.
* \hideinitializer
*/
#define TPWM_CLEAR_CMP_UP_INT_FLAG(timer) ((timer)->PWMINTSTS0 = TIMER_PWMINTSTS0_CMPUIF_Msk)
/**
* @brief Enable Compare Down Event Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to enable the compare down event interrupt function.
* \hideinitializer
*/
#define TPWM_ENABLE_CMP_DOWN_INT(timer) ((timer)->PWMINTEN0 |= TIMER_PWMINTEN0_CMPDIEN_Msk)
/**
* @brief Disable Compare Down Event Interrupt
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to disable the compare down event interrupt function.
* \hideinitializer
*/
#define TPWM_DISABLE_CMP_DOWN_INT(timer) ((timer)->PWMINTEN0 &= ~TIMER_PWMINTEN0_CMPDIEN_Msk)
/**
* @brief Get Compare Down Event Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @retval 0 Compare down event interrupt did not occur
* @retval 1 Compare down event interrupt occurred
*
* @details This macro indicates compare down event occurred or not.
* \hideinitializer
*/
#define TPWM_GET_CMP_DOWN_INT_FLAG(timer) (((timer)->PWMINTSTS0 & TIMER_PWMINTSTS0_CMPDIF_Msk)? 1 : 0)
/**
* @brief Clear Compare Down Event Interrupt Flag
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro clears compare down event interrupt flag.
* \hideinitializer
*/
#define TPWM_CLEAR_CMP_DOWN_INT_FLAG(timer) ((timer)->PWMINTSTS0 = TIMER_PWMINTSTS0_CMPDIF_Msk)
/**
* @brief Get Counter Reach Maximum Count Status
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @retval 0 Timer PWM counter never counts to maximum value
* @retval 1 Timer PWM counter counts to maximum value, 0xFFFF
*
* @details This macro indicates Timer PWM counter has count to 0xFFFF or not.
* \hideinitializer
*/
#define TPWM_GET_REACH_MAX_CNT_STATUS(timer) (((timer)->PWMSTATUS & TIMER_PWMSTATUS_CNTMAXF_Msk)? 1 : 0)
/**
* @brief Clear Counter Reach Maximum Count Status
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro clears reach maximum count status.
* \hideinitializer
*/
#define TPWM_CLEAR_REACH_MAX_CNT_STATUS(timer) ((timer)->PWMSTATUS = TIMER_PWMSTATUS_CNTMAXF_Msk)
/**
* @brief Get Trigger EADC Status
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @retval 0 Trigger EADC start conversion is not occur
* @retval 1 Specified counter compare event has trigger ADC start conversion
*
* @details This macro is used to indicate PWM counter compare event has triggered EADC start conversion.
* \hideinitializer
*/
#define TPWM_GET_TRG_EADC_STATUS(timer) (((timer)->PWMSTATUS & TIMER_PWMSTATUS_EADCTRGF_Msk)? 1 : 0)
/**
* @brief Clear Trigger EADC Status
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to clear PWM counter compare event trigger EADC status.
* \hideinitializer
*/
#define TPWM_CLEAR_TRG_EADC_STATUS(timer) ((timer)->PWMSTATUS = TIMER_PWMSTATUS_EADCTRGF_Msk)
/**
* @brief Set Brake Event at Brake Pin High or Low-to-High
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to set detect brake event when external brake pin at high level or transfer from low to high.
* @note The default brake pin detection is high level or from low to high.
* \hideinitializer
*/
#define TPWM_SET_BRAKE_PIN_HIGH_DETECT(timer) ((timer)->PWMBNF &= ~TIMER_PWMBNF_BRKPINV_Msk)
/**
* @brief Set Brake Event at Brake Pin Low or High-to-Low
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
*
* @return None
*
* @details This macro is used to set detect brake event when external brake pin at low level or transfer from high to low.
* \hideinitializer
*/
#define TPWM_SET_BRAKE_PIN_LOW_DETECT(timer) ((timer)->PWMBNF |= TIMER_PWMBNF_BRKPINV_Msk)
/**
* @brief Set External Brake Pin Source
*
* @param[in] timer The pointer of the specified Timer module. It could be TIMER0, TIMER1, TIMER2, TIMER3.
* @param[in] pin The external brake pin source, could be one of following source
* - \ref TPWM_TM_BRAKE0
* - \ref TPWM_TM_BRAKE1
* - \ref TPWM_TM_BRAKE2
* - \ref TPWM_TM_BRAKE3
*
* @return None
*
* @details This macro is used to set detect brake event when external brake pin at high level or transfer from low to high.
* \hideinitializer
*/
#define TPWM_SET_BRAKE_PIN_SOURCE(timer, pin) ((timer)->PWMBNF = ((timer)->PWMBNF & ~TIMER_PWMBNF_BKPINSRC_Msk) | ((pin)<<TIMER_PWMBNF_BKPINSRC_Pos))
void TPWM_SetCounterClockSource(TIMER_T *timer, uint32_t u32CntClkSrc);
uint32_t TPWM_ConfigOutputFreqAndDuty(TIMER_T *timer, uint32_t u32Frequency, uint32_t u32DutyCycle);
void TPWM_EnableDeadTime(TIMER_T *timer, uint32_t u32DTCount);
void TPWM_EnableDeadTimeWithPrescale(TIMER_T *timer, uint32_t u32DTCount);
void TPWM_DisableDeadTime(TIMER_T *timer);
void TPWM_EnableCounter(TIMER_T *timer);
void TPWM_DisableCounter(TIMER_T *timer);
void TPWM_EnableTriggerEADC(TIMER_T *timer, uint32_t u32Condition);
void TPWM_DisableTriggerEADC(TIMER_T *timer);
void TPWM_EnableFaultBrake(TIMER_T *timer, uint32_t u32CH0Level, uint32_t u32CH1Level, uint32_t u32BrakeSource);
void TPWM_EnableFaultBrakeInt(TIMER_T *timer, uint32_t u32IntSource);
void TPWM_DisableFaultBrakeInt(TIMER_T *timer, uint32_t u32IntSource);
uint32_t TPWM_GetFaultBrakeIntFlag(TIMER_T *timer, uint32_t u32IntSource);
void TPWM_ClearFaultBrakeIntFlag(TIMER_T *timer, uint32_t u32IntSource);
void TPWM_SetLoadMode(TIMER_T *timer, uint32_t u32LoadMode);
void TPWM_EnableBrakePinDebounce(TIMER_T *timer, uint32_t u32BrakePinSrc, uint32_t u32DebounceCnt, uint32_t u32ClkSrcSel);
void TPWM_DisableBrakePinDebounce(TIMER_T *timer);
void TPWM_EnableBrakePinInverse(TIMER_T *timer);
void TPWM_DisableBrakePinInverse(TIMER_T *timer);
void TPWM_SetBrakePinSource(TIMER_T *timer, uint32_t u32BrakePinNum);
/*@}*/ /* end of group M480_TIMER_PWM_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_TIMER_PWM_Driver */
/*@}*/ /* end of group M480_Device_Driver */
#ifdef __cplusplus
}
#endif
#endif /* __TIMER_PWM_H__ */

View File

@ -0,0 +1,578 @@
/**************************************************************************//**
* @file uart.c
* @version V3.00
* @brief M480 series UART driver source file
*
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "M480.h"
/** @addtogroup M480_Device_Driver M480 Device Driver
@{
*/
/** @addtogroup M480_UART_Driver UART Driver
@{
*/
/** @addtogroup M480_UART_EXPORTED_FUNCTIONS UART Exported Functions
@{
*/
/**
* @brief Clear UART specified interrupt flag
*
* @param[in] uart The pointer of the specified UART module.
* @param[in] u32InterruptFlag The specified interrupt of UART module.
* - \ref UART_INTSTS_LININT_Msk : LIN bus interrupt
* - \ref UART_INTEN_WKIEN_Msk : Wake-up interrupt
* - \ref UART_INTSTS_BUFERRINT_Msk : Buffer Error interrupt
* - \ref UART_INTSTS_MODEMINT_Msk : Modem Status interrupt
* - \ref UART_INTSTS_RLSINT_Msk : Receive Line Status interrupt
*
* @return None
*
* @details The function is used to clear UART specified interrupt flag.
*/
void UART_ClearIntFlag(UART_T* uart , uint32_t u32InterruptFlag)
{
if(u32InterruptFlag & UART_INTSTS_RLSINT_Msk) { /* Clear Receive Line Status Interrupt */
uart->FIFOSTS = UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_FEF_Msk;
uart->FIFOSTS = UART_FIFOSTS_ADDRDETF_Msk;
}
if(u32InterruptFlag & UART_INTSTS_MODEMINT_Msk) { /* Clear Modem Status Interrupt */
uart->MODEMSTS |= UART_MODEMSTS_CTSDETF_Msk;
} else {
}
if(u32InterruptFlag & UART_INTSTS_BUFERRINT_Msk) { /* Clear Buffer Error Interrupt */
uart->FIFOSTS = UART_FIFOSTS_RXOVIF_Msk | UART_FIFOSTS_TXOVIF_Msk;
}
if(u32InterruptFlag & UART_INTSTS_WKINT_Msk) { /* Clear Wake-up Interrupt */
uart->WKSTS = UART_WKSTS_CTSWKF_Msk | UART_WKSTS_DATWKF_Msk |
UART_WKSTS_RFRTWKF_Msk |UART_WKSTS_RS485WKF_Msk |
UART_WKSTS_TOUTWKF_Msk;
}
if(u32InterruptFlag & UART_INTSTS_LININT_Msk) { /* Clear LIN Bus Interrupt */
uart->INTSTS = UART_INTSTS_LINIF_Msk;
uart->LINSTS = UART_LINSTS_BITEF_Msk | UART_LINSTS_BRKDETF_Msk |
UART_LINSTS_SLVSYNCF_Msk | UART_LINSTS_SLVIDPEF_Msk |
UART_LINSTS_SLVHEF_Msk | UART_LINSTS_SLVHDETF_Msk ;
}
}
/**
* @brief Disable UART interrupt
*
* @param[in] uart The pointer of the specified UART module.
*
* @return None
*
* @details The function is used to disable UART interrupt.
*/
void UART_Close(UART_T* uart)
{
uart->INTEN = 0ul;
}
/**
* @brief Disable UART auto flow control function
*
* @param[in] uart The pointer of the specified UART module.
*
* @return None
*
* @details The function is used to disable UART auto flow control.
*/
void UART_DisableFlowCtrl(UART_T* uart)
{
uart->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
}
/**
* @brief Disable UART specified interrupt
*
* @param[in] uart The pointer of the specified UART module.
* @param[in] u32InterruptFlag The specified interrupt of UART module.
* - \ref UART_INTEN_WKIEN_Msk : Wake-up interrupt
* - \ref UART_INTEN_LINIEN_Msk : Lin bus interrupt
* - \ref UART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt
* - \ref UART_INTEN_RXTOIEN_Msk : Rx time-out interrupt
* - \ref UART_INTEN_MODEMIEN_Msk : Modem status interrupt
* - \ref UART_INTEN_RLSIEN_Msk : Receive Line status interrupt
* - \ref UART_INTEN_THREIEN_Msk : Tx empty interrupt
* - \ref UART_INTEN_RDAIEN_Msk : Rx ready interrupt *
*
* @return None
*
* @details The function is used to disable UART specified interrupt and disable NVIC UART IRQ.
*/
void UART_DisableInt(UART_T* uart, uint32_t u32InterruptFlag)
{
/* Disable UART specified interrupt */
UART_DISABLE_INT(uart, u32InterruptFlag);
}
/**
* @brief Enable UART auto flow control function
*
* @param[in] uart The pointer of the specified UART module.
*
* @return None
*
* @details The function is used to Enable UART auto flow control.
*/
void UART_EnableFlowCtrl(UART_T* uart)
{
/* Set RTS pin output is low level active */
uart->MODEM |= UART_MODEM_RTSACTLV_Msk;
/* Set CTS pin input is low level active */
uart->MODEMSTS |= UART_MODEMSTS_CTSACTLV_Msk;
/* Set RTS and CTS auto flow control enable */
uart->INTEN |= UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk;
}
/**
* @brief The function is used to enable UART specified interrupt and enable NVIC UART IRQ.
*
* @param[in] uart The pointer of the specified UART module.
* @param[in] u32InterruptFlag The specified interrupt of UART module:
* - \ref UART_INTEN_WKIEN_Msk : Wake-up interrupt
* - \ref UART_INTEN_LINIEN_Msk : Lin bus interrupt
* - \ref UART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt
* - \ref UART_INTEN_RXTOIEN_Msk : Rx time-out interrupt
* - \ref UART_INTEN_MODEMIEN_Msk : Modem status interrupt
* - \ref UART_INTEN_RLSIEN_Msk : Receive Line status interrupt
* - \ref UART_INTEN_THREIEN_Msk : Tx empty interrupt
* - \ref UART_INTEN_RDAIEN_Msk : Rx ready interrupt *
*
* @return None
*
* @details The function is used to enable UART specified interrupt and enable NVIC UART IRQ.
*/
void UART_EnableInt(UART_T* uart, uint32_t u32InterruptFlag)
{
/* Enable UART specified interrupt */
UART_ENABLE_INT(uart, u32InterruptFlag);
}
/**
* @brief Open and set UART function
*
* @param[in] uart The pointer of the specified UART module.
* @param[in] u32baudrate The baudrate of UART module.
*
* @return None
*
* @details This function use to enable UART function and set baud-rate.
*/
void UART_Open(UART_T* uart, uint32_t u32baudrate)
{
uint32_t u32UartClkSrcSel=0ul, u32UartClkDivNum=0ul;
uint32_t u32ClkTbl[4] = {__HXT, 0ul, __LXT, __HIRC};
uint32_t u32Baud_Div = 0ul;
if(uart==(UART_T*)UART0) {
/* Get UART clock source selection */
u32UartClkSrcSel = ((uint32_t)(CLK->CLKSEL1 & CLK_CLKSEL1_UART0SEL_Msk)) >> CLK_CLKSEL1_UART0SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART0DIV_Msk) >> CLK_CLKDIV0_UART0DIV_Pos;
} else if(uart==(UART_T*)UART1) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART1SEL_Msk) >> CLK_CLKSEL1_UART1SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART1DIV_Msk) >> CLK_CLKDIV0_UART1DIV_Pos;
} else if(uart==(UART_T*)UART2) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART2SEL_Msk) >> CLK_CLKSEL3_UART2SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART2DIV_Msk) >> CLK_CLKDIV4_UART2DIV_Pos;
} else if(uart==(UART_T*)UART3) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART3SEL_Msk) >> CLK_CLKSEL3_UART3SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART3DIV_Msk) >> CLK_CLKDIV4_UART3DIV_Pos;
} else if(uart==(UART_T*)UART4) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART4SEL_Msk) >> CLK_CLKSEL3_UART4SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART4DIV_Msk) >> CLK_CLKDIV4_UART4DIV_Pos;
} else if(uart==(UART_T*)UART5) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART5SEL_Msk) >> CLK_CLKSEL3_UART5SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART5DIV_Msk) >> CLK_CLKDIV4_UART5DIV_Pos;
}
/* Select UART function */
uart->FUNCSEL = UART_FUNCSEL_UART;
/* Set UART line configuration */
uart->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
/* Set UART Rx and RTS trigger level */
uart->FIFO &= ~(UART_FIFO_RFITL_Msk | UART_FIFO_RTSTRGLV_Msk);
/* Get PLL clock frequency if UART clock source selection is PLL */
if(u32UartClkSrcSel == 1ul) {
u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq();
}
/* Set UART baud rate */
if(u32baudrate != 0ul) {
u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate);
if(u32Baud_Div > 0xFFFFul) {
uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate));
} else {
uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div);
}
}
}
/**
* @brief Read UART data
*
* @param[in] uart The pointer of the specified UART module.
* @param[in] pu8RxBuf The buffer to receive the data of receive FIFO.
* @param[in] u32ReadBytes The the read bytes number of data.
*
* @return u32Count Receive byte count
*
* @details The function is used to read Rx data from RX FIFO and the data will be stored in pu8RxBuf.
*/
uint32_t UART_Read(UART_T* uart, uint8_t pu8RxBuf[], uint32_t u32ReadBytes)
{
uint32_t u32Count, u32delayno;
uint32_t u32Exit = 0ul;
for(u32Count = 0ul; u32Count < u32ReadBytes; u32Count++) {
u32delayno = 0ul;
while(uart->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) { /* Check RX empty => failed */
u32delayno++;
if(u32delayno >= 0x40000000ul) {
u32Exit = 1ul;
break;
} else {
}
}
if(u32Exit == 1ul) {
break;
} else {
pu8RxBuf[u32Count] = (uint8_t)uart->DAT; /* Get Data from UART RX */
}
}
return u32Count;
}
/**
* @brief Set UART line configuration
*
* @param[in] uart The pointer of the specified UART module.
* @param[in] u32baudrate The register value of baudrate of UART module.
* If u32baudrate = 0, UART baudrate will not change.
* @param[in] u32data_width The data length of UART module.
* - \ref UART_WORD_LEN_5
* - \ref UART_WORD_LEN_6
* - \ref UART_WORD_LEN_7
* - \ref UART_WORD_LEN_8
* @param[in] u32parity The parity setting (none/odd/even/mark/space) of UART module.
* - \ref UART_PARITY_NONE
* - \ref UART_PARITY_ODD
* - \ref UART_PARITY_EVEN
* - \ref UART_PARITY_MARK
* - \ref UART_PARITY_SPACE
* @param[in] u32stop_bits The stop bit length (1/1.5/2 bit) of UART module.
* - \ref UART_STOP_BIT_1
* - \ref UART_STOP_BIT_1_5
* - \ref UART_STOP_BIT_2
*
* @return None
*
* @details This function use to config UART line setting.
*/
void UART_SetLine_Config(UART_T* uart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits)
{
uint32_t u32UartClkSrcSel=0ul, u32UartClkDivNum=0ul;
uint32_t u32ClkTbl[4ul] = {__HXT, 0ul, __LXT, __HIRC};
uint32_t u32Baud_Div = 0ul;
if(uart==(UART_T*)UART0) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART0SEL_Msk) >> CLK_CLKSEL1_UART0SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART0DIV_Msk) >> CLK_CLKDIV0_UART0DIV_Pos;
} else if(uart==(UART_T*)UART1) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART1SEL_Msk) >> CLK_CLKSEL1_UART1SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART1DIV_Msk) >> CLK_CLKDIV0_UART1DIV_Pos;
} else if(uart==(UART_T*)UART2) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART2SEL_Msk) >> CLK_CLKSEL3_UART2SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART2DIV_Msk) >> CLK_CLKDIV4_UART2DIV_Pos;
} else if(uart==(UART_T*)UART3) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART3SEL_Msk) >> CLK_CLKSEL3_UART3SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART3DIV_Msk) >> CLK_CLKDIV4_UART3DIV_Pos;
} else if(uart==(UART_T*)UART4) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART4SEL_Msk) >> CLK_CLKSEL3_UART4SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART4DIV_Msk) >> CLK_CLKDIV4_UART4DIV_Pos;
} else if(uart==(UART_T*)UART5) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART5SEL_Msk) >> CLK_CLKSEL3_UART5SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART5DIV_Msk) >> CLK_CLKDIV4_UART5DIV_Pos;
}
/* Get PLL clock frequency if UART clock source selection is PLL */
if(u32UartClkSrcSel == 1ul) {
u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq();
} else {
}
/* Set UART baud rate */
if(u32baudrate != 0ul) {
u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate);
if(u32Baud_Div > 0xFFFFul) {
uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32baudrate));
} else {
uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div);
}
}
/* Set UART line configuration */
uart->LINE = u32data_width | u32parity | u32stop_bits;
}
/**
* @brief Set Rx timeout count
*
* @param[in] uart The pointer of the specified UART module.
* @param[in] u32TOC Rx timeout counter.
*
* @return None
*
* @details This function use to set Rx timeout count.
*/
void UART_SetTimeoutCnt(UART_T* uart, uint32_t u32TOC)
{
/* Set time-out interrupt comparator */
uart->TOUT = (uart->TOUT & ~UART_TOUT_TOIC_Msk) | (u32TOC);
/* Set time-out counter enable */
uart->INTEN |= UART_INTEN_TOCNTEN_Msk;
}
/**
* @brief Select and configure IrDA function
*
* @param[in] uart The pointer of the specified UART module.
* @param[in] u32Buadrate The baudrate of UART module.
* @param[in] u32Direction The direction of UART module in IrDA mode:
* - \ref UART_IRDA_TXEN
* - \ref UART_IRDA_RXEN
*
* @return None
*
* @details The function is used to configure IrDA relative settings. It consists of TX or RX mode and baudrate.
*/
void UART_SelectIrDAMode(UART_T* uart, uint32_t u32Buadrate, uint32_t u32Direction)
{
uint32_t u32UartClkSrcSel=0ul, u32UartClkDivNum=0ul;
uint32_t u32ClkTbl[4ul] = {__HXT, 0ul, __LXT, __HIRC};
uint32_t u32Baud_Div;
/* Select IrDA function mode */
uart->FUNCSEL = UART_FUNCSEL_IrDA;
if(uart==UART0) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART0SEL_Msk) >> CLK_CLKSEL1_UART0SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART0DIV_Msk) >> CLK_CLKDIV0_UART0DIV_Pos;
} else if(uart==UART1) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART1SEL_Msk) >> CLK_CLKSEL1_UART1SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UART1DIV_Msk) >> CLK_CLKDIV0_UART1DIV_Pos;
} else if(uart==UART2) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART2SEL_Msk) >> CLK_CLKSEL3_UART2SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART2DIV_Msk) >> CLK_CLKDIV4_UART2DIV_Pos;
} else if(uart==UART3) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART3SEL_Msk) >> CLK_CLKSEL3_UART3SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART3DIV_Msk) >> CLK_CLKDIV4_UART3DIV_Pos;
} else if(uart==UART4) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART4SEL_Msk) >> CLK_CLKSEL3_UART4SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART4DIV_Msk) >> CLK_CLKDIV4_UART4DIV_Pos;
} else if(uart==UART5) {
/* Get UART clock source selection */
u32UartClkSrcSel = (CLK->CLKSEL3 & CLK_CLKSEL3_UART5SEL_Msk) >> CLK_CLKSEL3_UART5SEL_Pos;
/* Get UART clock divider number */
u32UartClkDivNum = (CLK->CLKDIV4 & CLK_CLKDIV4_UART5DIV_Msk) >> CLK_CLKDIV4_UART5DIV_Pos;
}
/* Get PLL clock frequency if UART clock source selection is PLL */
if(u32UartClkSrcSel == 1ul) {
u32ClkTbl[u32UartClkSrcSel] = CLK_GetPLLClockFreq();
} else {
}
/* Set UART IrDA baud rate in mode 0 */
if(u32Buadrate != 0ul) {
u32Baud_Div = UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u32UartClkSrcSel]) / (u32UartClkDivNum + 1ul), u32Buadrate);
if(u32Baud_Div < 0xFFFFul) {
uart->BAUD = (UART_BAUD_MODE0 | u32Baud_Div);
} else {
}
}
/* Configure IrDA relative settings */
if(u32Direction == UART_IRDA_RXEN) {
uart->IRDA |= UART_IRDA_RXINV_Msk; /*Rx signal is inverse*/
uart->IRDA &= ~UART_IRDA_TXEN_Msk;
} else {
uart->IRDA &= ~UART_IRDA_TXINV_Msk; /*Tx signal is not inverse*/
uart->IRDA |= UART_IRDA_TXEN_Msk;
}
}
/**
* @brief Select and configure RS485 function
*
* @param[in] uart The pointer of the specified UART module.
* @param[in] u32Mode The operation mode(NMM/AUD/AAD).
* - \ref UART_ALTCTL_RS485NMM_Msk
* - \ref UART_ALTCTL_RS485AUD_Msk
* - \ref UART_ALTCTL_RS485AAD_Msk
* @param[in] u32Addr The RS485 address.
*
* @return None
*
* @details The function is used to set RS485 relative setting.
*/
void UART_SelectRS485Mode(UART_T* uart, uint32_t u32Mode, uint32_t u32Addr)
{
/* Select UART RS485 function mode */
uart->FUNCSEL = UART_FUNCSEL_RS485;
/* Set RS585 configuration */
uart->ALTCTL &= ~(UART_ALTCTL_RS485NMM_Msk | UART_ALTCTL_RS485AUD_Msk | UART_ALTCTL_RS485AAD_Msk | UART_ALTCTL_ADDRMV_Msk);
uart->ALTCTL |= (u32Mode | (u32Addr << UART_ALTCTL_ADDRMV_Pos));
}
/**
* @brief Select and configure LIN function
*
* @param[in] uart The pointer of the specified UART module.
* @param[in] u32Mode The LIN direction :
* - \ref UART_ALTCTL_LINTXEN_Msk
* - \ref UART_ALTCTL_LINRXEN_Msk
* @param[in] u32BreakLength The break field length.
*
* @return None
*
* @details The function is used to set LIN relative setting.
*/
void UART_SelectLINMode(UART_T* uart, uint32_t u32Mode, uint32_t u32BreakLength)
{
/* Select LIN function mode */
uart->FUNCSEL = UART_FUNCSEL_LIN;
/* Select LIN function setting : Tx enable, Rx enable and break field length */
uart->ALTCTL &= ~(UART_ALTCTL_LINTXEN_Msk | UART_ALTCTL_LINRXEN_Msk | UART_ALTCTL_BRKFL_Msk);
uart->ALTCTL |= (u32Mode | (u32BreakLength << UART_ALTCTL_BRKFL_Pos));
}
/**
* @brief Write UART data
*
* @param[in] uart The pointer of the specified UART module.
* @param[in] pu8TxBuf The buffer to send the data to UART transmission FIFO.
* @param[out] u32WriteBytes The byte number of data.
*
* @return u32Count transfer byte count
*
* @details The function is to write data into TX buffer to transmit data by UART.
*/
uint32_t UART_Write(UART_T* uart, uint8_t pu8TxBuf[], uint32_t u32WriteBytes)
{
uint32_t u32Count, u32delayno;
uint32_t u32Exit = 0ul;
for(u32Count = 0ul; u32Count != u32WriteBytes; u32Count++) {
u32delayno = 0ul;
while((uart->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk) == 0ul) { /* Wait Tx empty and Time-out manner */
u32delayno++;
if(u32delayno >= 0x40000000ul) {
u32Exit = 1ul;
break;
} else {
}
}
if(u32Exit == 1ul) {
break;
} else {
uart->DAT = pu8TxBuf[u32Count]; /* Send UART Data from buffer */
}
}
return u32Count;
}
/*@}*/ /* end of group M480_UART_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group M480_UART_Driver */
/*@}*/ /* end of group M480_Device_Driver */
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/

Some files were not shown because too many files have changed in this diff Show More