未验证 提交 7847c5e9 编写于 作者: K Kevin Liu 提交者: GitHub

Microchip SAM MCU新增ethernet支持和驱动更新 (#5821)

* Microchip SAM MCU BSP update and add ethernet driver

1. Update Microchip SAM MCU BSP, add I2C, GMAC, ADC driver support. 2. Add ethernet driver support of SAM MCU for RT-Thread.

* Add GMAC and I2C driver support

1. Update MCU BSP to support I2C/ADC/GMAC peripherals. 2. Add I2C and ethernet driver and LWIP support. 3. Update serial driver.

* Add I2C driver and move some files to the common folder

1. Add I2C driver. 2. Move the same drivers and demo code to same folder to reduce duplicated code.
上级 991b6e78
......@@ -183,6 +183,9 @@ About RT-Thread env tools, click [Here](https://github.com/RT-Thread/rt-thread/b
![](doc/3-1-8-atmel-start-Studio7-start-debugging3.png)
* Debugging message output.
![](doc/3-1-9-atmel-start-rt-thread-run.png)
# 4. Reconfigure MCU BSP
......
import rtconfig
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
#remove other no use files
if GetDepend('SAM_CAN_EXAMPLE') == False:
SrcRemove(src, ['can_demo.c'])
if GetDepend('SAM_I2C_EXAMPLE') == False:
SrcRemove(src, ['i2c_demo.c'])
if GetDepend('SAM_ADC_EXAMPLE') == False:
SrcRemove(src, ['adc_demo.c'])
if GetDepend('SAM_LWIP_EXAMPLE') == False:
SrcRemove(src, ['lwip_demo.c'])
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Email Notes
* 2022-04-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#include <rtthread.h>
#include <atmel_start.h>
#include "adc_demo.h"
#ifdef SAM_ADC_EXAMPLE
#if defined(SOC_SAMC21)
#define ADC_RESOLUTION_12BIT ADC_CTRLC_RESSEL_12BIT_Val
#define ADC_RESOLUTION_16BIT ADC_CTRLC_RESSEL_16BIT_Val
#elif defined(SOC_SAME54)
#define ADC_RESOLUTION_12BIT ADC_CTRLB_RESSEL_12BIT_Val
#define ADC_RESOLUTION_16BIT ADC_CTRLB_RESSEL_16BIT_Val
#elif defined(SOC_SAME70)
#define ADC_RESOLUTION_12BIT AFEC_EMR_RES_NO_AVERAGE_Val
#define ADC_RESOLUTION_16BIT AFEC_EMR_RES_OSR256_Val
#else
#error "ADC undefined SOC Platform"
#endif
/**
* @brief Call this function will run ADC test code.
*
* @note Test code will try to read ADC conversion result.
*
* @param None.
*
* @return RT_OK or -RT_ERROR.
*/
rt_err_t adc_demo_run(void)
{
rt_uint8_t buffer[2];
/* enable ADC driver module */
adc_sync_enable_channel(&ADC_0, 0);
adc_sync_read_channel(&ADC_0, 0, buffer, 2);
#ifndef RT_USING_FINSH
rt_kprintf("buf[0]=0x%02X buf[1]=0x%02X\r\n", buffer[0], buffer[1]);
#endif
/* ADC 16-bit resolution */
adc_sync_disable_channel(&ADC_0, 0);
adc_sync_set_resolution(&ADC_0, ADC_RESOLUTION_16BIT);
adc_sync_enable_channel(&ADC_0, 0);
#ifndef RT_USING_FINSH
rt_kprintf("buf[0]=0x%02X buf[1]=0x%02X\r\n", buffer[0], buffer[1]);
#endif
/* ADC 12-bit resolution */
adc_sync_disable_channel(&ADC_0, 0);
adc_sync_set_resolution(&ADC_0, ADC_RESOLUTION_12BIT);
adc_sync_enable_channel(&ADC_0, 0);
#ifndef RT_USING_FINSH
rt_kprintf("buf[0]=0x%02X buf[1]=0x%02X\r\n", buffer[0], buffer[1]);
#endif
return RT_EOK;
}
#endif
/*@}*/
......@@ -5,11 +5,11 @@
*
* Change Logs:
* Date Author Email Notes
* 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release
* 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#ifndef __BOARD_SERIAL_H_
#define __BOARD_SERIAL_H_
#ifndef __APPLICATION_ADC_H_
#define __APPLICATION_ADC_H_
#include <rtthread.h>
......@@ -17,6 +17,6 @@
* @brief External function definitions
*
*/
int rt_hw_uart_init(void);
rt_err_t adc_demo_run(void);
#endif // __BOARD_SERIAL_H_
#endif // __APPLICATION_I2C_H_
......@@ -5,16 +5,11 @@
*
* Change Logs:
* Date Author Email Notes
* 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release
* 2022-04-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#include <rtthread.h>
#ifdef RT_USING_FINSH
#include <finsh.h>
#include <shell.h>
#endif
#include "atmel_start.h"
#include "driver_init.h"
#include "utils.h"
......@@ -23,6 +18,14 @@
#ifdef SAM_CAN_EXAMPLE
#if defined(SOC_SAMC21) || defined(SOC_SAME54)
#define CAN_HARDWARE (void *)CAN1
#elif defined(SOC_SAME70)
#define CAN_HARDWARE (void *)MCAN1
#else
#error "CAN undefined SOC Platform"
#endif
static volatile enum can_async_interrupt_type can_errors;
static rt_sem_t can_txdone;
static rt_sem_t can_rxdone;
......@@ -251,7 +254,7 @@ static void can_thread_entry(void* parameter)
/* CAN task got CAN error message, handler CAN Error Status */
if ((can_errors == CAN_IRQ_BO) || (can_errors == CAN_IRQ_DO))
{
can_async_init(&CAN_0, CAN1);
can_async_init(&CAN_0, CAN_HARDWARE);
}
}
}
......
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Email Notes
* 2022-04-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#include <rtthread.h>
#include <atmel_start.h>
#include "i2c_demo.h"
#ifdef SAM_I2C_EXAMPLE
#define I2C_AT24MAC_PGMAXSZ (16+1)
#define CONF_AT24MAC_ADDRESS 0x57
/**
* @brief Call this function will run I2C test code.
*
* @note Test code will try to read/write external EEPROM.
*
* @param None.
*
* @return RT_OK or -RT_ERROR.
*/
rt_err_t i2c_demo_run(void)
{
rt_uint8_t addr = 0x20;
rt_int32_t len;
rt_uint8_t i2ctx[I2C_AT24MAC_PGMAXSZ];
rt_uint8_t i2crx[I2C_AT24MAC_PGMAXSZ];
for (len = 1; len < I2C_AT24MAC_PGMAXSZ; len++)
{
i2ctx[len] = (rt_uint8_t)(len + 0x20);
}
/* enable I2C master and set slave address before use I2C driver module */
i2c_m_sync_enable(&I2C_0);
i2c_m_sync_set_slaveaddr(&I2C_0, CONF_AT24MAC_ADDRESS, I2C_M_SEVEN);
/* write 16bytes data to address 0x20 - I2C slave address + random address + write data[0]...[n] */
i2ctx[0] = addr; /* Refer to AT24MAC data sheet, first byte is page address. */
io_write(&(I2C_0.io), i2ctx, I2C_AT24MAC_PGMAXSZ);
/* Refer to data sheet, for random read, should send read address first. */
io_write(&(I2C_0.io), &addr, 1);
/* Then start I2C read after send I2C slave address first */
io_read(&(I2C_0.io), &i2crx[1], 16);
#ifndef RT_USING_FINSH
rt_kprintf("i2crx[0]=0x%02X i2crx[15]=0x%02X\r\n", i2crx[0], i2crx[15]);
#endif
return RT_EOK;
}
#endif
/*@}*/
/*
* Copyright (c)
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Email Notes
* 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#ifndef __APPLICATION_I2C_H_
#define __APPLICATION_I2C_H_
#include <rtthread.h>
/**
* @brief External function definitions
*
*/
rt_err_t i2c_demo_run(void);
#endif // __APPLICATION_I2C_H_
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-01-24 ChungHsuan improve code comments
*/
#include <rtthread.h>
#include <string.h>
#if !defined(SAL_USING_POSIX)
#error "Please enable SAL_USING_POSIX!"
#else
#include <sys/time.h>
#include <sys/select.h>
#endif
#include <sys/socket.h> /* socket.h header file is needed when using BSD socket */ /* 使用BSD socket,需要包含socket.h头文件 */
#include "netdb.h"
#define DEBUG_TCP_CLIENT
#define DBG_TAG "TCP"
#ifdef DEBUG_TCP_CLIENT
#define DBG_LVL DBG_LOG
#else
#define DBG_LVL DBG_INFO /* DBG_ERROR */
#endif
#include <rtdbg.h>
#include "lwip_demo.h"
#ifdef SAM_LWIP_EXAMPLE
#define BUFSZ 1024
static int started = 0;
static int is_running = 0;
static char url[256] = "www.baidu.com";
static int port = 8080;
static const char send_data[] = "This is TCP Client from RT-Thread."; /* The message be sent */ /* 发送用到的数据 */
/**
* @brief This function is for creating a tcp client on RT-Thread
*/
static void tcpclient(void *arg)
{
int ret;
char *recv_data;
int bytes_received;
int sock = -1;
struct hostent *host = RT_NULL;
struct sockaddr_in server_addr;
struct timeval timeout;
fd_set readset;
/* Get host address by parameter url(Domain name resolution if input domain) */
/* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
host = gethostbyname(url);
if (host == RT_NULL)
{
LOG_E("Get host by name failed!");
return;
}
/* Allocate space for recv_data */
/* 分配用于存放接收数据的缓冲 */
recv_data = rt_malloc(BUFSZ);
if (recv_data == RT_NULL)
{
LOG_E("No memory");
return;
}
/* Create a socket and set it to SOCK_STREAM(TCP) */
/* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* Failed on creatinf socket */
/* 创建socket失败 */
LOG_E("Create socket error");
goto __exit;
}
/* Initialize server side address */
/* 初始化预连接的服务端地址 */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
/* Connect to server */
/* 连接到服务端 */
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
/*Failed on connecting to server*/
/* 连接失败 */
LOG_E("Connect fail!");
goto __exit;
}
started = 1;
is_running = 1;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
while (is_running)
{
FD_ZERO(&readset);
FD_SET(sock, &readset);
/* Wait for read */
if (select(sock + 1, &readset, RT_NULL, RT_NULL, &timeout) == 0)
continue;
/* Receive the maximum size 1024 bytes from socket */
/* 从sock连接中接收最大BUFSZ - 1字节数据 */
bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);
if (bytes_received < 0)
{
/* Receive failed and close the connection */
/* 接收失败,关闭这个连接 */
LOG_E("Received error, close the socket.");
goto __exit;
}
else if (bytes_received == 0)
{
/* Print warning message when recv function return 0 */
/* 打印recv函数返回值为0的警告信息 */
LOG_W("Received warning, recv function return 0.");
continue;
}
else
{
/* Receive data sucessfully and append '\0' at the end of message */
/* 有接收到数据,把末端清零 */
recv_data[bytes_received] = '\0';
if (rt_strcmp(recv_data, "q") == 0 || rt_strcmp(recv_data, "Q") == 0)
{
/* If the first letter is 'q' or 'Q', close the connection */
/* 如果是首字母是q或Q,关闭这个连接 */
LOG_I("Got a 'q' or 'Q', close the socket.");
goto __exit;
}
else
{
/* Show the message in terminal */
/* 在控制终端显示收到的数据 */
LOG_D("Received data = %s", recv_data);
}
}
/* Send message to connected socket */
/* 发送数据到sock连接 */
ret = send(sock, send_data, rt_strlen(send_data), 0);
if (ret < 0)
{
/* Send failed, close the connection */
/* 发送失败,关闭这个连接 */
LOG_I("send error, close the socket.");
goto __exit;
}
else if (ret == 0)
{
/* Print warning message when send function return 0 */
/* 打印send函数返回值为0的警告信息 */
LOG_W("Send warning, send function return 0.");
}
}
__exit:
if (recv_data)
{
rt_free(recv_data);
recv_data = RT_NULL;
}
if (sock >= 0)
{
closesocket(sock);
sock = -1;
}
started = 0;
is_running = 0;
return;
}
/**
* @brief Call this function will run LWIP example code.
*
* @note .
*
* @param None.
*
* @return RT_OK or -RT_ERROR.
*/
rt_err_t lwip_demo_run(void)
{
rt_thread_t tid;
tid = rt_thread_create("tcp_client",
tcpclient, RT_NULL,
2048, RT_THREAD_PRIORITY_MAX/3, 20);
if (tid != RT_NULL)
{
rt_thread_startup(tid);
}
return RT_EOK;
}
#endif
/*@}*/
/*
* Copyright (c)
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Email Notes
* 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#ifndef __APPLICATION_LWIP_H_
#define __APPLICATION_LWIP_H_
#include <rtthread.h>
/**
* @brief External function definitions
*
*/
rt_err_t lwip_demo_run(void);
#endif // __APPLICATION_LWIP_H_
Import('RTT_ROOT')
Import('rtconfig')
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
#remove other no use files
if GetDepend('SAM_I2C_EXAMPLE') == False:
SrcRemove(src, ['sam_i2c.c'])
if GetDepend('SAM_LWIP_EXAMPLE') == False:
SrcRemove(src, ['sam_gmac.c'])
# You can select chips from the list above
CPPDEFINES = []
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
Return('group')
\ No newline at end of file
/*
* Copyright (c)
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Email Notes
* 2022-04-06 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <rtdbg.h>
#include <netif/ethernetif.h>
#include <lwipopts.h>
#include <atmel_start.h>
#include <peripheral_clk_config.h>
#include <ieee8023_mii_standard_config.h>
#include "board.h"
#include "sam_gmac.h"
#ifdef RT_USING_LWIP
struct rt_sam_eth
{
/* inherit from ethernet device */
struct eth_device parent;
struct mac_async_descriptor *macif;
struct ethernet_phy_descriptor *phyif;
#ifdef RT_USING_TIMER_SOFT
rt_timer_t phy_monitor_timer;
#else
rt_thread_t phy_monitor_tid;
#endif
/* ethernet MAC address */
rt_uint8_t mac_addr[NETIF_MAX_HWADDR_LEN];
/* GMAC Link Speed */
gmac_speed_type link_speed;
/* GMAC Link Mode */
gmac_duplex_type link_mode;
};
static struct rt_sam_eth sam_eth_device;
/**
* @brief Called by GMAC RX interrupt, will notify RX task
*
* @note Will call eth_device_ready to notify RX task.
*
* @param
*
* @return
*/
static void rt_sam_gmac_rxcb(void)
{
rt_err_t result;
/* enter interrupt */
rt_interrupt_enter();
result = eth_device_ready(&sam_eth_device.parent);
if (result != RT_EOK)
LOG_E("rt_sam_gmac_rxcb error");
/* leave interrupt */
rt_interrupt_leave();
}
/**
* @brief Initialize the MAC hardware
*
* @note Will set MAC filter by using input MAC address.
*
* @param gmac_dev GMAC device description.
*
* @return
*/
static inline void rt_sam_gmac_init(struct rt_sam_eth *gmac_dev)
{
struct mac_async_filter filter;
/* set MAC hardware address */
rt_memcpy(filter.mac, sam_eth_device.mac_addr, NETIF_MAX_HWADDR_LEN);
filter.tid_enable = false;
mac_async_set_filter(gmac_dev->macif, 0, &filter);
mac_async_register_callback(gmac_dev->macif, MAC_ASYNC_RECEIVE_CB, (FUNC_PTR)rt_sam_gmac_rxcb);
}
static rt_err_t rt_sam_eth_init(rt_device_t dev)
{
LOG_D("gmac init");
return RT_EOK;
}
static rt_err_t rt_sam_eth_open(rt_device_t dev, rt_uint16_t oflag)
{
LOG_D("gmac open");
return RT_EOK;
}
static rt_err_t rt_sam_eth_close(rt_device_t dev)
{
LOG_D("gmac close");
return RT_EOK;
}
static rt_size_t rt_sam_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
LOG_D("gmac read");
rt_set_errno(-RT_ENOSYS);
return 0;
}
static rt_size_t rt_sam_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
LOG_D("gmac write");
rt_set_errno(-RT_ENOSYS);
return 0;
}
static rt_err_t rt_sam_eth_control(rt_device_t dev, int cmd, void *args)
{
rt_err_t ret = RT_EOK;
switch (cmd)
{
case NIOCTL_GADDR:
/* get mac address */
if (args)
rt_memcpy(args, sam_eth_device.mac_addr, 6);
break;
default :
break;
}
return ret;
}
/**
* @brief Transmission packet though the MAC hardware
*
* @note Send package to MAC.
*
* @param dev the RT net device input.
*
* @param p stored message will be sent to MAC.
*
* @return RT_EOK.
*/
rt_err_t rt_sam_eth_tx(rt_device_t dev, struct pbuf *p)
{
struct rt_sam_eth *gmac_dev = (struct rt_sam_eth *)dev->user_data;
struct pbuf * q;
void * tbuf;
uint8_t * pos;
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
if (p->tot_len == p->len)
{
mac_async_write(gmac_dev->macif, p->payload, p->tot_len);
}
else
{
tbuf = mem_malloc(LWIP_MEM_ALIGN_SIZE(p->tot_len));
pos = tbuf;
if (tbuf == NULL)
{
return ERR_MEM;
}
for (q = p; q != NULL; q = q->next)
{
rt_memcpy(pos, q->payload, q->len);
pos += q->len;
}
mac_async_write(gmac_dev->macif, tbuf, p->tot_len);
mem_free(tbuf);
}
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.xmit);
return ERR_OK;
}
/**
* @brief Receive packet from the MAC hardware
*
* @note Returned pbuf filled with the received packet (including MAC header)
*
* @param dev the RT net device input.
*
* @return NULL on memory error
*/
struct pbuf *rt_sam_eth_rx(rt_device_t dev)
{
struct rt_sam_eth *gmac_dev = (struct rt_sam_eth *)dev->user_data;
struct pbuf * p;
u16_t len;
len = mac_async_read_len(gmac_dev->macif); /* Obtain the size of the packet */
if (len == 0)
{
return NULL;
}
#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
/* Allocate a pbuf as one large chunk, This include protocol header */
p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
if (p != NULL)
{
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
/* Read the entire packet into the pbuf. */
mac_async_read(gmac_dev->macif, p->payload, p->len);
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.recv);
}
else
{
mac_async_read(gmac_dev->macif, NULL, 0);
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
}
return p;
}
/**
* @brief PHY link status monitor task - timer task or thread
*
* @note Will check link status, link mode and link speed
*
* @param parameter input parameter passing to the function.
*
* @return
*/
static void rt_sam_eth_monitor(void *parameter)
{
struct rt_sam_eth *sam_eth = (struct rt_sam_eth *)parameter;
bool link_up;
int32_t ret;
uint16_t val;
static rt_uint8_t link_count = 0;
#ifndef RT_USING_TIMER_SOFT
while (1)
{
#endif
ret = ethernet_phy_get_link_status(sam_eth->phyif, &link_up);
if (ERR_NONE == ret)
{
if (link_up)
{
/* send link up. */
eth_device_linkchange(&sam_eth->parent, RT_TRUE);
}
else
{
/* send link down. */
eth_device_linkchange(&sam_eth->parent, RT_FALSE);;
}
}
ret = ethernet_phy_read_reg(sam_eth->phyif, MDIO_REG1_BMSR, &val);
if (ERR_NONE == ret)
{
if (val & (MDIO_REG1_BIT_100BASE_TX_FD | MDIO_REG1_BIT_100BASE_TX_HD))
{
LOG_D("100Mbps");
sam_eth_device.link_speed = GMAC_SPEED_100MBPS;
}
else
{
LOG_D("10Mbps");
sam_eth_device.link_speed = GMAC_SPEED_10MBPS;
}
if (val & (MDIO_REG1_BIT_100BASE_TX_FD | MDIO_REG1_BIT_10BASE_T_FD))
{
LOG_D("100Mbps");
sam_eth_device.link_mode = GMAC_FULL_DUPLEX;
}
else
{
LOG_D("10Mbps");
sam_eth_device.link_mode = GMAC_HALF_DUPLEX;
}
}
if (link_count >= 10)
{
link_count = 0;
/* Restart an auto-negotiation */
ethernet_phy_restart_autoneg(sam_eth->phyif);
}
#ifndef RT_USING_TIMER_SOFT
rt_thread_mdelay(1000);
}
#endif
}
/**
* @brief Register the GMAC Ethernet device.
*
* @note
*
* @param
*
* @return RT_OK or RT_ERROR.
*/
static int rt_hw_sam_eth_init(void)
{
rt_err_t state = RT_EOK;
#if CONF_AT24MAC_ADDRESS != 0
rt_uint8_t addr = 0x9A;
#endif
sam_eth_device.macif = &MACIF;
sam_eth_device.phyif = &MACIF_PHY_desc;
sam_eth_device.link_speed = GMAC_SPEED_100MBPS;
sam_eth_device.link_mode = GMAC_FULL_DUPLEX;
#if CONF_AT24MAC_ADDRESS != 0
i2c_m_sync_enable(&I2C_0);
i2c_m_sync_set_slaveaddr(&I2C_0, CONF_AT24MAC_ADDRESS, I2C_M_SEVEN);
io_write(&(I2C_0.io), &addr, 1);
io_read(&(I2C_0.io), sam_eth_device.mac_addr, 6);
#else
/* set mac to 0x11 if no EEPROM mounted */
memset(sam_eth_device.mac_addr, 0x11, 6);
#endif
sam_eth_device.parent.parent.init = rt_sam_eth_init;
sam_eth_device.parent.parent.open = rt_sam_eth_open;
sam_eth_device.parent.parent.close = rt_sam_eth_close;
sam_eth_device.parent.parent.read = rt_sam_eth_read;
sam_eth_device.parent.parent.write = rt_sam_eth_write;
sam_eth_device.parent.parent.control = rt_sam_eth_control;
sam_eth_device.parent.parent.user_data = (void *)&sam_eth_device;
sam_eth_device.parent.eth_rx = rt_sam_eth_rx;
sam_eth_device.parent.eth_tx = rt_sam_eth_tx;
rt_sam_gmac_init(&sam_eth_device);
/* register eth device */
state = eth_device_init(&(sam_eth_device.parent), "e0");
if (RT_EOK == state)
{
LOG_D("gmac device init success");
}
else
{
LOG_E("gmac device init faild: %d", state);
state = -RT_ERROR;
goto outs;
}
/* start SAM PHY monitor */
#ifdef RT_USING_TIMER_SOFT
sam_eth_device.phy_monitor_timer = rt_timer_create("phylnk",
rt_sam_eth_monitor,
(void *)&sam_eth_device,
10*RT_TICK_PER_SECOND,
RT_TIMER_FLAG_PERIODIC);
if (RT_NULL != sam_eth_device.phy_monitor_timer)
{
rt_timer_start(sam_eth_device.phy_monitor_timer);
}
else
{
state = -RT_ERROR;
LOG_E("gmac rt_timer_create faild: %d", state);
}
#else
sam_eth_device.phy_monitor_tid = rt_thread_create("phy",
rt_sam_eth_monitor,
(void *)&sam_eth_device,
1024,
RT_THREAD_PRIORITY_MAX - 2,
2);
if (sam_eth_device.phy_monitor_tid != RT_NULL)
{
rt_thread_startup(sam_eth_device.phy_monitor_tid);
}
else
{
state = -RT_ERROR;
LOG_E("gmac rt_thread_create faild: %d", state);
}
#endif
outs:
return state;
}
INIT_DEVICE_EXPORT(rt_hw_sam_eth_init);
#endif /* BSP_USING_ETH_ARTPI */
/*
* Copyright (c)
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Email Notes
* 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#ifndef __BOARD_SAM_GMAC_H_
#define __BOARD_SAM_GMAC_H_
#include <rtthread.h>
/**
* @brief GMAC duplex type
*/
typedef enum
{
GMAC_HALF_DUPLEX = 0x00, /*!< half duplex */
GMAC_FULL_DUPLEX = 0x01 /*!< full duplex */
} gmac_duplex_type;
/**
* @brief GMAC speed type
*/
typedef enum
{
GMAC_SPEED_10MBPS = 0x00, /*!< 10 mbps */
GMAC_SPEED_100MBPS = 0x01 /*!< 100 mbps */
} gmac_speed_type;
#define CONF_AT24MAC_ADDRESS 0x57
#endif // __BOARD_SAM_GMAC_H_
/*
* Copyright (c)
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Email Notes
* 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <atmel_start.h>
#ifdef SAM_I2C_EXAMPLE
struct sam_i2c_bus
{
struct rt_i2c_bus_device parent;
struct i2c_m_sync_desc *i2c_desc;
char *device_name;
};
#define I2CBUS_NAME "i2c0"
static struct sam_i2c_bus sam_i2c0 =
{
.i2c_desc = &I2C_0,
.device_name = I2CBUS_NAME,
};
static rt_size_t sam_i2c_master_xfer(struct rt_i2c_bus_device *bus,
struct rt_i2c_msg msgs[],
rt_uint32_t num);
static rt_size_t sam_i2c_slave_xfer(struct rt_i2c_bus_device *bus,
struct rt_i2c_msg msgs[],
rt_uint32_t num);
static rt_err_t sam_i2c_bus_control(struct rt_i2c_bus_device *bus,
rt_uint32_t, rt_uint32_t);
static const struct rt_i2c_bus_device_ops sam_i2c_ops =
{
.master_xfer = sam_i2c_master_xfer,
.slave_xfer = sam_i2c_slave_xfer,
.i2c_bus_control = sam_i2c_bus_control,
};
static inline void sam_i2c_update_control(struct rt_i2c_msg *src,
struct _i2c_m_msg *dest)
{
dest->len = (int32_t)src->len;
dest->addr = src->addr;
dest->buffer = src->buf;
/* Get I2C message R/W attribute first */
dest->flags = dest->flags & 0x0001;
if (dest->flags & RT_I2C_ADDR_10BIT)
dest->flags |= I2C_M_TEN;
else
dest->flags |= I2C_M_SEVEN;
}
static rt_size_t sam_i2c_master_xfer(struct rt_i2c_bus_device *bus,
struct rt_i2c_msg msgs[],
rt_uint32_t num)
{
struct sam_i2c_bus *sam_i2c = (struct sam_i2c_bus *)bus;
struct _i2c_m_msg i2c_msg;
rt_size_t i;
RT_ASSERT(bus != RT_NULL);
for (i = 0; i < num; i++)
{
sam_i2c_update_control(&msgs[i], &i2c_msg);
if (i2c_m_sync_transfer(sam_i2c->i2c_desc, &i2c_msg) != 0)
break;
}
return i;
}
static rt_size_t sam_i2c_slave_xfer(struct rt_i2c_bus_device *bus,
struct rt_i2c_msg msgs[],
rt_uint32_t num)
{
return 0;
}
static rt_err_t sam_i2c_bus_control(struct rt_i2c_bus_device *bus,
rt_uint32_t cmd,
rt_uint32_t arg)
{
return RT_ERROR;
struct sam_i2c_bus *sam_i2c = (struct sam_i2c_bus *)bus;
RT_ASSERT(bus != RT_NULL);
switch (cmd)
{
case RT_I2C_DEV_CTRL_CLK:
i2c_m_sync_set_baudrate(sam_i2c->i2c_desc, 0, arg);
break;
default:
return -RT_EIO;
}
return RT_EOK;
}
int rt_hw_i2c_init(void)
{
rt_i2c_bus_device_register(&sam_i2c0.parent, sam_i2c0.device_name);
return 0;
}
#ifdef RT_USING_COMPONENTS_INIT
INIT_BOARD_EXPORT(rt_hw_i2c_init);
#endif
#endif
/*@}*/
......@@ -5,11 +5,11 @@
*
* Change Logs:
* Date Author Email Notes
* 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release
* 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#ifndef __BOARD_SERIAL_H_
#define __BOARD_SERIAL_H_
#ifndef __BOARD_SAM_I2C_H_
#define __BOARD_SAM_I2C_H_
#include <rtthread.h>
......@@ -17,6 +17,6 @@
* @brief External function definitions
*
*/
int rt_hw_uart_init(void);
int rt_hw_i2c_init(void);
#endif // __BOARD_SERIAL_H_
#endif // __BOARD_SAM_I2C_H_
......@@ -16,6 +16,34 @@
/* SAM MCU serial device */
static struct rt_serial_device sam_serial;
static void serial_rxcallback(const struct usart_async_descriptor *const io_descr)
{
(void)io_descr;
/* enter interrupt */
rt_interrupt_enter();
/* Notify Serial driver to process RX data */
rt_hw_serial_isr(&sam_serial, RT_SERIAL_EVENT_RX_IND);
/* leave interrupt */
rt_interrupt_leave();
}
static void serial_txcallback(const struct usart_async_descriptor *const io_descr)
{
(void)io_descr;
/* enter interrupt */
rt_interrupt_enter();
/* Notify Serial driver to process TX done event */
rt_hw_serial_isr(&sam_serial, RT_SERIAL_EVENT_TX_DONE);
/* leave interrupt */
rt_interrupt_leave();
}
/**
* @brief Configure serial port
*
......@@ -25,61 +53,61 @@ static struct rt_serial_device sam_serial;
*/
static rt_err_t serial_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
struct usart_sync_descriptor* desc;
struct usart_async_descriptor* desc;
RT_ASSERT(serial != RT_NULL);
desc = (struct usart_sync_descriptor *)serial->parent.user_data;
desc = (struct usart_async_descriptor *)serial->parent.user_data;
RT_ASSERT(desc != RT_NULL);
RT_ASSERT(cfg != RT_NULL);
usart_sync_disable(desc);
usart_async_disable(desc);
/* Set baudrate */
usart_sync_set_baud_rate(desc, (const uint32_t)cfg->baud_rate);
usart_async_set_baud_rate(desc, (const uint32_t)cfg->baud_rate);
/* Set stop bit */
if (cfg->stop_bits == STOP_BITS_1)
usart_sync_set_stopbits(desc, USART_STOP_BITS_ONE);
usart_async_set_stopbits(desc, USART_STOP_BITS_ONE);
else if (cfg->stop_bits == STOP_BITS_2)
usart_sync_set_stopbits(desc, USART_STOP_BITS_TWO);
usart_async_set_stopbits(desc, USART_STOP_BITS_TWO);
if (cfg->bit_order == BIT_ORDER_LSB)
usart_sync_set_data_order(desc, USART_DATA_ORDER_LSB);
usart_async_set_data_order(desc, USART_DATA_ORDER_LSB);
else if (cfg->bit_order == BIT_ORDER_MSB)
usart_sync_set_data_order(desc, USART_DATA_ORDER_MSB);
usart_async_set_data_order(desc, USART_DATA_ORDER_MSB);
/* Set character size */
switch (cfg->data_bits)
{
case DATA_BITS_5:
usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_5BITS);
usart_async_set_character_size(desc, USART_CHARACTER_SIZE_5BITS);
break;
case DATA_BITS_6:
usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_6BITS);
usart_async_set_character_size(desc, USART_CHARACTER_SIZE_6BITS);
break;
case DATA_BITS_7:
usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_7BITS);
usart_async_set_character_size(desc, USART_CHARACTER_SIZE_7BITS);
break;
case DATA_BITS_8:
usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_8BITS);
usart_async_set_character_size(desc, USART_CHARACTER_SIZE_8BITS);
break;
case DATA_BITS_9:
usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_9BITS);
usart_async_set_character_size(desc, USART_CHARACTER_SIZE_9BITS);
break;
default:
break;
}
if (cfg->parity == PARITY_NONE)
usart_sync_set_parity(desc, USART_PARITY_NONE);
usart_async_set_parity(desc, USART_PARITY_NONE);
else if (cfg->parity == PARITY_ODD)
usart_sync_set_parity(desc, USART_PARITY_ODD);
usart_async_set_parity(desc, USART_PARITY_ODD);
else if (cfg->parity == PARITY_EVEN)
usart_sync_set_parity(desc, USART_PARITY_EVEN);
usart_async_set_parity(desc, USART_PARITY_EVEN);
usart_sync_enable(desc);
usart_async_enable(desc);
return RT_EOK;
}
......@@ -93,10 +121,10 @@ static rt_err_t serial_configure(struct rt_serial_device *serial, struct serial_
*/
static rt_err_t serial_control(struct rt_serial_device *serial, int cmd, void *arg)
{
struct usart_sync_descriptor* desc;
struct usart_async_descriptor* desc;
RT_ASSERT(serial != RT_NULL);
desc = (struct usart_sync_descriptor *)serial->parent.user_data;
desc = (struct usart_async_descriptor *)serial->parent.user_data;
RT_ASSERT(desc != RT_NULL);
......@@ -104,11 +132,11 @@ static rt_err_t serial_control(struct rt_serial_device *serial, int cmd, void *a
{
/* disable interrupt */
case RT_DEVICE_CTRL_CLR_INT:
usart_sync_disable(desc);
usart_async_disable(desc);
break;
/* enable interrupt */
case RT_DEVICE_CTRL_SET_INT:
usart_sync_enable(desc);
usart_async_enable(desc);
break;
/* UART config */
case RT_DEVICE_CTRL_CONFIG :
......@@ -127,14 +155,15 @@ static rt_err_t serial_control(struct rt_serial_device *serial, int cmd, void *a
*/
static int serial_putc(struct rt_serial_device *serial, char c)
{
struct usart_sync_descriptor* desc;
struct usart_async_descriptor* desc;
RT_ASSERT(serial != RT_NULL);
desc = (struct usart_sync_descriptor *)serial->parent.user_data;
desc = (struct usart_async_descriptor *)serial->parent.user_data;
RT_ASSERT(desc != RT_NULL);
io_write(&desc->io, (const uint8_t *)&c, 1);
while (usart_async_is_tx_empty(desc) == 0);
_usart_async_write_byte(&TARGET_IO.device, (uint8_t)c);
return 1;
}
......@@ -150,17 +179,17 @@ static int serial_getc(struct rt_serial_device *serial)
{
char c;
int ch;
struct usart_sync_descriptor* desc;
struct usart_async_descriptor* desc;
RT_ASSERT(serial != RT_NULL);
desc = (struct usart_sync_descriptor *)serial->parent.user_data;
desc = (struct usart_async_descriptor *)serial->parent.user_data;
RT_ASSERT(desc != RT_NULL);
ch = -1;
if (usart_sync_is_rx_not_empty(desc))
if (usart_async_is_rx_not_empty(desc))
{
io_read(&desc->io, (uint8_t *)&c, 1);;
io_read(&desc->io, (uint8_t *)&c, 1);
ch = c & 0xff;
}
......@@ -190,8 +219,12 @@ int rt_hw_uart_init(void)
sam_serial.config = config;
sam_serial.serial_rx = RT_NULL;
sam_serial.serial_rx = RT_NULL;
rt_hw_serial_register(&sam_serial, "uart0",
RT_DEVICE_FLAG_RDWR, (void *)&TARGET_IO);
rt_hw_serial_register(&sam_serial, RT_CONSOLE_DEVICE_NAME,
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX |
RT_DEVICE_FLAG_INT_TX, (void *)&TARGET_IO);
usart_async_register_callback(&TARGET_IO, USART_ASYNC_TXC_CB, serial_txcallback);
usart_async_register_callback(&TARGET_IO, USART_ASYNC_RXC_CB, serial_rxcallback);
return 0;
}
......
......@@ -93,8 +93,32 @@ CONFIG_RT_USING_USER_MAIN=y
CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048
CONFIG_RT_MAIN_THREAD_PRIORITY=10
# CONFIG_RT_USING_LEGACY is not set
# CONFIG_RT_USING_MSH is not set
# CONFIG_RT_USING_DFS is not set
CONFIG_RT_USING_MSH=y
CONFIG_RT_USING_FINSH=y
CONFIG_FINSH_USING_MSH=y
CONFIG_FINSH_THREAD_NAME="tshell"
CONFIG_FINSH_THREAD_PRIORITY=20
CONFIG_FINSH_THREAD_STACK_SIZE=4096
CONFIG_FINSH_USING_HISTORY=y
CONFIG_FINSH_HISTORY_LINES=5
CONFIG_FINSH_USING_SYMTAB=y
CONFIG_FINSH_CMD_SIZE=80
CONFIG_MSH_USING_BUILT_IN_COMMANDS=y
CONFIG_FINSH_USING_DESCRIPTION=y
# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
# CONFIG_FINSH_USING_AUTH is not set
CONFIG_FINSH_ARG_MAX=10
CONFIG_RT_USING_DFS=y
CONFIG_DFS_USING_POSIX=y
CONFIG_DFS_USING_WORKDIR=y
CONFIG_DFS_FILESYSTEMS_MAX=4
CONFIG_DFS_FILESYSTEM_TYPES_MAX=4
CONFIG_DFS_FD_MAX=16
# CONFIG_RT_USING_DFS_MNTTABLE is not set
# CONFIG_RT_USING_DFS_ELMFAT is not set
CONFIG_RT_USING_DFS_DEVFS=y
# CONFIG_RT_USING_DFS_ROMFS is not set
# CONFIG_RT_USING_DFS_RAMFS is not set
# CONFIG_RT_USING_FAL is not set
# CONFIG_RT_USING_LWP is not set
......@@ -102,7 +126,9 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10
# Device Drivers
#
CONFIG_RT_USING_DEVICE_IPC=y
# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set
CONFIG_RT_USING_SYSTEM_WORKQUEUE=y
CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048
CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23
CONFIG_RT_USING_SERIAL=y
CONFIG_RT_USING_SERIAL_V1=y
# CONFIG_RT_USING_SERIAL_V2 is not set
......@@ -111,7 +137,9 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64
# CONFIG_RT_USING_CAN is not set
# CONFIG_RT_USING_HWTIMER is not set
# CONFIG_RT_USING_CPUTIME is not set
# CONFIG_RT_USING_I2C is not set
CONFIG_RT_USING_I2C=y
# CONFIG_RT_I2C_DEBUG is not set
# CONFIG_RT_USING_I2C_BITOPS is not set
# CONFIG_RT_USING_PHY is not set
# CONFIG_RT_USING_PIN is not set
# CONFIG_RT_USING_ADC is not set
......@@ -639,10 +667,12 @@ CONFIG_SOC_SAMC21J18=y
#
CONFIG_SAMC21_CAN0=y
CONFIG_SAMC21_ADC0=y
CONFIG_SAMC21_I2C0=y
#
# Application Demo Config
#
CONFIG_SAM_CAN_EXAMPLE=y
CONFIG_SAM_ADC_EXAMPLE=y
CONFIG_SAM_I2C_EXAMPLE=y
CONFIG_SOC_SAMC21=y
......@@ -34,8 +34,27 @@ if rtconfig.PLATFORM == 'iar':
Export('RTT_ROOT')
Export('rtconfig')
SDK_ROOT = os.path.abspath('./')
if os.path.exists(SDK_ROOT + '/common'):
common_path_prefix = SDK_ROOT + '/common'
else:
common_path_prefix = os.path.dirname(SDK_ROOT) + '/common'
SDK_LIB = common_path_prefix
Export('SDK_LIB')
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False)
sam_board = 'board'
rtconfig.BSP_LIBRARY_TYPE = sam_board
# include libraries
objs.extend(SConscript(os.path.join(common_path_prefix, sam_board, 'SConscript')))
# include drivers
objs.extend(SConscript(os.path.join(common_path_prefix, 'applications', 'SConscript')))
# make a building
DoBuilding(TARGET, objs)
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Email Notes
* 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#include <rtthread.h>
#ifdef RT_USING_FINSH
#include <finsh.h>
#include <shell.h>
#endif
#include "atmel_start.h"
#include "driver_init.h"
#include "utils.h"
#include "can_demo.h"
#ifdef SAM_CAN_EXAMPLE
static volatile enum can_async_interrupt_type can_errors;
static rt_sem_t can_txdone;
static rt_sem_t can_rxdone;
static rt_uint8_t can_stack[ 512 ];
static struct rt_thread can_thread;
/**
* @brief Callback function and should be invoked after call can_async_write.
*
* @note
*
* @param descr is CAN device description.
*
* @return None.
*/
static void can_tx_callback(struct can_async_descriptor *const descr)
{
rt_err_t result;
rt_interrupt_enter();
result = rt_sem_release(can_txdone);
if (RT_EOK != result)
{
#ifndef RT_USING_FINSH
rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__);
#endif
}
rt_interrupt_leave();
}
/**
* @brief Callback function and should be invoked after remote device send.
*
* @note This callback function will be called in CAN interrupt function
*
* @param descr is CAN device description.
*
* @return None.
*/
static void can_rx_callback(struct can_async_descriptor *const descr)
{
rt_err_t result;
rt_interrupt_enter();
result = rt_sem_release(can_rxdone);
if (RT_EOK != result)
{
#ifndef RT_USING_FINSH
rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__);
#endif
}
rt_interrupt_leave();
}
/**
* @brief Callback function and should be invoked after CAN device IRQ handler detects errors happened.
*
* @note This callback function will be called in CAN interrupt function
*
* @param descr is CAN device description.
*
* @return None.
*/
static void can_err_callback(struct can_async_descriptor *const descr,
enum can_async_interrupt_type type)
{
rt_err_t result;
if (type == CAN_IRQ_EW)
{
/* Error warning, Error counter has reached the error warning limit of 96,
* An error count value greater than about 96 indicates a heavily disturbed
* bus. It may be of advantage to provide means to test for this condition.
*/
}
else if (type == CAN_IRQ_EA)
{
/* Error Active State, The CAN node normally take part in bus communication
* and sends an ACTIVE ERROR FLAG when an error has been detected.
*/
}
else if (type == CAN_IRQ_EP)
{
/* Error Passive State, The Can node goes into error passive state if at least
* one of its error counters is greater than 127. It still takes part in bus
* activities, but it sends a passive error frame only, on errors.
*/
}
else if (type == CAN_IRQ_BO)
{
/* Bus Off State, The CAN node is 'bus off' when the TRANSMIT ERROR COUNT is
* greater than or equal to 256.
*/
/* Suspend CAN task and re-initialize CAN module. */
can_errors = type;
rt_interrupt_enter();
result = rt_sem_release(can_rxdone);
if (RT_EOK != result)
{
#ifndef RT_USING_FINSH
rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__);
#endif
}
rt_interrupt_leave();
}
else if (type == CAN_IRQ_DO)
{
/* Data Overrun in receive queue. A message was lost because the messages in
* the queue was not reading and releasing fast enough. There is not enough
* space for a new message in receive queue.
*/
/* Suggest to delete CAN task and re-initialize it. */
can_errors = type;
rt_interrupt_enter();
result = rt_sem_release(can_rxdone);
if (RT_EOK != result)
{
#ifndef RT_USING_FINSH
rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__);
#endif
}
rt_interrupt_leave();
}
};
/**
* @brief Initialize CAN module before task run.
*
* @note This function will set CAN Tx/Rx callback function and filters.
*
* @param None.
*
* @return None.
*/
static inline void can_demo_init(void)
{
struct can_filter filter;
/**
* CAN_Node0_tx_callback callback should be invoked after call
* can_async_write, and remote device should receive message with ID=0x45A
*/
can_async_register_callback(&CAN_0, CAN_ASYNC_TX_CB, (FUNC_PTR)can_tx_callback);
/**
* CAN_0_rx_callback callback should be invoked after call
* can_async_set_filter and remote device send CAN Message with the same
* content as the filter.
*/
can_async_register_callback(&CAN_0, CAN_ASYNC_RX_CB, (FUNC_PTR)can_rx_callback);
/* Should set at least one CAN standard & message filter before enable it. */
filter.id = 0x469;
filter.mask = 0;
can_async_set_filter(&CAN_0, 0, CAN_FMT_STDID, &filter);
/* If set second standard message filter, should increase filter index
* and filter algorithm
* For example: index should set to 1, otherwise it will replace filter 0.
* can_async_set_filter(&CAN_0, 1, CAN_FMT_STDID, &filter); */
filter.id = 0x10000096;
filter.mask = 0;
can_async_set_filter(&CAN_0, 0, CAN_FMT_EXTID, &filter);
can_async_enable(&CAN_0);
}
/**
* @brief CAN task.
*
* @note This task will waiting for CAN RX semaphore and then process input.
*
* @param parameter - task input parameter.
*
* @return None.
*/
static void can_thread_entry(void* parameter)
{
int32_t ret;
rt_err_t result;
uint8_t data[64];
uint32_t count=0;
struct can_message msg;
while (1)
{
#ifndef RT_USING_FINSH
rt_kprintf("can task run count : %d\r\n",count);
#endif
count++;
result = rt_sem_take(can_rxdone, RT_WAITING_FOREVER);
if (RT_EOK != result)
continue;
do
{
/* Process the incoming packet. */
ret = can_async_read(&CAN_0, &msg);
if (ret == ERR_NONE)
{
#ifndef RT_USING_FINSH
rt_kprintf("CAN RX Message is % frame\r\n",
msg.type == CAN_TYPE_DATA ? "data" : "remote");
rt_kprintf("CAN RX Message is % frame\r\n",
msg.type == CAN_FMT_STDID ? "Standard" : "Extended");
rt_kprintf("can RX Message ID: 0x%X length: %d\r\n", msg.id, msg.len);
rt_kprintf("CAN RX Message content: ");
for (uint8_t i = 0; i < msg.len; i++)
rt_kprintf("0x%02X ", data[i]);
rt_kprintf("\r\n");
#endif
}
} while (ret == ERR_NONE); /* Get all data stored in CAN RX FIFO */
/* CAN task got CAN error message, handler CAN Error Status */
if ((can_errors == CAN_IRQ_BO) || (can_errors == CAN_IRQ_DO))
{
can_async_init(&CAN_0, CAN1);
}
}
}
/**
* @brief Call this function will to send a CAN message.
*
* @note
*
* @param msg - message to be sent, timeouts - wait timeouts for Tx completion.
*
* @return RT_OK or RT_ERROR.
*/
rt_err_t can_send_message(struct can_message *msg, rt_uint32_t timeouts)
{
rt_err_t result;
if (RT_NULL == msg)
{
rt_kprintf("can_send_message input message error\r\n");
return RT_ERROR;
}
can_async_write(&CAN_0, msg);
result = rt_sem_take(can_rxdone, timeouts);
return result;
}
/**
* @brief Call this function will create a CAN task.
*
* @note Should create Tx/Rx semaphore before run task.
*
* @param None.
*
* @return RT_OK or -RT_ERROR.
*/
rt_err_t can_demo_run(void)
{
rt_err_t result;
can_rxdone = rt_sem_create("can_rx", 0, RT_IPC_FLAG_FIFO);
if (RT_NULL == can_rxdone)
{
rt_kprintf("can_rx semaphore create failed\r\n");
return (-RT_ERROR);
}
can_txdone = rt_sem_create("can_tx", 0, RT_IPC_FLAG_FIFO);
if (RT_NULL == can_txdone)
{
rt_kprintf("can_tx semaphore create failed\r\n");
return (-RT_ERROR);
}
can_demo_init();
/* initialize CAN thread */
result = rt_thread_init(&can_thread,
"can",
can_thread_entry,
RT_NULL,
(rt_uint8_t*)&can_stack[0],
sizeof(can_stack),
RT_THREAD_PRIORITY_MAX/3,
5);
if (result == RT_EOK)
{
rt_thread_startup(&can_thread);
}
return result;
}
#endif
/*@}*/
......@@ -5,7 +5,7 @@
*
* Change Logs:
* Date Author Email Notes
* 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release
* 2022-04-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#include <rtthread.h>
......@@ -22,6 +22,14 @@
#include "can_demo.h"
#endif
#ifdef SAM_I2C_EXAMPLE
#include "i2c_demo.h"
#endif
#ifdef SAM_ADC_EXAMPLE
#include "adc_demo.h"
#endif
static rt_uint8_t led_stack[ 512 ];
static struct rt_thread led_thread;
......@@ -63,6 +71,14 @@ int main(void)
can_demo_run();
#endif
#ifdef SAM_I2C_EXAMPLE
i2c_demo_run();
#endif
#ifdef SAM_ADC_EXAMPLE
adc_demo_run();
#endif
return 0;
}
......
......@@ -32,6 +32,11 @@ menu "Onboard Peripheral Drivers"
config SAMC21_ADC0
bool "Enable ADC0"
default false
config SAMC21_I2C0
bool "Enable I2C0"
default false
endmenu
menu "Application Demo Config"
......@@ -49,4 +54,10 @@ menu "Application Demo Config"
help
Add ADC example task to project
config SAM_I2C_EXAMPLE
bool "Enable SAM I2C Example"
depends on SAMC21_I2C0
default true
help
Add I2C example task to project
endmenu
......@@ -25,13 +25,14 @@ static struct io_descriptor* g_stdio;
void rt_hw_console_output(const char *str)
{
io_write(g_stdio, (uint8_t *)str, strlen(str));
while (TARGET_IO.stat != 0);
}
RTM_EXPORT(rt_hw_console_output);
static inline void hw_board_init_usart(void)
{
usart_sync_get_io_descriptor(&TARGET_IO, &g_stdio);
usart_sync_enable(&TARGET_IO);
usart_async_get_io_descriptor(&TARGET_IO, &g_stdio);
usart_async_enable(&TARGET_IO);
}
/**
......
/*
* Copyright (c)
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Email Notes
* 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <atmel_start.h>
/* SAM MCU serial device */
static struct rt_serial_device sam_serial;
/**
* @brief Configure serial port
*
* This function will configure UART baudrate, parity and so on.
*
* @return RT_EOK.
*/
static rt_err_t serial_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
struct usart_sync_descriptor* desc;
RT_ASSERT(serial != RT_NULL);
desc = (struct usart_sync_descriptor *)serial->parent.user_data;
RT_ASSERT(desc != RT_NULL);
RT_ASSERT(cfg != RT_NULL);
usart_sync_disable(desc);
/* Set baudrate */
usart_sync_set_baud_rate(desc, (const uint32_t)cfg->baud_rate);
/* Set stop bit */
if (cfg->stop_bits == STOP_BITS_1)
usart_sync_set_stopbits(desc, USART_STOP_BITS_ONE);
else if (cfg->stop_bits == STOP_BITS_2)
usart_sync_set_stopbits(desc, USART_STOP_BITS_TWO);
if (cfg->bit_order == BIT_ORDER_LSB)
usart_sync_set_data_order(desc, USART_DATA_ORDER_LSB);
else if (cfg->bit_order == BIT_ORDER_MSB)
usart_sync_set_data_order(desc, USART_DATA_ORDER_MSB);
/* Set character size */
switch (cfg->data_bits)
{
case DATA_BITS_5:
usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_5BITS);
break;
case DATA_BITS_6:
usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_6BITS);
break;
case DATA_BITS_7:
usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_7BITS);
break;
case DATA_BITS_8:
usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_8BITS);
break;
case DATA_BITS_9:
usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_9BITS);
break;
default:
break;
}
if (cfg->parity == PARITY_NONE)
usart_sync_set_parity(desc, USART_PARITY_NONE);
else if (cfg->parity == PARITY_ODD)
usart_sync_set_parity(desc, USART_PARITY_ODD);
else if (cfg->parity == PARITY_EVEN)
usart_sync_set_parity(desc, USART_PARITY_EVEN);
usart_sync_enable(desc);
return RT_EOK;
}
/**
* @brief Control serial port
*
* This function provide UART enable/disable control.
*
* @return RT_EOK.
*/
static rt_err_t serial_control(struct rt_serial_device *serial, int cmd, void *arg)
{
struct usart_sync_descriptor* desc;
RT_ASSERT(serial != RT_NULL);
desc = (struct usart_sync_descriptor *)serial->parent.user_data;
RT_ASSERT(desc != RT_NULL);
switch (cmd)
{
/* disable interrupt */
case RT_DEVICE_CTRL_CLR_INT:
usart_sync_disable(desc);
break;
/* enable interrupt */
case RT_DEVICE_CTRL_SET_INT:
usart_sync_enable(desc);
break;
/* UART config */
case RT_DEVICE_CTRL_CONFIG :
break;
}
return RT_EOK;
}
/**
* @brief Serial sends a char
*
* This function will send a char to the UART
*
* @return 1.
*/
static int serial_putc(struct rt_serial_device *serial, char c)
{
struct usart_sync_descriptor* desc;
RT_ASSERT(serial != RT_NULL);
desc = (struct usart_sync_descriptor *)serial->parent.user_data;
RT_ASSERT(desc != RT_NULL);
io_write(&desc->io, (const uint8_t *)&c, 1);
return 1;
}
/**
* @brief Serial gets a char
*
* This function will get a char from the UART
*
* @return received char character or -1 if no char received.
*/
static int serial_getc(struct rt_serial_device *serial)
{
char c;
int ch;
struct usart_sync_descriptor* desc;
RT_ASSERT(serial != RT_NULL);
desc = (struct usart_sync_descriptor *)serial->parent.user_data;
RT_ASSERT(desc != RT_NULL);
ch = -1;
if (usart_sync_is_rx_not_empty(desc))
{
io_read(&desc->io, (uint8_t *)&c, 1);;
ch = c & 0xff;
}
return ch;
}
static const struct rt_uart_ops sam_serial_ops =
{
serial_configure,
serial_control,
serial_putc,
serial_getc,
};
/**
* @brief Initialize the UART
*
* This function initialize the UART
*
* @return None.
*/
int rt_hw_uart_init(void)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
sam_serial.ops = &sam_serial_ops;
sam_serial.config = config;
sam_serial.serial_rx = RT_NULL;
sam_serial.serial_rx = RT_NULL;
rt_hw_serial_register(&sam_serial, "uart0",
RT_DEVICE_FLAG_RDWR, (void *)&TARGET_IO);
return 0;
}
/*@}*/
......@@ -42,17 +42,21 @@
<description>Atmel Start Framework</description>
<RTE_Components_h>#define ATMEL_START</RTE_Components_h>
<files>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/adc_sync.rst"/>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/can_async.rst"/>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/flash.rst"/>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/usart_sync.rst"/>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/i2c_master_sync.rst"/>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/usart_async.rst"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_atomic.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_can_async.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_delay.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_flash.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_gpio.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_i2c_m_sync.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_init.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_io.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_sleep.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_adc_dma.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_can.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_can_async.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_core.h"/>
......@@ -78,6 +82,7 @@
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_delay.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_flash.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_gpio.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_i2c_m_sync.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_init.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_io.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_sleep.c"/>
......@@ -90,9 +95,11 @@
<file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_increment_macro.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_list.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_repeat_macro.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_ringbuffer.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_assert.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_event.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_list.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_ringbuffer.c"/>
<file category="source" condition="GCC" name="hal/utils/src/utils_syscalls.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hpl/divas/hpl_divas.c"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hri/hri_ac_c21.h"/>
......@@ -138,7 +145,10 @@
<file category="header" condition="ARMCC, GCC, IAR" name="examples/driver_examples.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="examples/driver_examples.c"/>
<file category="header" condition="ARMCC, GCC, IAR" name="config/hpl_divas_config.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_usart_sync.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_adc_sync.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_usart_async.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_adc_async.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_adc_sync.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_missing_features.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_reset.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_spi_m_async.h"/>
......@@ -148,8 +158,11 @@
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_spi_s_sync.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usart_async.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usart_sync.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_usart_sync.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_adc_sync.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_usart_async.c"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/parts.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hpl/adc/hpl_adc.c"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hpl/adc/hpl_adc_base.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hpl/can/hpl_can.c"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hpl/can/hpl_can_base.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hpl/core/hpl_core_m0plus_base.c"/>
......@@ -168,6 +181,7 @@
<file category="source" condition="ARMCC, GCC, IAR" name="hpl/sercom/hpl_sercom.c"/>
<file category="header" condition="ARMCC, GCC, IAR" name="atmel_start.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="atmel_start.c"/>
<file attr="config" category="header" condition="ARMCC, GCC, IAR" name="config/hpl_adc_config.h"/>
<file attr="config" category="header" condition="ARMCC, GCC, IAR" name="config/hpl_can_config.h"/>
<file attr="config" category="header" condition="ARMCC, GCC, IAR" name="config/hpl_dmac_config.h"/>
<file attr="config" category="header" condition="ARMCC, GCC, IAR" name="config/hpl_gclk_config.h"/>
......@@ -183,6 +197,7 @@
<file category="include" condition="ARMCC, GCC, IAR" name="examples"/>
<file category="include" condition="ARMCC, GCC, IAR" name="hal/include"/>
<file category="include" condition="ARMCC, GCC, IAR" name="hal/utils/include"/>
<file category="include" condition="ARMCC, GCC, IAR" name="hpl/adc"/>
<file category="include" condition="ARMCC, GCC, IAR" name="hpl/can"/>
<file category="include" condition="ARMCC, GCC, IAR" name="hpl/core"/>
<file category="include" condition="ARMCC, GCC, IAR" name="hpl/divas"/>
......
......@@ -11,8 +11,10 @@ CPPDEFINES = []
CPPDEFINES += [rtconfig.DEVICE_TYPE]
# The set of source files associated with this SConscript file.
src = Glob('hal/src/*.c')
src += Glob('hal/utils/src/*.c')
src += Glob('hpl/adc/*.c')
src += Glob('hpl/can/*.c')
src += Glob('hpl/core/*.c')
src += Glob('hpl/divas/*.c')
......@@ -45,12 +47,15 @@ path = [
cwd + '/config',
cwd + '/hal/include',
cwd + '/hal/utils/include',
cwd + '/hpl/adc',
cwd + '/hpl/can',
cwd + '/hpl/core',
cwd + '/hpl/gclk',
cwd + '/hpl/pm',
cwd + '/hpl/port',
cwd + '/hri',
cwd + '/../board',
cwd + '/../../common/applications',
cwd + '/samc21/include']
group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
......
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
ifdef SystemRoot
SHELL = cmd.exe
MK_DIR = mkdir
else
ifeq ($(shell uname), Linux)
MK_DIR = mkdir -p
endif
ifeq ($(shell uname | cut -d _ -f 1), CYGWIN)
MK_DIR = mkdir -p
endif
ifeq ($(shell uname | cut -d _ -f 1), MINGW32)
MK_DIR = mkdir -p
endif
ifeq ($(shell uname | cut -d _ -f 1), MINGW64)
MK_DIR = mkdir -p
endif
endif
# List the subdirectories for creating object files
SUB_DIRS += \
\
hpl/pm \
hpl/osc32kctrl \
hpl/can \
hpl/dmac \
samc21/armcc/Device/SAMC21/Source/ARM \
hal/src \
hpl/mclk \
hal/utils/src \
hpl/sercom \
examples \
hpl/gclk \
hpl/oscctrl \
samc21/armcc/Device/SAMC21/Source \
hpl/nvmctrl \
hpl/core \
hpl/divas
# List the object files
OBJS += \
hal/src/hal_io.o \
hal/src/hal_can_async.o \
hpl/can/hpl_can.o \
hpl/nvmctrl/hpl_nvmctrl.o \
samc21/armcc/Device/SAMC21/Source/ARM/startup_SAMC21.o \
hal/src/hal_delay.o \
hpl/oscctrl/hpl_oscctrl.o \
hpl/core/hpl_init.o \
hal/utils/src/utils_list.o \
hpl/core/hpl_core_m0plus_base.o \
hal/utils/src/utils_assert.o \
hpl/dmac/hpl_dmac.o \
hpl/pm/hpl_pm.o \
hal/src/hal_usart_sync.o \
hpl/mclk/hpl_mclk.o \
hpl/gclk/hpl_gclk.o \
hal/src/hal_flash.o \
hal/src/hal_init.o \
main.o \
hpl/osc32kctrl/hpl_osc32kctrl.o \
examples/driver_examples.o \
driver_init.o \
samc21/armcc/Device/SAMC21/Source/system_samc21.o \
hpl/sercom/hpl_sercom.o \
hal/src/hal_gpio.o \
hpl/divas/hpl_divas.o \
hal/utils/src/utils_event.o \
hal/src/hal_sleep.o \
atmel_start.o \
hal/src/hal_atomic.o
OBJS_AS_ARGS += \
"hal/src/hal_io.o" \
"hal/src/hal_can_async.o" \
"hpl/can/hpl_can.o" \
"hpl/nvmctrl/hpl_nvmctrl.o" \
"samc21/armcc/Device/SAMC21/Source/ARM/startup_SAMC21.o" \
"hal/src/hal_delay.o" \
"hpl/oscctrl/hpl_oscctrl.o" \
"hpl/core/hpl_init.o" \
"hal/utils/src/utils_list.o" \
"hpl/core/hpl_core_m0plus_base.o" \
"hal/utils/src/utils_assert.o" \
"hpl/dmac/hpl_dmac.o" \
"hpl/pm/hpl_pm.o" \
"hal/src/hal_usart_sync.o" \
"hpl/mclk/hpl_mclk.o" \
"hpl/gclk/hpl_gclk.o" \
"hal/src/hal_flash.o" \
"hal/src/hal_init.o" \
"main.o" \
"hpl/osc32kctrl/hpl_osc32kctrl.o" \
"examples/driver_examples.o" \
"driver_init.o" \
"samc21/armcc/Device/SAMC21/Source/system_samc21.o" \
"hpl/sercom/hpl_sercom.o" \
"hal/src/hal_gpio.o" \
"hpl/divas/hpl_divas.o" \
"hal/utils/src/utils_event.o" \
"hal/src/hal_sleep.o" \
"atmel_start.o" \
"hal/src/hal_atomic.o"
# List the dependency files
DEPS := $(OBJS:%.o=%.d)
DEPS_AS_ARGS += \
"hal/utils/src/utils_event.d" \
"hal/src/hal_io.d" \
"hal/src/hal_can_async.d" \
"hpl/can/hpl_can.d" \
"samc21/armcc/Device/SAMC21/Source/ARM/startup_SAMC21.d" \
"hpl/nvmctrl/hpl_nvmctrl.d" \
"hpl/core/hpl_core_m0plus_base.d" \
"hal/utils/src/utils_list.d" \
"hpl/dmac/hpl_dmac.d" \
"hal/utils/src/utils_assert.d" \
"hal/src/hal_delay.d" \
"hpl/core/hpl_init.d" \
"hpl/pm/hpl_pm.d" \
"hal/src/hal_flash.d" \
"hpl/gclk/hpl_gclk.d" \
"hal/src/hal_init.d" \
"hal/src/hal_usart_sync.d" \
"hpl/mclk/hpl_mclk.d" \
"driver_init.d" \
"samc21/armcc/Device/SAMC21/Source/system_samc21.d" \
"hpl/osc32kctrl/hpl_osc32kctrl.d" \
"main.d" \
"examples/driver_examples.d" \
"hpl/divas/hpl_divas.d" \
"hal/src/hal_sleep.d" \
"hpl/sercom/hpl_sercom.d" \
"hal/src/hal_gpio.d" \
"hal/src/hal_atomic.d" \
"hpl/oscctrl/hpl_oscctrl.d" \
"atmel_start.d"
OUTPUT_FILE_NAME :=AtmelStart
QUOTE := "
OUTPUT_FILE_PATH +=$(OUTPUT_FILE_NAME).elf
OUTPUT_FILE_PATH_AS_ARGS +=$(OUTPUT_FILE_NAME).elf
vpath %.c ../
vpath %.s ../
vpath %.S ../
# All Target
all: $(SUB_DIRS) $(OUTPUT_FILE_PATH)
# Linker target
$(OUTPUT_FILE_PATH): $(OBJS)
@echo Building target: $@
@echo Invoking: ARMCC Linker
$(QUOTE)armlink$(QUOTE) --ro-base 0x00000000 --entry 0x00000000 --rw-base 0x20000000 --entry Reset_Handler --first __Vectors \
--strict --summary_stderr --info summarysizes --map --xref --callgraph --symbols \
--info sizes --info totals --info unused --info veneers --list $(OUTPUT_FILE_NAME).map \
-o $(OUTPUT_FILE_NAME).elf --cpu Cortex-M0+ \
$(OBJS_AS_ARGS)
@echo Finished building target: $@
# Compiler target(s)
%.o: %.c
@echo Building file: $<
@echo ARMCC Compiler
$(QUOTE)armcc$(QUOTE) --c99 -c -DDEBUG -O1 -g --apcs=interwork --split_sections --cpu Cortex-M0+ -D__SAMC21J18A__ \
-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/can" -I"../hpl/core" -I"../hpl/divas" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/sercom" -I"../hri" -I"../" -I"../CMSIS/Core/Include" -I"../samc21/include" \
--depend "$@" -o "$@" "$<"
@echo Finished building: $<
%.o: %.s
@echo Building file: $<
@echo ARMCC Assembler
$(QUOTE)armasm$(QUOTE) -g --apcs=interwork --cpu Cortex-M0+ --pd "D__SAMC21J18A__ SETA 1" \
-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/can" -I"../hpl/core" -I"../hpl/divas" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/sercom" -I"../hri" -I"../" -I"../CMSIS/Core/Include" -I"../samc21/include" \
--depend "$(@:%.o=%.d)" -o "$@" "$<"
@echo Finished building: $<
%.o: %.S
@echo Building file: $<
@echo ARMCC Preprocessing Assembler
$(QUOTE)armcc$(QUOTE) --c99 -c -DDEBUG -O1 -g --apcs=interwork --split_sections --cpu Cortex-M0+ -D__SAMC21J18A__ \
-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/can" -I"../hpl/core" -I"../hpl/divas" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/sercom" -I"../hri" -I"../" -I"../CMSIS/Core/Include" -I"../samc21/include" \
--depend "$@" -o "$@" "$<"
@echo Finished building: $<
# Detect changes in the dependent files and recompile the respective object files.
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(DEPS)),)
-include $(DEPS)
endif
endif
$(SUB_DIRS):
$(MK_DIR) "$@"
clean:
rm -f $(OBJS_AS_ARGS)
rm -f $(OUTPUT_FILE_PATH)
rm -f $(DEPS_AS_ARGS)
rm -f $(OUTPUT_FILE_NAME).map $(OUTPUT_FILE_NAME).elf
......@@ -22,6 +22,64 @@ application:
configuration: null
middlewares: {}
drivers:
ADC_0:
user_label: ADC_0
definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::ADC0::driver_config_definition::ADC::HAL:Driver:ADC.Sync
functionality: ADC
api: HAL:Driver:ADC_Sync
configuration:
adc_advanced_settings: true
adc_arch_adjres: 0
adc_arch_corren: false
adc_arch_dbgrun: false
adc_arch_dualsel: BOTH
adc_arch_event_settings: false
adc_arch_flushei: false
adc_arch_flushinv: false
adc_arch_gaincorr: 0
adc_arch_leftadj: false
adc_arch_offcomp: false
adc_arch_offsetcorr: 0
adc_arch_ondemand: false
adc_arch_r2r: false
adc_arch_refcomp: false
adc_arch_resrdyeo: false
adc_arch_runstdby: false
adc_arch_samplen: 0
adc_arch_samplenum: 1 sample
adc_arch_seqen: 0
adc_arch_slaveen: false
adc_arch_startei: false
adc_arch_startinv: false
adc_arch_winlt: 0
adc_arch_winmode: No window mode
adc_arch_winmoneo: false
adc_arch_winut: 0
adc_differential_mode: false
adc_freerunning_mode: false
adc_pinmux_negative: I/O ground
adc_pinmux_positive: ADC AIN0 pin
adc_prescaler: Peripheral clock divided by 2
adc_reference: Internal bandgap reference
adc_resolution: 16-bit (averaging must be enabled)
optional_signals:
- identifier: ADC_0:AIN/10
pad: PA10
mode: Enabled
configuration: null
definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::optional_signal_definition::ADC0.AIN.10
name: ADC0/AIN/10
label: AIN/10
variant: null
clocks:
domain_group:
nodes:
- name: ADC
input: Generic clock generator 0
external: false
external_frequency: 0
configuration:
adc_gclk_selection: Generic clock generator 0
DMAC:
user_label: DMAC
definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::DMAC::driver_config_definition::DMAC::HAL:HPL:DMAC
......@@ -589,13 +647,53 @@ drivers:
variant: null
clocks:
domain_group: null
I2C_0:
user_label: I2C_0
definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::SERCOM0::driver_config_definition::I2C.Master.Standard~2FFast-mode::HAL:Driver:I2C.Master.Sync
functionality: I2C
api: HAL:Driver:I2C_Master_Sync
configuration:
i2c_master_advanced: true
i2c_master_arch_dbgstop: Keep running
i2c_master_arch_inactout: 20-21 SCL cycle time-out(200-210us)
i2c_master_arch_lowtout: true
i2c_master_arch_mexttoen: true
i2c_master_arch_runstdby: false
i2c_master_arch_sdahold: 300-600ns hold time
i2c_master_arch_sexttoen: false
i2c_master_arch_trise: 215
i2c_master_baud_rate: 100000
optional_signals: []
variant:
specification: SDA=0, SCL=1
required_signals:
- name: SERCOM0/PAD/0
pad: PA08
label: SDA
- name: SERCOM0/PAD/1
pad: PA09
label: SCL
clocks:
domain_group:
nodes:
- name: Core
input: Generic clock generator 0
external: false
external_frequency: 0
- name: Slow
input: Generic clock generator 1
external: false
external_frequency: 0
configuration:
core_gclk_selection: Generic clock generator 0
slow_gclk_selection: Generic clock generator 1
TARGET_IO:
user_label: TARGET_IO
definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::SERCOM4::driver_config_definition::UART::HAL:Driver:USART.Sync
definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::SERCOM4::driver_config_definition::UART::HAL:Driver:USART.Async
functionality: USART
api: HAL:Driver:USART_Sync
api: HAL:Driver:USART_Async
configuration:
usart_advanced: false
usart_advanced: true
usart_arch_clock_mode: USART with internal clock
usart_arch_cloden: false
usart_arch_dbgstop: Keep running
......@@ -703,6 +801,24 @@ drivers:
configuration:
can_gclk_selection: Generic clock generator 0
pads:
PA08:
name: PA08
definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::pad::PA08
mode: I2C
user_label: PA08
configuration: null
PA09:
name: PA09
definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::pad::PA09
mode: I2C
user_label: PA09
configuration: null
PA10:
name: PA10
definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::pad::PA10
mode: Analog
user_label: PA10
configuration: null
PB10:
name: PB10
definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::pad::PB10
......
......@@ -22,6 +22,9 @@
#define GPIO_PIN_FUNCTION_H 7
#define GPIO_PIN_FUNCTION_I 8
#define PA08 GPIO(GPIO_PORTA, 8)
#define PA09 GPIO(GPIO_PORTA, 9)
#define PA10 GPIO(GPIO_PORTA, 10)
#define LED0 GPIO(GPIO_PORTA, 15)
#define PA24 GPIO(GPIO_PORTA, 24)
#define PA25 GPIO(GPIO_PORTA, 25)
......
/* Auto-generated config file hpl_adc_config.h */
#ifndef HPL_ADC_CONFIG_H
#define HPL_ADC_CONFIG_H
// <<< Use Configuration Wizard in Context Menu >>>
#ifndef CONF_ADC_0_ENABLE
#define CONF_ADC_0_ENABLE 1
#endif
// <h> Basic Configuration
// <o> Conversion Result Resolution
// <0x0=>12-bit
// <0x1=>16-bit (averaging must be enabled)
// <0x2=>10-bit
// <0x3=>8-bit
// <i> Defines the bit resolution for the ADC sample values (RESSEL)
// <id> adc_resolution
#ifndef CONF_ADC_0_RESSEL
#define CONF_ADC_0_RESSEL 0x1
#endif
// <o> Reference Selection
// <0x0=>Internal bandgap reference
// <0x1=>1/1.6 VDDANA
// <0x2=>1/2 VDDANA (only for VDDANA > 2.0V)
// <0x3=>External reference A
// <0x4=>DAC internal output
// <0x5=>VDDANA
// <i> Select the reference for the ADC (REFSEL)
// <id> adc_reference
#ifndef CONF_ADC_0_REFSEL
#define CONF_ADC_0_REFSEL 0x0
#endif
// <o> Prescaler configuration
// <0x0=>Peripheral clock divided by 2
// <0x1=>Peripheral clock divided by 4
// <0x2=>Peripheral clock divided by 8
// <0x3=>Peripheral clock divided by 16
// <0x4=>Peripheral clock divided by 32
// <0x5=>Peripheral clock divided by 64
// <0x6=>Peripheral clock divided by 128
// <0x7=>Peripheral clock divided by 256
// <i> These bits define the ADC clock relative to the peripheral clock (PRESCALER)
// <id> adc_prescaler
#ifndef CONF_ADC_0_PRESCALER
#define CONF_ADC_0_PRESCALER 0x0
#endif
// <q> Free Running Mode
// <i> When enabled, the ADC is in free running mode and a new conversion will be initiated when a previous conversion completes. (FREERUN)
// <id> adc_freerunning_mode
#ifndef CONF_ADC_0_FREERUN
#define CONF_ADC_0_FREERUN 0
#endif
// <q> Differential Mode
// <i> In differential mode, the voltage difference between the MUXPOS and MUXNEG inputs will be converted by the ADC. (DIFFMODE)
// <id> adc_differential_mode
#ifndef CONF_ADC_0_DIFFMODE
#define CONF_ADC_0_DIFFMODE 0
#endif
// <o> Positive Mux Input Selection
// <0x00=>ADC AIN0 pin
// <0x01=>ADC AIN1 pin
// <0x02=>ADC AIN2 pin
// <0x03=>ADC AIN3 pin
// <0x04=>ADC AIN4 pin
// <0x05=>ADC AIN5 pin
// <0x06=>ADC AIN6 pin
// <0x07=>ADC AIN7 pin
// <0x08=>ADC AIN8 pin
// <0x09=>ADC AIN9 pin
// <0x0A=>ADC AIN10 pin
// <0x0B=>ADC AIN11 pin
// <0x19=>Bandgap voltage
// <0x1A=>1/4 scaled core supply
// <0x1B=>1/4 scaled I/O supply
// <0x1C=>DAC output
// <i> These bits define the Mux selection for the positive ADC input. (MUXPOS)
// <id> adc_pinmux_positive
#ifndef CONF_ADC_0_MUXPOS
#define CONF_ADC_0_MUXPOS 0x0
#endif
// <o> Negative Mux Input Selection
// <0x00=>ADC AIN0 pin
// <0x01=>ADC AIN1 pin
// <0x02=>ADC AIN2 pin
// <0x03=>ADC AIN3 pin
// <0x04=>ADC AIN4 pin
// <0x05=>ADC AIN5 pin
// <0x18=>Internal ground
// <0x19=>I/O ground
// <i> These bits define the Mux selection for the negative ADC input. (MUXNEG)
// <id> adc_pinmux_negative
#ifndef CONF_ADC_0_MUXNEG
#define CONF_ADC_0_MUXNEG 0x19
#endif
// </h>
// <e> Advanced Configuration
// <id> adc_advanced_settings
#ifndef CONF_ADC_0_ADVANCED
#define CONF_ADC_0_ADVANCED 1
#endif
// <q> Slave enable
// <i> Will enable master/slave operation and only available in slave instance
// <id> adc_arch_slaveen
#ifndef CONF_ADC_0_SLAVEEN
#define CONF_ADC_0_SLAVEEN 0
#endif
// <o> Dual mode trigger selection
// <0x0=>BOTH
// <0x1=>INTERLEAVE
// <i> These bits define the trigger mode. (DUALSEL)
// <id> adc_arch_dualsel
#ifndef CONF_ADC_0_DUALSEL
#define CONF_ADC_0_DUALSEL 0x0
#endif
// <q> Rail-to-Rail operation
// <i> This bit enable R2R operation (R2R)
// <id> adc_arch_r2r
#ifndef CONF_ADC_0_R2R
#define CONF_ADC_0_R2R 0
#endif
// <q> Run in standby
// <i> Indicates whether the ADC will continue running in standby sleep mode or not (RUNSTDBY)
// <id> adc_arch_runstdby
#ifndef CONF_ADC_0_RUNSTDBY
#define CONF_ADC_0_RUNSTDBY 0
#endif
// <q>Debug Run
// <i> If enabled, the ADC is running if the CPU is halted by an external debugger. (DBGRUN)
// <id> adc_arch_dbgrun
#ifndef CONF_ADC_0_DBGRUN
#define CONF_ADC_0_DBGRUN 0
#endif
// <q> On Demand Control
// <i> Will keep the ADC peripheral running if requested by other peripherals (ONDEMAND)
// <id> adc_arch_ondemand
#ifndef CONF_ADC_0_ONDEMAND
#define CONF_ADC_0_ONDEMAND 0
#endif
// <q> Left-Adjusted Result
// <i> When enabled, the ADC conversion result is left-adjusted in the RESULT register. The high byte of the 12-bit result will be present in the upper part of the result register. (LEFTADJ)
// <id> adc_arch_leftadj
#ifndef CONF_ADC_0_LEFTADJ
#define CONF_ADC_0_LEFTADJ 0
#endif
// <q> Reference Buffer Offset Compensation Enable
// <i> The accuracy of the gain stage can be increased by enabling the reference buffer offset compensation. This will decrease the input impedance and thus increase the start-up time of the reference. (REFCOMP)
// <id> adc_arch_refcomp
#ifndef CONF_ADC_0_REFCOMP
#define CONF_ADC_0_REFCOMP 0
#endif
// <q>Comparator Offset Compensation Enable
// <i> This bit indicates whether the Comparator Offset Compensation is enabled or not (OFFCOMP)
// <id> adc_arch_offcomp
#ifndef CONF_ADC_0_OFFCOMP
#define CONF_ADC_0_OFFCOMP 0
#endif
// <q> Digital Correction Logic Enabled
// <i> When enabled, the ADC conversion result in the RESULT register is then corrected for gain and offset based on the values in the GAINCAL and OFFSETCAL registers. (CORREN)
// <id> adc_arch_corren
#ifndef CONF_ADC_0_CORREN
#define CONF_ADC_0_CORREN 0
#endif
// <o> Offset Correction Value <0-4095>
// <i> If the digital correction logic is enabled (CTRLB.CORREN = 1), these bits define how the ADC conversion result is compensated for offset error before being written to the Result register. (OFFSETCORR)
// <id> adc_arch_offsetcorr
#ifndef CONF_ADC_0_OFFSETCORR
#define CONF_ADC_0_OFFSETCORR 0
#endif
// <o> Gain Correction Value <0-4095>
// <i> If the digital correction logic is enabled (CTRLB.CORREN = 1), these bits define how the ADC conversion result is compensated for gain error before being written to the result register. (GAINCORR)
// <id> adc_arch_gaincorr
#ifndef CONF_ADC_0_GAINCORR
#define CONF_ADC_0_GAINCORR 0
#endif
// <o> Adjusting Result / Division Coefficient <0-7>
// <i> These bits define the division coefficient in 2n steps. (ADJRES)
// <id> adc_arch_adjres
#ifndef CONF_ADC_0_ADJRES
#define CONF_ADC_0_ADJRES 0x0
#endif
// <o.0..10> Number of Samples to be Collected
// <0x0=>1 sample
// <0x1=>2 samples
// <0x2=>4 samples
// <0x3=>8 samples
// <0x4=>16 samples
// <0x5=>32 samples
// <0x6=>64 samples
// <0x7=>128 samples
// <0x8=>256 samples
// <0x9=>512 samples
// <0xA=>1024 samples
// <i> Define how many samples should be added together.The result will be available in the Result register (SAMPLENUM)
// <id> adc_arch_samplenum
#ifndef CONF_ADC_0_SAMPLENUM
#define CONF_ADC_0_SAMPLENUM 0x0
#endif
// <o> Sampling Time Length <0-63>
// <i> These bits control the ADC sampling time in number of CLK_ADC cycles, depending of the prescaler value, thus controlling the ADC input impedance. (SAMPLEN)
// <id> adc_arch_samplen
#ifndef CONF_ADC_0_SAMPLEN
#define CONF_ADC_0_SAMPLEN 0
#endif
// <o> Window Monitor Mode
// <0x0=>No window mode
// <0x1=>Mode 1: RESULT above lower threshold
// <0x2=>Mode 2: RESULT beneath upper threshold
// <0x3=>Mode 3: RESULT inside lower and upper threshold
// <0x4=>Mode 4: RESULT outside lower and upper threshold
// <i> These bits enable and define the window monitor mode. (WINMODE)
// <id> adc_arch_winmode
#ifndef CONF_ADC_0_WINMODE
#define CONF_ADC_0_WINMODE 0x0
#endif
// <o> Window Monitor Lower Threshold <0-65535>
// <i> If the window monitor is enabled, these bits define the lower threshold value. (WINLT)
// <id> adc_arch_winlt
#ifndef CONF_ADC_0_WINLT
#define CONF_ADC_0_WINLT 0
#endif
// <o> Window Monitor Upper Threshold <0-65535>
// <i> If the window monitor is enabled, these bits define the lower threshold value. (WINUT)
// <id> adc_arch_winut
#ifndef CONF_ADC_0_WINUT
#define CONF_ADC_0_WINUT 0
#endif
// <o> Bitmask for positive input sequence <0-4294967295>
// <i> Use this parameter to input the bitmask for positive input sequence control (refer to datasheet for the device).
// <id> adc_arch_seqen
#ifndef CONF_ADC_0_SEQEN
#define CONF_ADC_0_SEQEN 0x0
#endif
// </e>
// <e> Event Control
// <id> adc_arch_event_settings
#ifndef CONF_ADC_0_EVENT_CONTROL
#define CONF_ADC_0_EVENT_CONTROL 0
#endif
// <q> Window Monitor Event Out
// <i> Enables event output on window event (WINMONEO)
// <id> adc_arch_winmoneo
#ifndef CONF_ADC_0_WINMONEO
#define CONF_ADC_0_WINMONEO 0
#endif
// <q> Result Ready Event Out
// <i> Enables event output on result ready event (RESRDEO)
// <id> adc_arch_resrdyeo
#ifndef CONF_ADC_0_RESRDYEO
#define CONF_ADC_0_RESRDYEO 0
#endif
// <q> Invert flush Event Signal
// <i> Invert the flush event input signal (FLUSHINV)
// <id> adc_arch_flushinv
#ifndef CONF_ADC_0_FLUSHINV
#define CONF_ADC_0_FLUSHINV 0
#endif
// <q> Trigger Flush On Event
// <i> Trigger an ADC pipeline flush on event (FLUSHEI)
// <id> adc_arch_flushei
#ifndef CONF_ADC_0_FLUSHEI
#define CONF_ADC_0_FLUSHEI 0
#endif
// <q> Invert Start Conversion Event Signal
// <i> Invert the start conversion event input signal (STARTINV)
// <id> adc_arch_startinv
#ifndef CONF_ADC_0_STARTINV
#define CONF_ADC_0_STARTINV 0
#endif
// <q> Trigger Conversion On Event
// <i> Trigger a conversion on event. (STARTEI)
// <id> adc_arch_startei
#ifndef CONF_ADC_0_STARTEI
#define CONF_ADC_0_STARTEI 0
#endif
// </e>
// <<< end of configuration section >>>
#endif // HPL_ADC_CONFIG_H
......@@ -6,6 +6,141 @@
#include <peripheral_clk_config.h>
#ifndef SERCOM_I2CM_CTRLA_MODE_I2C_MASTER
#define SERCOM_I2CM_CTRLA_MODE_I2C_MASTER (5 << 2)
#endif
#ifndef CONF_SERCOM_0_I2CM_ENABLE
#define CONF_SERCOM_0_I2CM_ENABLE 1
#endif
// <h> Basic
// <o> I2C Bus clock speed (Hz) <1-400000>
// <i> I2C Bus clock (SCL) speed measured in Hz
// <id> i2c_master_baud_rate
#ifndef CONF_SERCOM_0_I2CM_BAUD
#define CONF_SERCOM_0_I2CM_BAUD 100000
#endif
// </h>
// <e> Advanced
// <id> i2c_master_advanced
#ifndef CONF_SERCOM_0_I2CM_ADVANCED_CONFIG
#define CONF_SERCOM_0_I2CM_ADVANCED_CONFIG 1
#endif
// <o> TRise (ns) <0-300>
// <i> Determined by the bus impedance, check electric characteristics in the datasheet
// <i> Standard Fast Mode: typical 215ns, max 300ns
// <i> Fast Mode +: typical 60ns, max 100ns
// <i> High Speed Mode: typical 20ns, max 40ns
// <id> i2c_master_arch_trise
#ifndef CONF_SERCOM_0_I2CM_TRISE
#define CONF_SERCOM_0_I2CM_TRISE 215
#endif
// <q> Master SCL Low Extended Time-Out (MEXTTOEN)
// <i> This enables the master SCL low extend time-out
// <id> i2c_master_arch_mexttoen
#ifndef CONF_SERCOM_0_I2CM_MEXTTOEN
#define CONF_SERCOM_0_I2CM_MEXTTOEN 1
#endif
// <q> Slave SCL Low Extend Time-Out (SEXTTOEN)
// <i> Enables the slave SCL low extend time-out. If SCL is cumulatively held low for greater than 25ms from the initial START to a STOP, the slave will release its clock hold if enabled and reset the internal state machine
// <id> i2c_master_arch_sexttoen
#ifndef CONF_SERCOM_0_I2CM_SEXTTOEN
#define CONF_SERCOM_0_I2CM_SEXTTOEN 0
#endif
// <q> SCL Low Time-Out (LOWTOUT)
// <i> Enables SCL low time-out. If SCL is held low for 25ms-35ms, the master will release it's clock hold
// <id> i2c_master_arch_lowtout
#ifndef CONF_SERCOM_0_I2CM_LOWTOUT
#define CONF_SERCOM_0_I2CM_LOWTOUT 1
#endif
// <o> Inactive Time-Out (INACTOUT)
// <0x0=>Disabled
// <0x1=>5-6 SCL cycle time-out(50-60us)
// <0x2=>10-11 SCL cycle time-out(100-110us)
// <0x3=>20-21 SCL cycle time-out(200-210us)
// <i> Defines if inactivity time-out should be enabled, and how long the time-out should be
// <id> i2c_master_arch_inactout
#ifndef CONF_SERCOM_0_I2CM_INACTOUT
#define CONF_SERCOM_0_I2CM_INACTOUT 0x3
#endif
// <o> SDA Hold Time (SDAHOLD)
// <0=>Disabled
// <1=>50-100ns hold time
// <2=>300-600ns hold time
// <3=>400-800ns hold time
// <i> Defines the SDA hold time with respect to the negative edge of SCL
// <id> i2c_master_arch_sdahold
#ifndef CONF_SERCOM_0_I2CM_SDAHOLD
#define CONF_SERCOM_0_I2CM_SDAHOLD 0x2
#endif
// <q> Run in stand-by
// <i> Determine if the module shall run in standby sleep mode
// <id> i2c_master_arch_runstdby
#ifndef CONF_SERCOM_0_I2CM_RUNSTDBY
#define CONF_SERCOM_0_I2CM_RUNSTDBY 0
#endif
// <o> Debug Stop Mode
// <i> Behavior of the baud-rate generator when CPU is halted by external debugger.
// <0=>Keep running
// <1=>Halt
// <id> i2c_master_arch_dbgstop
#ifndef CONF_SERCOM_0_I2CM_DEBUG_STOP_MODE
#define CONF_SERCOM_0_I2CM_DEBUG_STOP_MODE 0
#endif
// </e>
#ifndef CONF_SERCOM_0_I2CM_SPEED
#define CONF_SERCOM_0_I2CM_SPEED 0x00 // Speed: Standard/Fast mode
#endif
#if CONF_SERCOM_0_I2CM_TRISE < 215 || CONF_SERCOM_0_I2CM_TRISE > 300
#warning Bad I2C Rise time for Standard/Fast mode, reset to 215ns
#undef CONF_SERCOM_0_I2CM_TRISE
#define CONF_SERCOM_0_I2CM_TRISE 215U
#endif
// gclk_freq - (i2c_scl_freq * 10) - (gclk_freq * i2c_scl_freq * Trise)
// BAUD + BAUDLOW = --------------------------------------------------------------------
// i2c_scl_freq
// BAUD: register value low [7:0]
// BAUDLOW: register value high [15:8], only used for odd BAUD + BAUDLOW
#define CONF_SERCOM_0_I2CM_BAUD_BAUDLOW \
(((CONF_GCLK_SERCOM0_CORE_FREQUENCY - (CONF_SERCOM_0_I2CM_BAUD * 10U) \
- (CONF_SERCOM_0_I2CM_TRISE * (CONF_SERCOM_0_I2CM_BAUD / 100U) * (CONF_GCLK_SERCOM0_CORE_FREQUENCY / 10000U) \
/ 1000U)) \
* 10U \
+ 5U) \
/ (CONF_SERCOM_0_I2CM_BAUD * 10U))
#ifndef CONF_SERCOM_0_I2CM_BAUD_RATE
#if CONF_SERCOM_0_I2CM_BAUD_BAUDLOW > (0xFF * 2)
#warning Requested I2C baudrate too low, please check
#define CONF_SERCOM_0_I2CM_BAUD_RATE 0xFF
#elif CONF_SERCOM_0_I2CM_BAUD_BAUDLOW <= 1
#warning Requested I2C baudrate too high, please check
#define CONF_SERCOM_0_I2CM_BAUD_RATE 1
#else
#define CONF_SERCOM_0_I2CM_BAUD_RATE \
((CONF_SERCOM_0_I2CM_BAUD_BAUDLOW & 0x1) \
? (CONF_SERCOM_0_I2CM_BAUD_BAUDLOW / 2) + ((CONF_SERCOM_0_I2CM_BAUD_BAUDLOW / 2 + 1) << 8) \
: (CONF_SERCOM_0_I2CM_BAUD_BAUDLOW / 2))
#endif
#endif
#include <peripheral_clk_config.h>
#ifndef CONF_SERCOM_4_USART_ENABLE
#define CONF_SERCOM_4_USART_ENABLE 1
#endif
......@@ -69,7 +204,7 @@
// <e> Advanced configuration
// <id> usart_advanced
#ifndef CONF_SERCOM_4_USART_ADVANCED_CONFIG
#define CONF_SERCOM_4_USART_ADVANCED_CONFIG 0
#define CONF_SERCOM_4_USART_ADVANCED_CONFIG 1
#endif
// <q> Run in stand-by
......
......@@ -4,6 +4,38 @@
// <<< Use Configuration Wizard in Context Menu >>>
// <y> ADC Clock Source
// <id> adc_gclk_selection
// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
// <i> Select the clock source for ADC.
#ifndef CONF_GCLK_ADC0_SRC
#define CONF_GCLK_ADC0_SRC GCLK_PCHCTRL_GEN_GCLK0_Val
#endif
/**
* \def CONF_GCLK_ADC0_FREQUENCY
* \brief ADC0's Clock frequency
*/
#ifndef CONF_GCLK_ADC0_FREQUENCY
#define CONF_GCLK_ADC0_FREQUENCY 40001536
#endif
/**
* \def CONF_CPU_FREQUENCY
* \brief CPU's Clock frequency
......@@ -31,6 +63,70 @@
// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
// <i> Select the clock source for CORE.
#ifndef CONF_GCLK_SERCOM0_CORE_SRC
#define CONF_GCLK_SERCOM0_CORE_SRC GCLK_PCHCTRL_GEN_GCLK0_Val
#endif
// <y> Slow Clock Source
// <id> slow_gclk_selection
// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
// <i> Select the slow clock source.
#ifndef CONF_GCLK_SERCOM0_SLOW_SRC
#define CONF_GCLK_SERCOM0_SLOW_SRC GCLK_PCHCTRL_GEN_GCLK1_Val
#endif
/**
* \def CONF_GCLK_SERCOM0_CORE_FREQUENCY
* \brief SERCOM0's Core Clock frequency
*/
#ifndef CONF_GCLK_SERCOM0_CORE_FREQUENCY
#define CONF_GCLK_SERCOM0_CORE_FREQUENCY 40001536
#endif
/**
* \def CONF_GCLK_SERCOM0_SLOW_FREQUENCY
* \brief SERCOM0's Slow Clock frequency
*/
#ifndef CONF_GCLK_SERCOM0_SLOW_FREQUENCY
#define CONF_GCLK_SERCOM0_SLOW_FREQUENCY 4000000
#endif
// <y> Core Clock Source
// <id> core_gclk_selection
// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
// <i> Select the clock source for CORE.
#ifndef CONF_GCLK_SERCOM4_CORE_SRC
#define CONF_GCLK_SERCOM4_CORE_SRC GCLK_PCHCTRL_GEN_GCLK0_Val
......
......@@ -11,11 +11,43 @@
#include <utils.h>
#include <hal_init.h>
struct can_async_descriptor CAN_0;
#include <hpl_adc_base.h>
/*! The buffer size for USART */
#define TARGET_IO_BUFFER_SIZE 16
struct usart_async_descriptor TARGET_IO;
struct can_async_descriptor CAN_0;
static uint8_t TARGET_IO_buffer[TARGET_IO_BUFFER_SIZE];
struct adc_sync_descriptor ADC_0;
struct flash_descriptor FLASH_0;
struct usart_sync_descriptor TARGET_IO;
struct i2c_m_sync_desc I2C_0;
void ADC_0_PORT_init(void)
{
// Disable digital pin circuitry
gpio_set_pin_direction(PA10, GPIO_DIRECTION_OFF);
gpio_set_pin_function(PA10, PINMUX_PA10B_ADC0_AIN10);
}
void ADC_0_CLOCK_init(void)
{
hri_mclk_set_APBCMASK_ADC0_bit(MCLK);
hri_gclk_write_PCHCTRL_reg(GCLK, ADC0_GCLK_ID, CONF_GCLK_ADC0_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
}
void ADC_0_init(void)
{
ADC_0_CLOCK_init();
ADC_0_PORT_init();
adc_sync_init(&ADC_0, ADC0, _adc_get_adc_sync());
}
void FLASH_0_CLOCK_init(void)
{
......@@ -29,25 +61,79 @@ void FLASH_0_init(void)
flash_init(&FLASH_0, NVMCTRL);
}
void TARGET_IO_PORT_init(void)
void I2C_0_PORT_init(void)
{
gpio_set_pin_function(PB10, PINMUX_PB10D_SERCOM4_PAD2);
gpio_set_pin_pull_mode(PA08,
// <y> Pull configuration
// <id> pad_pull_config
// <GPIO_PULL_OFF"> Off
// <GPIO_PULL_UP"> Pull-up
// <GPIO_PULL_DOWN"> Pull-down
GPIO_PULL_OFF);
gpio_set_pin_function(PA08, PINMUX_PA08C_SERCOM0_PAD0);
gpio_set_pin_pull_mode(PA09,
// <y> Pull configuration
// <id> pad_pull_config
// <GPIO_PULL_OFF"> Off
// <GPIO_PULL_UP"> Pull-up
// <GPIO_PULL_DOWN"> Pull-down
GPIO_PULL_OFF);
gpio_set_pin_function(PA09, PINMUX_PA09C_SERCOM0_PAD1);
}
gpio_set_pin_function(PB11, PINMUX_PB11D_SERCOM4_PAD3);
void I2C_0_CLOCK_init(void)
{
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM0_GCLK_ID_CORE, CONF_GCLK_SERCOM0_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM0_GCLK_ID_SLOW, CONF_GCLK_SERCOM0_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
hri_mclk_set_APBCMASK_SERCOM0_bit(MCLK);
}
void I2C_0_init(void)
{
I2C_0_CLOCK_init();
i2c_m_sync_init(&I2C_0, SERCOM0);
I2C_0_PORT_init();
}
void TARGET_IO_CLOCK_init(void)
/**
* \brief USART Clock initialization function
*
* Enables register interface and peripheral clock
*/
void TARGET_IO_CLOCK_init()
{
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM4_GCLK_ID_CORE, CONF_GCLK_SERCOM4_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM4_GCLK_ID_SLOW, CONF_GCLK_SERCOM4_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
hri_mclk_set_APBCMASK_SERCOM4_bit(MCLK);
}
/**
* \brief USART pinmux initialization function
*
* Set each required pin to USART functionality
*/
void TARGET_IO_PORT_init()
{
gpio_set_pin_function(PB10, PINMUX_PB10D_SERCOM4_PAD2);
gpio_set_pin_function(PB11, PINMUX_PB11D_SERCOM4_PAD3);
}
/**
* \brief USART initialization function
*
* Enables USART peripheral, clocks and initializes USART driver
*/
void TARGET_IO_init(void)
{
TARGET_IO_CLOCK_init();
usart_sync_init(&TARGET_IO, SERCOM4, (void *)NULL);
usart_async_init(&TARGET_IO, SERCOM4, TARGET_IO_buffer, TARGET_IO_BUFFER_SIZE, (void *)NULL);
TARGET_IO_PORT_init();
}
......@@ -89,8 +175,11 @@ void system_init(void)
gpio_set_pin_function(LED0, GPIO_PIN_FUNCTION_OFF);
ADC_0_init();
FLASH_0_init();
I2C_0_init();
TARGET_IO_init();
CAN_0_init();
}
......@@ -21,19 +21,33 @@ extern "C" {
#include <hal_io.h>
#include <hal_sleep.h>
#include <hal_adc_sync.h>
#include <hal_flash.h>
#include <hal_usart_sync.h>
#include <hal_i2c_m_sync.h>
#include <hal_usart_async.h>
#include <hal_can_async.h>
extern struct adc_sync_descriptor ADC_0;
extern struct flash_descriptor FLASH_0;
extern struct usart_sync_descriptor TARGET_IO;
extern struct can_async_descriptor CAN_0;
extern struct i2c_m_sync_desc I2C_0;
extern struct usart_async_descriptor TARGET_IO;
extern struct can_async_descriptor CAN_0;
void ADC_0_PORT_init(void);
void ADC_0_CLOCK_init(void);
void ADC_0_init(void);
void FLASH_0_init(void);
void FLASH_0_CLOCK_init(void);
void I2C_0_CLOCK_init(void);
void I2C_0_init(void);
void I2C_0_PORT_init(void);
void TARGET_IO_PORT_init(void);
void TARGET_IO_CLOCK_init(void);
void TARGET_IO_init(void);
......
......@@ -10,6 +10,20 @@
#include "driver_init.h"
#include "utils.h"
/**
* Example of using ADC_0 to generate waveform.
*/
void ADC_0_example(void)
{
uint8_t buffer[2];
adc_sync_enable_channel(&ADC_0, 0);
while (1) {
adc_sync_read_channel(&ADC_0, 0, buffer, 2);
}
}
static uint8_t src_data[128];
static uint8_t chk_data[128];
/**
......@@ -70,16 +84,43 @@ void RWW_FLASH_0_example(void)
}
}
void I2C_0_example(void)
{
struct io_descriptor *I2C_0_io;
i2c_m_sync_get_io_descriptor(&I2C_0, &I2C_0_io);
i2c_m_sync_enable(&I2C_0);
i2c_m_sync_set_slaveaddr(&I2C_0, 0x12, I2C_M_SEVEN);
io_write(I2C_0_io, (uint8_t *)"Hello World!", 12);
}
/**
* Example of using TARGET_IO to write "Hello World" using the IO abstraction.
*
* Since the driver is asynchronous we need to use statically allocated memory for string
* because driver initiates transfer and then returns before the transmission is completed.
*
* Once transfer has been completed the tx_cb function will be called.
*/
static uint8_t example_TARGET_IO[12] = "Hello World!";
static void tx_cb_TARGET_IO(const struct usart_async_descriptor *const io_descr)
{
/* Transfer completed */
}
void TARGET_IO_example(void)
{
struct io_descriptor *io;
usart_sync_get_io_descriptor(&TARGET_IO, &io);
usart_sync_enable(&TARGET_IO);
io_write(io, (uint8_t *)"Hello World!", 12);
usart_async_register_callback(&TARGET_IO, USART_ASYNC_TXC_CB, tx_cb_TARGET_IO);
/*usart_async_register_callback(&TARGET_IO, USART_ASYNC_RXC_CB, rx_cb);
usart_async_register_callback(&TARGET_IO, USART_ASYNC_ERROR_CB, err_cb);*/
usart_async_get_io_descriptor(&TARGET_IO, &io);
usart_async_enable(&TARGET_IO);
io_write(io, example_TARGET_IO, 12);
}
void CAN_0_tx_callback(struct can_async_descriptor *const descr)
......
......@@ -12,9 +12,13 @@
extern "C" {
#endif
void ADC_0_example(void);
void FLASH_0_example(void);
void RWW_FLASH_0_example(void);
void I2C_0_example(void);
void TARGET_IO_example(void);
void CAN_0_example(void);
......
======================
ADC Synchronous driver
======================
An ADC (Analog-to-Digital Converter) converts analog signals to digital values.
A reference signal with a known voltage level is quantified into equally
sized chunks, each representing a digital value from 0 to the highest number
possible with the bit resolution supported by the ADC. The input voltage
measured by the ADC is compared against these chunks and the chunk with the
closest voltage level defines the digital value that can be used to represent
the analog input voltage level.
Usually an ADC can operate in either differential or single-ended mode.
In differential mode two signals (V+ and V-) are compared against each other
and the resulting digital value represents the relative voltage level between
V+ and V-. This means that if the input voltage level on V+ is lower than on
V- the digital value is negative, which also means that in differential
mode one bit is lost to the sign. In single-ended mode only V+ is compared
against the reference voltage, and the resulting digital value can only be
positive, but the full bit-range of the ADC can be used.
Usually multiple resolutions are supported by the ADC, lower resolution can
reduce the conversion time, but lose accuracy.
Some ADCs has a gain stage on the input lines which can be used to increase the
dynamic range. The default gain value is usually x1, which means that the
conversion range is from 0V to the reference voltage.
Applications can change the gain stage, to increase or reduce the conversion
range.
The window mode allows the conversion result to be compared to a set of
predefined threshold values. Applications can use callback function to monitor
if the conversion result exceeds predefined threshold value.
Usually multiple reference voltages are supported by the ADC, both internal and
external with difference voltage levels. The reference voltage have an impact
on the accuracy, and should be selected to cover the full range of the analog
input signal and never less than the expected maximum input voltage.
There are two conversion modes supported by ADC, single shot and free running.
In single shot mode the ADC only make one conversion when triggered by the
application, in free running mode it continues to make conversion from it
is triggered until it is stopped by the application. When window monitoring,
the ADC should be set to free running mode.
Features
--------
* Initialization and de-initialization
* Support multiple Conversion Mode, Single or Free run
* Start ADC Conversion
* Read Conversion Result
Applications
------------
* Measurement of internal sensor. E.g., MCU internal temperature sensor value.
* Measurement of external sensor. E.g., Temperature, humidity sensor value.
* Sampling and measurement of a signal. E.g., sinusoidal wave, square wave.
Dependencies
------------
* ADC hardware
Concurrency
-----------
N/A
Limitations
-----------
N/A
Knows issues and workarounds
----------------------------
N/A
=============================
I2C Master synchronous driver
=============================
I2C (Inter-Integrated Circuit) is a two wire serial interface usually used
for on-board low-speed bi-directional communication between controllers and
peripherals. The master device is responsible for initiating and controlling
all transfers on the I2C bus. Only one master device can be active on the I2C
bus at the time, but the master role can be transferred between devices on the
same I2C bus. I2C uses only two bidirectional open-drain lines, usually
designated SDA (Serial Data Line) and SCL (Serial Clock Line), with pull up
resistors.
The stop condition is automatically controlled by the driver if the I/O write and
read functions are used, but can be manually controlled by using the
i2c_m_sync_transfer function.
Often a master accesses different information in the slave by accessing
different registers in the slave. This is done by first sending a message to
the target slave containing the register address, followed by a repeated start
condition (no stop condition between) ending with transferring register data.
This scheme is supported by the i2c_m_sync_cmd_write and i2c_m_sync_cmd_read
function, but limited to 8-bit register addresses.
I2C Modes (standard mode/fastmode+/highspeed mode) can only be selected in
Atmel Start. If the SCL frequency (baudrate) has changed run-time, make sure to
stick within the SCL clock frequency range supported by the selected mode.
The requested SCL clock frequency is not validated by the
i2c_m_sync_set_baudrate function against the selected I2C mode.
Features
--------
* I2C Master support
* Initialization and de-initialization
* Enabling and disabling
* Run-time bus speed configuration
* Write and read I2C messages
* Slave register access functions (limited to 8-bit address)
* Manual or automatic stop condition generation
* 10- and 7- bit addressing
* I2C Modes supported
+----------------------+-------------------+
|* Standard/Fast mode | (SCL: 1 - 400kHz) |
+----------------------+-------------------+
|* Fastmode+ | (SCL: 1 - 1000kHz)|
+----------------------+-------------------+
|* Highspeed mode | (SCL: 1 - 3400kHz)|
+----------------------+-------------------+
Applications
------------
* Transfer data to and from one or multiple I2C slaves like I2C connected sensors, data storage or other I2C capable peripherals
* Data communication between micro controllers
* Controlling displays
Dependencies
------------
* I2C Master capable hardware
Concurrency
-----------
N/A
Limitations
-----------
General
^^^^^^^
* System Managmenet Bus (SMBus) not supported.
* Power Management Bus (PMBus) not supported.
Clock considerations
^^^^^^^^^^^^^^^^^^^^
The register value for the requested I2C speed is calculated and placed in the correct register, but not validated if it works correctly with the clock/prescaler settings used for the module. To validate the I2C speed setting use the formula found in the configuration file for the module. Selectable speed is automatically limited within the speed range defined by the I2C mode selected.
Known issues and workarounds
----------------------------
N/A
The USART Synchronous Driver
============================
The USART Asynchronous Driver
=============================
The universal synchronous and asynchronous receiver and transmitter
(USART) is usually used to transfer data from one device to the other.
The USART driver use a ring buffer to store received data. When the USART
raise the data received interrupt, this data will be stored in the ring buffer
at the next free location. When the ring buffer is full, the next reception
will overwrite the oldest data stored in the ring buffer. There is one
USART_BUFFER_SIZE macro per used hardware instance, e.g. for SERCOM0 the macro
is called SERCOM0_USART_BUFFER_SIZE.
On the other hand, when sending data over USART, the data is not copied to an
internal buffer, but the data buffer supplied by the user is used. The callback
will only be generated at the end of the buffer and not for each byte.
User can set action for flow control pins by function usart_set_flow_control,
if the flow control is enabled. All the available states are defined in union
usart_flow_control_state.
......@@ -24,6 +35,8 @@ Features
* Data order
* Flow control
* Data transfer: transmission, reception
* Notifications about transfer done or error case via callbacks
* Status information with busy state and transfer count
Applications
------------
......@@ -34,7 +47,8 @@ between devices.
Dependencies
------------
USART capable hardware.
USART capable hardware, with interrupt on each character is sent or
received.
Concurrency
-----------
......
/**
* \file
*
* \brief ADC functionality declaration.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _HAL_ADC_SYNC_H_INCLUDED
#define _HAL_ADC_SYNC_H_INCLUDED
#include <hpl_adc_sync.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup doc_driver_hal_adc_sync
*
* @{
*/
/**
* \brief ADC descriptor
*
* The ADC descriptor forward declaration.
*/
struct adc_sync_descriptor;
/**
* \brief ADC descriptor
*/
struct adc_sync_descriptor {
/** ADC device */
struct _adc_sync_device device;
};
/**
* \brief Initialize ADC
*
* This function initializes the given ADC descriptor.
* It checks if the given hardware is not initialized and if the given hardware
* is permitted to be initialized.
*
* \param[out] descr An ADC descriptor to initialize
* \param[in] hw The pointer to hardware instance
* \param[in] func The pointer to a set of functions pointers
*
* \return Initialization status.
*/
int32_t adc_sync_init(struct adc_sync_descriptor *const descr, void *const hw, void *const func);
/**
* \brief Deinitialize ADC
*
* This function deinitializes the given ADC descriptor.
* It checks if the given hardware is initialized and if the given hardware is
* permitted to be deinitialized.
*
* \param[in] descr An ADC descriptor to deinitialize
*
* \return De-initialization status.
*/
int32_t adc_sync_deinit(struct adc_sync_descriptor *const descr);
/**
* \brief Enable ADC
*
* Use this function to set the ADC peripheral to enabled state.
*
* \param[in] descr Pointer to the ADC descriptor
* \param[in] channel Channel number
*
* \return Operation status
*
*/
int32_t adc_sync_enable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel);
/**
* \brief Disable ADC
*
* Use this function to set the ADC peripheral to disabled state.
*
* \param[in] descr Pointer to the ADC descriptor
* \param[in] channel Channel number
*
* \return Operation status
*
*/
int32_t adc_sync_disable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel);
/**
* \brief Read data from ADC
*
* \param[in] descr The pointer to the ADC descriptor
* \param[in] channel Channel number
* \param[in] buf A buffer to read data to
* \param[in] length The size of a buffer
*
* \return The number of bytes read.
*/
int32_t adc_sync_read_channel(struct adc_sync_descriptor *const descr, const uint8_t channel, uint8_t *const buffer,
const uint16_t length);
/**
* \brief Set ADC reference source
*
* This function sets ADC reference source.
*
* \param[in] descr The pointer to the ADC descriptor
* \param[in] reference A reference source to set
*
* \return Status of the ADC reference source setting.
*/
int32_t adc_sync_set_reference(struct adc_sync_descriptor *const descr, const adc_reference_t reference);
/**
* \brief Set ADC resolution
*
* This function sets ADC resolution.
*
* \param[in] descr The pointer to the ADC descriptor
* \param[in] resolution A resolution to set
*
* \return Status of the ADC resolution setting.
*/
int32_t adc_sync_set_resolution(struct adc_sync_descriptor *const descr, const adc_resolution_t resolution);
/**
* \brief Set ADC input source of a channel
*
* This function sets ADC positive and negative input sources.
*
* \param[in] descr The pointer to the ADC descriptor
* \param[in] pos_input A positive input source to set
* \param[in] neg_input A negative input source to set
* \param[in] channel Channel number
*
* \return Status of the ADC channels setting.
*/
int32_t adc_sync_set_inputs(struct adc_sync_descriptor *const descr, const adc_pos_input_t pos_input,
const adc_neg_input_t neg_input, const uint8_t channel);
/**
* \brief Set ADC conversion mode
*
* This function sets ADC conversion mode.
*
* \param[in] descr The pointer to the ADC descriptor
* \param[in] mode A conversion mode to set
*
* \return Status of the ADC conversion mode setting.
*/
int32_t adc_sync_set_conversion_mode(struct adc_sync_descriptor *const descr, const enum adc_conversion_mode mode);
/**
* \brief Set ADC differential mode
*
* This function sets ADC differential mode.
*
* \param[in] descr The pointer to the ADC descriptor
* \param[in] channel Channel number
* \param[in] mode A differential mode to set
*
* \return Status of the ADC differential mode setting.
*/
int32_t adc_sync_set_channel_differential_mode(struct adc_sync_descriptor *const descr, const uint8_t channel,
const enum adc_differential_mode mode);
/**
* \brief Set ADC channel gain
*
* This function sets ADC channel gain.
*
* \param[in] descr The pointer to the ADC descriptor
* \param[in] channel Channel number
* \param[in] gain A gain to set
*
* \return Status of the ADC gain setting.
*/
int32_t adc_sync_set_channel_gain(struct adc_sync_descriptor *const descr, const uint8_t channel,
const adc_gain_t gain);
/**
* \brief Set ADC window mode
*
* This function sets ADC window mode.
*
* \param[in] descr The pointer to the ADC descriptor
* \param[in] mode A window mode to set
*
* \return Status of the ADC window mode setting.
*/
int32_t adc_sync_set_window_mode(struct adc_sync_descriptor *const descr, const adc_window_mode_t mode);
/**
* \brief Set ADC thresholds
*
* This function sets ADC positive and negative thresholds.
*
* \param[in] descr The pointer to the ADC descriptor
* \param[in] low_threshold A lower thresholds to set
* \param[in] up_threshold An upper thresholds to set
*
* \return Status of the ADC thresholds setting.
*/
int32_t adc_sync_set_thresholds(struct adc_sync_descriptor *const descr, const adc_threshold_t low_threshold,
const adc_threshold_t up_threshold);
/**
* \brief Retrieve threshold state
*
* This function retrieves ADC threshold state.
*
* \param[in] descr The pointer to the ADC descriptor
* \param[out] state The threshold state
*
* \return The state of ADC thresholds state retrieving.
*/
int32_t adc_sync_get_threshold_state(const struct adc_sync_descriptor *const descr,
adc_threshold_status_t *const state);
/**
* \brief Check if conversion is complete
*
* This function checks if the ADC has finished the conversion.
*
* \param[in] descr The pointer to the ADC descriptor
* \param[in] channel Channel number
*
* \return The status of ADC conversion completion checking.
* \retval 1 The conversion is complete
* \retval 0 The conversion is not complete
*/
int32_t adc_sync_is_channel_conversion_complete(const struct adc_sync_descriptor *const descr, const uint8_t channel);
/**
* \brief Retrieve the current driver version
*
* \return Current driver version.
*/
uint32_t adc_sync_get_version(void);
/**@}*/
#ifdef __cplusplus
}
#endif
#include <hpl_missing_features.h>
#endif /* _HAL_ADC_SYNC_H_INCLUDED */
/**
* \file
*
* \brief Sync I2C Hardware Abstraction Layer(HAL) declaration.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _HAL_I2C_M_SYNC_H_INCLUDED
#define _HAL_I2C_M_SYNC_H_INCLUDED
#include <hpl_i2c_m_sync.h>
#include <hal_io.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup doc_driver_hal_i2c_master_sync
*
* @{
*/
#define I2C_M_MAX_RETRY 1
/**
* \brief I2C descriptor structure, embed i2c_device & i2c_interface
*/
struct i2c_m_sync_desc {
struct _i2c_m_sync_device device;
struct io_descriptor io;
uint16_t slave_addr;
};
/**
* \brief Initialize synchronous I2C interface
*
* This function initializes the given I/O descriptor to be used as a
* synchronous I2C interface descriptor.
* It checks if the given hardware is not initialized and if the given hardware
* is permitted to be initialized.
*
* \param[in] i2c An I2C descriptor, which is used to communicate through I2C
* \param[in] hw The pointer to hardware instance
*
* \return Initialization status.
* \retval -1 The passed parameters were invalid or the interface is already initialized
* \retval 0 The initialization is completed successfully
*/
int32_t i2c_m_sync_init(struct i2c_m_sync_desc *i2c, void *hw);
/**
* \brief Deinitialize I2C interface
*
* This function deinitializes the given I/O descriptor.
* It checks if the given hardware is initialized and if the given hardware is permitted to be deinitialized.
*
* \param[in] i2c An I2C descriptor, which is used to communicate through I2C
*
* \return Uninitialization status.
* \retval -1 The passed parameters were invalid or the interface is already deinitialized
* \retval 0 The de-initialization is completed successfully
*/
int32_t i2c_m_sync_deinit(struct i2c_m_sync_desc *i2c);
/**
* \brief Set the slave device address
*
* This function sets the next transfer target slave I2C device address.
* It takes no effect to any already started access.
*
* \param[in] i2c An I2C descriptor, which is used to communicate through I2C
* \param[in] addr The slave address to access
* \param[in] addr_len The slave address length, can be I2C_M_TEN or I2C_M_SEVEN
*
* \return Masked slave address. The mask is a maximum 10-bit address, and 10th
* bit is set if a 10-bit address is used
*/
int32_t i2c_m_sync_set_slaveaddr(struct i2c_m_sync_desc *i2c, int16_t addr, int32_t addr_len);
/**
* \brief Set baudrate
*
* This function sets the I2C device to the specified baudrate.
* It only takes effect when the hardware is disabled.
*
* \param[in] i2c An I2C descriptor, which is used to communicate through I2C
* \param[in] clkrate Unused parameter. Should always be 0
* \param[in] baudrate The baudrate value set to master
*
* \return Whether successfully set the baudrate
* \retval -1 The passed parameters were invalid or the device is already enabled
* \retval 0 The baudrate set is completed successfully
*/
int32_t i2c_m_sync_set_baudrate(struct i2c_m_sync_desc *i2c, uint32_t clkrate, uint32_t baudrate);
/**
* \brief Sync version of enable hardware
*
* This function enables the I2C device, and then waits for this enabling operation to be done
*
* \param[in] i2c An I2C descriptor, which is used to communicate through I2C
*
* \return Whether successfully enable the device
* \retval -1 The passed parameters were invalid or the device enable failed
* \retval 0 The hardware enabling is completed successfully
*/
int32_t i2c_m_sync_enable(struct i2c_m_sync_desc *i2c);
/**
* \brief Sync version of disable hardware
*
* This function disables the I2C device and then waits for this disabling operation to be done
*
* \param[in] i2c An I2C descriptor, which is used to communicate through I2C
*
* \return Whether successfully disable the device
* \retval -1 The passed parameters were invalid or the device disable failed
* \retval 0 The hardware disabling is completed successfully
*/
int32_t i2c_m_sync_disable(struct i2c_m_sync_desc *i2c);
/**
* \brief Sync version of write command to I2C slave
*
* This function will write the value to a specified register in the I2C slave device and
* then wait for this operation to be done.
*
* The sequence of this routine is
* sta->address(write)->ack->reg address->ack->resta->address(write)->ack->reg value->nack->stt
*
* \param[in] i2c An I2C descriptor, which is used to communicate through I2C
* \param[in] reg The internal address/register of the I2C slave device
* \param[in] buffer The buffer holding data to write to the I2C slave device
* \param[in] length The length (in bytes) to write to the I2C slave device
*
* \return Whether successfully write to the device
* \retval <0 The passed parameters were invalid or write fail
* \retval 0 Writing to register is completed successfully
*/
int32_t i2c_m_sync_cmd_write(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length);
/**
* \brief Sync version of read register value from I2C slave
*
* This function will read a byte value from a specified register in the I2C slave device and
* then wait for this operation to be done.
*
* The sequence of this routine is
* sta->address(write)->ack->reg address->ack->resta->address(read)->ack->reg value->nack->stt
*
* \param[in] i2c An I2C descriptor, which is used to communicate through I2C
* \param[in] reg The internal address/register of the I2C slave device
* \param[in] buffer The buffer to hold the read data from the I2C slave device
* \param[in] length The length (in bytes) to read from the I2C slave device
*
* \return Whether successfully read from the device
* \retval <0 The passed parameters were invalid or read fail
* \retval 0 Reading from register is completed successfully
*/
int32_t i2c_m_sync_cmd_read(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length);
/**
* \brief Sync version of transfer message to/from the I2C slave
*
* This function will transfer a message between the I2C slave and the master. This function will wait for the operation
* to be done.
*
* \param[in] i2c An I2C descriptor, which is used to communicate through I2C
* \param[in] msg An i2c_m_msg struct
*
* \return The status of the operation
* \retval 0 Operation completed successfully
* \retval <0 Operation failed
*/
int32_t i2c_m_sync_transfer(struct i2c_m_sync_desc *const i2c, struct _i2c_m_msg *msg);
/**
* \brief Sync version of send stop condition on the i2c bus
*
* This function will create a stop condition on the i2c bus to release the bus
*
* \param[in] i2c An I2C descriptor, which is used to communicate through I2C
*
* \return The status of the operation
* \retval 0 Operation completed successfully
* \retval <0 Operation failed
*/
int32_t i2c_m_sync_send_stop(struct i2c_m_sync_desc *const i2c);
/**
* \brief Return I/O descriptor for this I2C instance
*
* This function will return a I/O instance for this I2C driver instance
*
* \param[in] i2c_m_sync_desc An I2C descriptor, which is used to communicate through I2C
* \param[in] io_descriptor A pointer to an I/O descriptor pointer type
*
* \return Error code
* \retval 0 No error detected
* \retval <0 Error code
*/
int32_t i2c_m_sync_get_io_descriptor(struct i2c_m_sync_desc *const i2c, struct io_descriptor **io);
/**
* \brief Retrieve the current driver version
*
* \return Current driver version.
*/
uint32_t i2c_m_sync_get_version(void);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif
......@@ -31,14 +31,15 @@
*
*/
#ifndef _HAL_SYNC_USART_H_INCLUDED
#define _HAL_SYNC_USART_H_INCLUDED
#ifndef _HAL_USART_ASYNC_H_INCLUDED
#define _HAL_USART_ASYNC_H_INCLUDED
#include "hal_io.h"
#include <hpl_usart_sync.h>
#include <hpl_usart_async.h>
#include <utils_ringbuffer.h>
/**
* \addtogroup doc_driver_hal_usart_sync
* \addtogroup doc_driver_hal_usart_async
*
* @{
*/
......@@ -48,41 +49,95 @@ extern "C" {
#endif
/**
* \brief Synchronous USART descriptor
* \brief USART descriptor
*
* The USART descriptor forward declaration.
*/
struct usart_async_descriptor;
/**
* \brief USART callback type
*/
typedef void (*usart_cb_t)(const struct usart_async_descriptor *const descr);
/**
* \brief USART callback types
*/
enum usart_async_callback_type { USART_ASYNC_RXC_CB, USART_ASYNC_TXC_CB, USART_ASYNC_ERROR_CB };
/**
* \brief USART callbacks
*/
struct usart_sync_descriptor {
struct io_descriptor io;
struct _usart_sync_device device;
struct usart_async_callbacks {
usart_cb_t tx_done;
usart_cb_t rx_done;
usart_cb_t error;
};
/** \brief USART status
* Status descriptor holds the current status of transfer.
*/
struct usart_async_status {
/** Status flags */
uint32_t flags;
/** Number of characters transmitted */
uint16_t txcnt;
/** Number of characters receviced */
uint16_t rxcnt;
};
/**
* \brief Asynchronous USART descriptor structure
*/
struct usart_async_descriptor {
struct io_descriptor io;
struct _usart_async_device device;
struct usart_async_callbacks usart_cb;
uint32_t stat;
struct ringbuffer rx;
uint16_t tx_por;
uint8_t * tx_buffer;
uint16_t tx_buffer_length;
};
/** USART write busy */
#define USART_ASYNC_STATUS_BUSY 0x0001
/**
* \brief Initialize USART interface
*
* This function initializes the given I/O descriptor to be used
* as USART interface descriptor.
* It checks if the given hardware is not initialized and
* if the given hardware is permitted to be initialized.
* This function initializes the given I/O descriptor to be used as USART
* interface descriptor.
* It checks if the given hardware is not initialized and if the given hardware
* is permitted to be initialized.
*
* \param[out] descr A USART descriptor which is used to communicate via USART
* \param[in] hw The pointer to hardware instance
* \param[in] func The pointer to as set of functions pointers
* \param[out] descr A USART descriptor which is used to communicate via the USART
* \param[in] hw The pointer to the hardware instance
* \param[in] rx_buffer An RX buffer
* \param[in] rx_buffer_length The length of the buffer above
* \param[in] func The pointer to a set of function pointers
*
* \return Initialization status.
* \retval -1 Passed parameters were invalid or the interface is already
* initialized
* \retval 0 The initialization is completed successfully
*/
int32_t usart_sync_init(struct usart_sync_descriptor *const descr, void *const hw, void *const func);
int32_t usart_async_init(struct usart_async_descriptor *const descr, void *const hw, uint8_t *const rx_buffer,
const uint16_t rx_buffer_length, void *const func);
/**
* \brief Deinitialize USART interface
*
* This function deinitializes the given I/O descriptor.
* It checks if the given hardware is initialized and
* if the given hardware is permitted to be deinitialized.
* It checks if the given hardware is initialized and if the given hardware
* is permitted to be deinitialized.
*
* \param[in] descr A USART descriptor which is used to communicate via USART
*
* \return De-initialization status.
*/
int32_t usart_sync_deinit(struct usart_sync_descriptor *const descr);
int32_t usart_async_deinit(struct usart_async_descriptor *const descr);
/**
* \brief Enable USART interface
......@@ -93,7 +148,7 @@ int32_t usart_sync_deinit(struct usart_sync_descriptor *const descr);
*
* \return Enabling status.
*/
int32_t usart_sync_enable(struct usart_sync_descriptor *const descr);
int32_t usart_async_enable(struct usart_async_descriptor *const descr);
/**
* \brief Disable USART interface
......@@ -104,7 +159,7 @@ int32_t usart_sync_enable(struct usart_sync_descriptor *const descr);
*
* \return Disabling status.
*/
int32_t usart_sync_disable(struct usart_sync_descriptor *const descr);
int32_t usart_async_disable(struct usart_async_descriptor *const descr);
/**
* \brief Retrieve I/O descriptor
......@@ -114,16 +169,30 @@ int32_t usart_sync_disable(struct usart_sync_descriptor *const descr);
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[out] io An I/O descriptor to retrieve
*
* \return The status of the I/O descriptor retrieving.
* \return The status of I/O descriptor retrieving.
*/
int32_t usart_sync_get_io_descriptor(struct usart_sync_descriptor *const descr, struct io_descriptor **io);
int32_t usart_async_get_io_descriptor(struct usart_async_descriptor *const descr, struct io_descriptor **io);
/**
* \brief Register USART callback
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[in] type Callback type
* \param[in] cb A callback function
*
* \return The status of callback assignment.
* \retval -1 Passed parameters were invalid or the interface is not initialized
* \retval 0 A callback is registered successfully
*/
int32_t usart_async_register_callback(struct usart_async_descriptor *const descr,
const enum usart_async_callback_type type, usart_cb_t cb);
/**
* \brief Specify action for flow control pins
*
* This function sets the action (or state) for the flow control pins
* if the flow control is enabled.
* It sets the state of flow control pins only if the automatic support of
* This function sets action (or state) for flow control pins if
* the flow control is enabled.
* It sets state of flow control pins only if automatic support of
* the flow control is not supported by the hardware.
*
* \param[in] descr A USART descriptor which is used to communicate via USART
......@@ -131,8 +200,8 @@ int32_t usart_sync_get_io_descriptor(struct usart_sync_descriptor *const descr,
*
* \return The status of flow control action setup.
*/
int32_t usart_sync_set_flow_control(struct usart_sync_descriptor *const descr,
const union usart_flow_control_state state);
int32_t usart_async_set_flow_control(struct usart_async_descriptor *const descr,
const union usart_flow_control_state state);
/**
* \brief Set USART baud rate
......@@ -142,7 +211,7 @@ int32_t usart_sync_set_flow_control(struct usart_sync_descriptor *const descr,
*
* \return The status of baud rate setting.
*/
int32_t usart_sync_set_baud_rate(struct usart_sync_descriptor *const descr, const uint32_t baud_rate);
int32_t usart_async_set_baud_rate(struct usart_async_descriptor *const descr, const uint32_t baud_rate);
/**
* \brief Set USART data order
......@@ -152,7 +221,7 @@ int32_t usart_sync_set_baud_rate(struct usart_sync_descriptor *const descr, cons
*
* \return The status of data order setting.
*/
int32_t usart_sync_set_data_order(struct usart_sync_descriptor *const descr, const enum usart_data_order data_order);
int32_t usart_async_set_data_order(struct usart_async_descriptor *const descr, const enum usart_data_order data_order);
/**
* \brief Set USART mode
......@@ -162,7 +231,7 @@ int32_t usart_sync_set_data_order(struct usart_sync_descriptor *const descr, con
*
* \return The status of mode setting.
*/
int32_t usart_sync_set_mode(struct usart_sync_descriptor *const descr, const enum usart_mode mode);
int32_t usart_async_set_mode(struct usart_async_descriptor *const descr, const enum usart_mode mode);
/**
* \brief Set USART parity
......@@ -172,7 +241,7 @@ int32_t usart_sync_set_mode(struct usart_sync_descriptor *const descr, const enu
*
* \return The status of parity setting.
*/
int32_t usart_sync_set_parity(struct usart_sync_descriptor *const descr, const enum usart_parity parity);
int32_t usart_async_set_parity(struct usart_async_descriptor *const descr, const enum usart_parity parity);
/**
* \brief Set USART stop bits
......@@ -182,7 +251,7 @@ int32_t usart_sync_set_parity(struct usart_sync_descriptor *const descr, const e
*
* \return The status of stop bits setting.
*/
int32_t usart_sync_set_stopbits(struct usart_sync_descriptor *const descr, const enum usart_stop_bits stop_bits);
int32_t usart_async_set_stopbits(struct usart_async_descriptor *const descr, const enum usart_stop_bits stop_bits);
/**
* \brief Set USART character size
......@@ -192,14 +261,16 @@ int32_t usart_sync_set_stopbits(struct usart_sync_descriptor *const descr, const
*
* \return The status of character size setting.
*/
int32_t usart_sync_set_character_size(struct usart_sync_descriptor *const descr, const enum usart_character_size size);
int32_t usart_async_set_character_size(struct usart_async_descriptor *const descr,
const enum usart_character_size size);
/**
* \brief Retrieve the state of flow control pins
*
* This function retrieves the of flow control pins
* This function retrieves the flow control pins
* if the flow control is enabled.
* Function can return USART_FLOW_CONTROL_STATE_UNAVAILABLE in case
*
* The function can return USART_FLOW_CONTROL_STATE_UNAVAILABLE in case
* if the flow control is done by the hardware
* and the pins state cannot be read out.
*
......@@ -208,8 +279,8 @@ int32_t usart_sync_set_character_size(struct usart_sync_descriptor *const descr,
*
* \return The status of flow control state reading.
*/
int32_t usart_sync_flow_control_status(const struct usart_sync_descriptor *const descr,
union usart_flow_control_state *const state);
int32_t usart_async_flow_control_status(const struct usart_async_descriptor *const descr,
union usart_flow_control_state *const state);
/**
* \brief Check if the USART transmitter is empty
......@@ -220,28 +291,49 @@ int32_t usart_sync_flow_control_status(const struct usart_sync_descriptor *const
* \retval 0 The USART transmitter is not empty
* \retval 1 The USART transmitter is empty
*/
int32_t usart_sync_is_tx_empty(const struct usart_sync_descriptor *const descr);
int32_t usart_async_is_tx_empty(const struct usart_async_descriptor *const descr);
/**
* \brief Check if the USART receiver is not empty
*
* \param[in] descr A USART descriptor which is used to communicate via USART
*
* \return The status of USART RX empty checking.
* \return The status of the USART RX empty checking.
* \retval 1 The USART receiver is not empty
* \retval 0 The USART receiver is empty
*/
int32_t usart_sync_is_rx_not_empty(const struct usart_sync_descriptor *const descr);
int32_t usart_async_is_rx_not_empty(const struct usart_async_descriptor *const descr);
/**
* \brief Retrieve the current interface status
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[out] status The state of USART
*
* \return The status of USART status retrieving.
*/
int32_t usart_async_get_status(struct usart_async_descriptor *const descr, struct usart_async_status *const status);
/**
* \brief flush USART ringbuf
*
* This function flush USART RX ringbuf.
*
* \param[in] descr The pointer to USART descriptor
*
* \return ERR_NONE
*/
int32_t usart_async_flush_rx_buffer(struct usart_async_descriptor *const descr);
/**
* \brief Retrieve the current driver version
*
* \return Current driver version.
*/
uint32_t usart_sync_get_version(void);
uint32_t usart_async_get_version(void);
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _HAL_SYNC_USART_H_INCLUDED */
#endif /* _HAL_USART_ASYNC_H_INCLUDED */
/**
* \file
*
* \brief ADC related functionality declaration.
*
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _HPL_ADC_ASYNC_H_INCLUDED
#define _HPL_ADC_ASYNC_H_INCLUDED
/**
* \addtogroup HPL ADC
*
* \section hpl_async_adc_rev Revision History
* - v1.0.0 Initial Release
*
*@{
*/
#include "hpl_adc_sync.h"
#include "hpl_irq.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief ADC device structure
*
* The ADC device structure forward declaration.
*/
struct _adc_async_device;
/**
* \brief ADC callback types
*/
enum _adc_async_callback_type { ADC_ASYNC_DEVICE_CONVERT_CB, ADC_ASYNC_DEVICE_MONITOR_CB, ADC_ASYNC_DEVICE_ERROR_CB };
/**
* \brief ADC interrupt callbacks
*/
struct _adc_async_callbacks {
void (*window_cb)(struct _adc_async_device *device, const uint8_t channel);
void (*error_cb)(struct _adc_async_device *device, const uint8_t channel);
};
/**
* \brief ADC channel interrupt callbacks
*/
struct _adc_async_ch_callbacks {
void (*convert_done)(struct _adc_async_device *device, const uint8_t channel, const uint16_t data);
};
/**
* \brief ADC descriptor device structure
*/
struct _adc_async_device {
struct _adc_async_callbacks adc_async_cb;
struct _adc_async_ch_callbacks adc_async_ch_cb;
struct _irq_descriptor irq;
void * hw;
};
/**
* \name HPL functions
*/
//@{
/**
* \brief Initialize synchronous ADC
*
* This function does low level ADC configuration.
*
* param[in] device The pointer to ADC device instance
* param[in] hw The pointer to hardware instance
*
* \return Initialization status
*/
int32_t _adc_async_init(struct _adc_async_device *const device, void *const hw);
/**
* \brief Deinitialize ADC
*
* \param[in] device The pointer to ADC device instance
*/
void _adc_async_deinit(struct _adc_async_device *const device);
/**
* \brief Enable ADC peripheral
*
* \param[in] device The pointer to ADC device instance
* \param[in] channel Channel number
*/
void _adc_async_enable_channel(struct _adc_async_device *const device, const uint8_t channel);
/**
* \brief Disable ADC peripheral
*
* \param[in] device The pointer to ADC device instance
* \param[in] channel Channel number
*/
void _adc_async_disable_channel(struct _adc_async_device *const device, const uint8_t channel);
/**
* \brief Retrieve ADC conversion data size
*
* \param[in] device The pointer to ADC device instance
*
* \return The data size in bytes
*/
uint8_t _adc_async_get_data_size(const struct _adc_async_device *const device);
/**
* \brief Check if conversion is done
*
* \param[in] device The pointer to ADC device instance
* \param[in] channel Channel number
*
* \return The status of conversion
* \retval true The conversion is done
* \retval false The conversion is not done
*/
bool _adc_async_is_channel_conversion_done(const struct _adc_async_device *const device, const uint8_t channel);
/**
* \brief Make conversion
*
* \param[in] device The pointer to ADC device instance
*/
void _adc_async_convert(struct _adc_async_device *const device);
/**
* \brief Retrieve the conversion result
*
* \param[in] device The pointer to ADC device instance
* \param[in] channel Channel number
*
* The result value
*/
uint16_t _adc_async_read_channel_data(const struct _adc_async_device *const device, const uint8_t channel);
/**
* \brief Set reference source
*
* \param[in] device The pointer to ADC device instance
* \param[in] reference A reference source to set
*/
void _adc_async_set_reference_source(struct _adc_async_device *const device, const adc_reference_t reference);
/**
* \brief Set resolution
*
* \param[in] device The pointer to ADC device instance
* \param[in] resolution A resolution to set
*/
void _adc_async_set_resolution(struct _adc_async_device *const device, const adc_resolution_t resolution);
/**
* \brief Set ADC input source of a channel
*
* \param[in] device The pointer to ADC device instance
* \param[in] pos_input A positive input source to set
* \param[in] neg_input A negative input source to set
* \param[in] channel Channel number
*/
void _adc_async_set_inputs(struct _adc_async_device *const device, const adc_pos_input_t pos_input,
const adc_neg_input_t neg_input, const uint8_t channel);
/**
* \brief Set conversion mode
*
* \param[in] device The pointer to ADC device instance
* \param[in] mode A conversion mode to set
*/
void _adc_async_set_conversion_mode(struct _adc_async_device *const device, const enum adc_conversion_mode mode);
/**
* \brief Set differential mode
*
* \param[in] device The pointer to ADC device instance
* \param[in] channel Channel number
* \param[in] mode A differential mode to set
*/
void _adc_async_set_channel_differential_mode(struct _adc_async_device *const device, const uint8_t channel,
const enum adc_differential_mode mode);
/**
* \brief Set gain
*
* \param[in] device The pointer to ADC device instance
* \param[in] channel Channel number
* \param[in] gain A gain to set
*/
void _adc_async_set_channel_gain(struct _adc_async_device *const device, const uint8_t channel, const adc_gain_t gain);
/**
* \brief Set window mode
*
* \param[in] device The pointer to ADC device instance
* \param[in] mode A mode to set
*/
void _adc_async_set_window_mode(struct _adc_async_device *const device, const adc_window_mode_t mode);
/**
* \brief Set lower threshold
*
* \param[in] device The pointer to ADC device instance
* \param[in] low_threshold A lower threshold to set
* \param[in] up_threshold An upper thresholds to set
*/
void _adc_async_set_thresholds(struct _adc_async_device *const device, const adc_threshold_t low_threshold,
const adc_threshold_t up_threshold);
/**
* \brief Retrieve threshold state
*
* \param[in] device The pointer to ADC device instance
* \param[out] state The threshold state
*/
void _adc_async_get_threshold_state(const struct _adc_async_device *const device, adc_threshold_status_t *const state);
/**
* \brief Enable/disable ADC channel interrupt
*
* \param[in] device The pointer to ADC device instance
* \param[in] channel Channel number
* \param[in] type The type of interrupt to disable/enable if applicable
* \param[in] state Enable or disable
*/
void _adc_async_set_irq_state(struct _adc_async_device *const device, const uint8_t channel,
const enum _adc_async_callback_type type, const bool state);
//@}
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _HPL_ADC_ASYNC_H_INCLUDED */
/**
* \file
*
* \brief ADC related functionality declaration.
*
* Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _HPL_ADC_DMA_H_INCLUDED
#define _HPL_ADC_DMA_H_INCLUDED
/**
* \addtogroup HPL ADC
*
* \section hpl_dma_adc_rev Revision History
* - v1.0.0 Initial Release
*
*@{
*/
#include <hpl_adc_sync.h>
#include <hpl_irq.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief ADC device structure
*
* The ADC device structure forward declaration.
*/
struct _adc_dma_device;
/**
* \brief ADC callback types
*/
enum _adc_dma_callback_type { ADC_DMA_DEVICE_COMPLETE_CB, ADC_DMA_DEVICE_ERROR_CB };
/**
* \brief ADC interrupt callbacks
*/
struct _adc_dma_callbacks {
void (*complete)(struct _adc_dma_device *device, const uint16_t data);
void (*error)(struct _adc_dma_device *device);
};
/**
* \brief ADC descriptor device structure
*/
struct _adc_dma_device {
struct _adc_dma_callbacks adc_dma_cb;
struct _irq_descriptor irq;
void * hw;
};
/**
* \name HPL functions
*/
//@{
/**
* \brief Initialize synchronous ADC
*
* This function does low level ADC configuration.
*
* param[in] device The pointer to ADC device instance
* param[in] hw The pointer to hardware instance
*
* \return Initialization status
*/
int32_t _adc_dma_init(struct _adc_dma_device *const device, void *const hw);
/**
* \brief Deinitialize ADC
*
* \param[in] device The pointer to ADC device instance
*/
void _adc_dma_deinit(struct _adc_dma_device *const device);
/**
* \brief Enable ADC peripheral
*
* \param[in] device The pointer to ADC device instance
* \param[in] channel Channel number
*/
void _adc_dma_enable_channel(struct _adc_dma_device *const device, const uint8_t channel);
/**
* \brief Disable ADC peripheral
*
* \param[in] device The pointer to ADC device instance
* \param[in] channel Channel number
*/
void _adc_dma_disable_channel(struct _adc_dma_device *const device, const uint8_t channel);
/**
* \brief Return address of ADC DMA source
*
* \param[in] device The pointer to ADC device instance
*
* \return ADC DMA source address
*/
uint32_t _adc_get_source_for_dma(struct _adc_dma_device *const device);
/**
* \brief Retrieve ADC conversion data size
*
* \param[in] device The pointer to ADC device instance
*
* \return The data size in bytes
*/
uint8_t _adc_dma_get_data_size(const struct _adc_dma_device *const device);
/**
* \brief Check if conversion is done
*
* \param[in] device The pointer to ADC device instance
*
* \return The status of conversion
* \retval true The conversion is done
* \retval false The conversion is not done
*/
bool _adc_dma_is_conversion_done(const struct _adc_dma_device *const device);
/**
* \brief Make conversion
*
* \param[in] device The pointer to ADC device instance
*/
void _adc_dma_convert(struct _adc_dma_device *const device);
/**
* \brief Set reference source
*
* \param[in] device The pointer to ADC device instance
* \param[in] reference A reference source to set
*/
void _adc_dma_set_reference_source(struct _adc_dma_device *const device, const adc_reference_t reference);
/**
* \brief Set resolution
*
* \param[in] device The pointer to ADC device instance
* \param[in] resolution A resolution to set
*/
void _adc_dma_set_resolution(struct _adc_dma_device *const device, const adc_resolution_t resolution);
/**
* \brief Set ADC input source of a channel
*
* \param[in] device The pointer to ADC device instance
* \param[in] pos_input A positive input source to set
* \param[in] neg_input A negative input source to set
* \param[in] channel Channel number
*/
void _adc_dma_set_inputs(struct _adc_dma_device *const device, const adc_pos_input_t pos_input,
const adc_neg_input_t neg_input, const uint8_t channel);
/**
* \brief Set conversion mode
*
* \param[in] device The pointer to ADC device instance
* \param[in] mode A conversion mode to set
*/
void _adc_dma_set_conversion_mode(struct _adc_dma_device *const device, const enum adc_conversion_mode mode);
/**
* \brief Set differential mode
*
* \param[in] device The pointer to ADC device instance
* \param[in] channel Channel number
* \param[in] mode A differential mode to set
*/
void _adc_dma_set_channel_differential_mode(struct _adc_dma_device *const device, const uint8_t channel,
const enum adc_differential_mode mode);
/**
* \brief Set gain
*
* \param[in] device The pointer to ADC device instance
* \param[in] channel Channel number
* \param[in] gain A gain to set
*/
void _adc_dma_set_channel_gain(struct _adc_dma_device *const device, const uint8_t channel, const adc_gain_t gain);
/**
* \brief Set window mode
*
* \param[in] device The pointer to ADC device instance
* \param[in] mode A mode to set
*/
void _adc_dma_set_window_mode(struct _adc_dma_device *const device, const adc_window_mode_t mode);
/**
* \brief Set thresholds
*
* \param[in] device The pointer to ADC device instance
* \param[in] low_threshold A lower thresholds to set
* \param[in] up_threshold An upper thresholds to set
*/
void _adc_dma_set_thresholds(struct _adc_dma_device *const device, const adc_threshold_t low_threshold,
const adc_threshold_t up_threshold);
/**
* \brief Retrieve threshold state
*
* \param[in] device The pointer to ADC device instance
* \param[out] state The threshold state
*/
void _adc_dma_get_threshold_state(const struct _adc_dma_device *const device, adc_threshold_status_t *const state);
//@}
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _HPL_ADC_DMA_H_INCLUDED */
此差异已折叠。
此差异已折叠。
此差异已折叠。
/**
* \file
*
* \brief Ringbuffer declaration.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _UTILS_RINGBUFFER_H_INCLUDED
#define _UTILS_RINGBUFFER_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup doc_driver_hal_utils_ringbuffer
*
* @{
*/
#include "compiler.h"
#include "utils_assert.h"
/**
* \brief Ring buffer element type
*/
struct ringbuffer {
uint8_t *buf; /** Buffer base address */
uint32_t size; /** Buffer size */
uint32_t read_index; /** Buffer read index */
uint32_t write_index; /** Buffer write index */
};
/**
* \brief Ring buffer init
*
* \param[in] rb The pointer to a ring buffer structure instance
* \param[in] buf Space to store the data
* \param[in] size The buffer length, must be aligned with power of 2
*
* \return ERR_NONE on success, or an error code on failure.
*/
int32_t ringbuffer_init(struct ringbuffer *const rb, void *buf, uint32_t size);
/**
* \brief Get one byte from ring buffer, the user needs to handle the concurrent
* access on buffer via put/get/flush
*
* \param[in] rb The pointer to a ring buffer structure instance
* \param[in] data One byte space to store the read data
*
* \return ERR_NONE on success, or an error code on failure.
*/
int32_t ringbuffer_get(struct ringbuffer *const rb, uint8_t *data);
/**
* \brief Put one byte to ring buffer, the user needs to handle the concurrent access
* on buffer via put/get/flush
*
* \param[in] rb The pointer to a ring buffer structure instance
* \param[in] data One byte data to be put into ring buffer
*
* \return ERR_NONE on success, or an error code on failure.
*/
int32_t ringbuffer_put(struct ringbuffer *const rb, uint8_t data);
/**
* \brief Return the element number of ring buffer
*
* \param[in] rb The pointer to a ring buffer structure instance
*
* \return The number of elements in ring buffer [0, rb->size]
*/
uint32_t ringbuffer_num(const struct ringbuffer *const rb);
/**
* \brief Flush ring buffer, the user needs to handle the concurrent access on buffer
* via put/get/flush
*
* \param[in] rb The pointer to a ring buffer structure instance
*
* \return ERR_NONE on success, or an error code on failure.
*/
uint32_t ringbuffer_flush(struct ringbuffer *const rb);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* _UTILS_RINGBUFFER_H_INCLUDED */
此差异已折叠。
......@@ -58,6 +58,31 @@ SECTIONS
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* section information for finsh shell */
. = ALIGN(4);
__fsymtab_start = .;
KEEP(*(FSymTab))
__fsymtab_end = .;
. = ALIGN(4);
__vsymtab_start = .;
KEEP(*(VSymTab))
__vsymtab_end = .;
. = ALIGN(4);
/* section information for initial. */
. = ALIGN(4);
__rt_init_start = .;
KEEP(*(SORT(.rti_fn*)))
__rt_init_end = .;
. = ALIGN(4);
/* section information for utest */
. = ALIGN(4);
__rt_utest_tc_tab_start = .;
KEEP(*(UtestTcTab))
__rt_utest_tc_tab_end = .;
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册