summaryrefslogtreecommitdiff
path: root/bsp/microchip/common
diff options
context:
space:
mode:
authorKevin Liu <[email protected]>2022-04-19 14:32:02 +0800
committerGitHub <[email protected]>2022-04-19 14:32:02 +0800
commit7847c5e98d7ec7ca81b0b6dd5dfbd694ef3ba512 (patch)
treeb5f43a4fb12ca433c3a918a3a3e1792786ae3972 /bsp/microchip/common
parent991b6e78b3bd51b810f6e7a74e7b3665ed90dcab (diff)
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.
Diffstat (limited to 'bsp/microchip/common')
-rw-r--r--bsp/microchip/common/applications/SConscript23
-rw-r--r--bsp/microchip/common/applications/adc_demo.c74
-rw-r--r--bsp/microchip/common/applications/adc_demo.h22
-rw-r--r--bsp/microchip/common/applications/can_demo.c336
-rw-r--r--bsp/microchip/common/applications/can_demo.h24
-rw-r--r--bsp/microchip/common/applications/i2c_demo.c65
-rw-r--r--bsp/microchip/common/applications/i2c_demo.h22
-rw-r--r--bsp/microchip/common/applications/lwip_demo.c211
-rw-r--r--bsp/microchip/common/applications/lwip_demo.h22
-rw-r--r--bsp/microchip/common/board/SConscript21
-rw-r--r--bsp/microchip/common/board/sam_gmac.c428
-rw-r--r--bsp/microchip/common/board/sam_gmac.h36
-rw-r--r--bsp/microchip/common/board/sam_i2c.c122
-rw-r--r--bsp/microchip/common/board/sam_i2c.h22
-rw-r--r--bsp/microchip/common/board/serial.c232
-rw-r--r--bsp/microchip/common/board/serial.h22
16 files changed, 1682 insertions, 0 deletions
diff --git a/bsp/microchip/common/applications/SConscript b/bsp/microchip/common/applications/SConscript
new file mode 100644
index 0000000000..9bc4192bd2
--- /dev/null
+++ b/bsp/microchip/common/applications/SConscript
@@ -0,0 +1,23 @@
+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')
diff --git a/bsp/microchip/common/applications/adc_demo.c b/bsp/microchip/common/applications/adc_demo.c
new file mode 100644
index 0000000000..900719f97e
--- /dev/null
+++ b/bsp/microchip/common/applications/adc_demo.c
@@ -0,0 +1,74 @@
+/*
+ * 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 [email protected] 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
+
+/*@}*/
diff --git a/bsp/microchip/common/applications/adc_demo.h b/bsp/microchip/common/applications/adc_demo.h
new file mode 100644
index 0000000000..5819343be8
--- /dev/null
+++ b/bsp/microchip/common/applications/adc_demo.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Email Notes
+ * 2022-04-11 Kevin.Liu [email protected] First Release
+ */
+
+#ifndef __APPLICATION_ADC_H_
+#define __APPLICATION_ADC_H_
+
+#include <rtthread.h>
+
+/**
+ * @brief External function definitions
+ *
+ */
+rt_err_t adc_demo_run(void);
+
+#endif // __APPLICATION_I2C_H_
diff --git a/bsp/microchip/common/applications/can_demo.c b/bsp/microchip/common/applications/can_demo.c
new file mode 100644
index 0000000000..25a009f769
--- /dev/null
+++ b/bsp/microchip/common/applications/can_demo.c
@@ -0,0 +1,336 @@
+/*
+ * 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 [email protected] First Release
+ */
+
+#include <rtthread.h>
+
+#include "atmel_start.h"
+#include "driver_init.h"
+#include "utils.h"
+
+#include "can_demo.h"
+
+#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;
+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, CAN_HARDWARE);
+ }
+ }
+}
+
+/**
+ * @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
+
+/*@}*/
diff --git a/bsp/microchip/common/applications/can_demo.h b/bsp/microchip/common/applications/can_demo.h
new file mode 100644
index 0000000000..499d0390f8
--- /dev/null
+++ b/bsp/microchip/common/applications/can_demo.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Email Notes
+ * 2019-07-16 Kevin.Liu [email protected] First Release
+ */
+
+#ifndef __APPLICATION_CAN_H_
+#define __APPLICATION_CAN_H_
+
+#include <rtthread.h>
+
+/**
+ * @brief External function definitions
+ *
+ */
+rt_err_t can_demo_run(void);
+
+rt_err_t can_send_message(struct can_message *msg, rt_uint32_t timeouts);
+
+#endif // __APPLICATION_CAN_H_
diff --git a/bsp/microchip/common/applications/i2c_demo.c b/bsp/microchip/common/applications/i2c_demo.c
new file mode 100644
index 0000000000..6e6d132286
--- /dev/null
+++ b/bsp/microchip/common/applications/i2c_demo.c
@@ -0,0 +1,65 @@
+/*
+ * 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 [email protected] 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
+
+/*@}*/
diff --git a/bsp/microchip/common/applications/i2c_demo.h b/bsp/microchip/common/applications/i2c_demo.h
new file mode 100644
index 0000000000..7fc4b4af6e
--- /dev/null
+++ b/bsp/microchip/common/applications/i2c_demo.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Email Notes
+ * 2022-04-11 Kevin.Liu [email protected] 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_
diff --git a/bsp/microchip/common/applications/lwip_demo.c b/bsp/microchip/common/applications/lwip_demo.c
new file mode 100644
index 0000000000..85c6a97d93
--- /dev/null
+++ b/bsp/microchip/common/applications/lwip_demo.c
@@ -0,0 +1,211 @@
+/*
+ * 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
+
+/*@}*/
diff --git a/bsp/microchip/common/applications/lwip_demo.h b/bsp/microchip/common/applications/lwip_demo.h
new file mode 100644
index 0000000000..9c2abd3989
--- /dev/null
+++ b/bsp/microchip/common/applications/lwip_demo.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Email Notes
+ * 2022-04-11 Kevin.Liu [email protected] 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_
diff --git a/bsp/microchip/common/board/SConscript b/bsp/microchip/common/board/SConscript
new file mode 100644
index 0000000000..a32002a272
--- /dev/null
+++ b/bsp/microchip/common/board/SConscript
@@ -0,0 +1,21 @@
+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
diff --git a/bsp/microchip/common/board/sam_gmac.c b/bsp/microchip/common/board/sam_gmac.c
new file mode 100644
index 0000000000..953c3430f4
--- /dev/null
+++ b/bsp/microchip/common/board/sam_gmac.c
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Email Notes
+ * 2022-04-06 Kevin.Liu [email protected] 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 */
diff --git a/bsp/microchip/common/board/sam_gmac.h b/bsp/microchip/common/board/sam_gmac.h
new file mode 100644
index 0000000000..6c4d90658a
--- /dev/null
+++ b/bsp/microchip/common/board/sam_gmac.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Email Notes
+ * 2022-04-11 Kevin.Liu [email protected] 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_
diff --git a/bsp/microchip/common/board/sam_i2c.c b/bsp/microchip/common/board/sam_i2c.c
new file mode 100644
index 0000000000..7196e0c87d
--- /dev/null
+++ b/bsp/microchip/common/board/sam_i2c.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Email Notes
+ * 2022-04-11 Kevin.Liu [email protected] 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
+/*@}*/
diff --git a/bsp/microchip/common/board/sam_i2c.h b/bsp/microchip/common/board/sam_i2c.h
new file mode 100644
index 0000000000..5ea3149ced
--- /dev/null
+++ b/bsp/microchip/common/board/sam_i2c.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Email Notes
+ * 2022-04-11 Kevin.Liu [email protected] First Release
+ */
+
+#ifndef __BOARD_SAM_I2C_H_
+#define __BOARD_SAM_I2C_H_
+
+#include <rtthread.h>
+
+/**
+ * @brief External function definitions
+ *
+ */
+int rt_hw_i2c_init(void);
+
+#endif // __BOARD_SAM_I2C_H_
diff --git a/bsp/microchip/common/board/serial.c b/bsp/microchip/common/board/serial.c
new file mode 100644
index 0000000000..9878bc468a
--- /dev/null
+++ b/bsp/microchip/common/board/serial.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Email Notes
+ * 2019-07-16 Kevin.Liu [email protected] First Release
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include <atmel_start.h>
+
+/* 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
+ *
+ * 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_async_descriptor* desc;
+
+ RT_ASSERT(serial != RT_NULL);
+
+ desc = (struct usart_async_descriptor *)serial->parent.user_data;
+
+ RT_ASSERT(desc != RT_NULL);
+ RT_ASSERT(cfg != RT_NULL);
+
+ usart_async_disable(desc);
+
+ /* Set baudrate */
+ usart_async_set_baud_rate(desc, (const uint32_t)cfg->baud_rate);
+
+ /* Set stop bit */
+ if (cfg->stop_bits == STOP_BITS_1)
+ usart_async_set_stopbits(desc, USART_STOP_BITS_ONE);
+ else if (cfg->stop_bits == STOP_BITS_2)
+ usart_async_set_stopbits(desc, USART_STOP_BITS_TWO);
+
+ if (cfg->bit_order == BIT_ORDER_LSB)
+ usart_async_set_data_order(desc, USART_DATA_ORDER_LSB);
+ else if (cfg->bit_order == BIT_ORDER_MSB)
+ usart_async_set_data_order(desc, USART_DATA_ORDER_MSB);
+
+ /* Set character size */
+ switch (cfg->data_bits)
+ {
+ case DATA_BITS_5:
+ usart_async_set_character_size(desc, USART_CHARACTER_SIZE_5BITS);
+ break;
+ case DATA_BITS_6:
+ usart_async_set_character_size(desc, USART_CHARACTER_SIZE_6BITS);
+ break;
+ case DATA_BITS_7:
+ usart_async_set_character_size(desc, USART_CHARACTER_SIZE_7BITS);
+ break;
+ case DATA_BITS_8:
+ usart_async_set_character_size(desc, USART_CHARACTER_SIZE_8BITS);
+ break;
+ case DATA_BITS_9:
+ usart_async_set_character_size(desc, USART_CHARACTER_SIZE_9BITS);
+ break;
+ default:
+ break;
+ }
+
+ if (cfg->parity == PARITY_NONE)
+ usart_async_set_parity(desc, USART_PARITY_NONE);
+ else if (cfg->parity == PARITY_ODD)
+ usart_async_set_parity(desc, USART_PARITY_ODD);
+ else if (cfg->parity == PARITY_EVEN)
+ usart_async_set_parity(desc, USART_PARITY_EVEN);
+
+ usart_async_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_async_descriptor* desc;
+
+ RT_ASSERT(serial != RT_NULL);
+ desc = (struct usart_async_descriptor *)serial->parent.user_data;
+
+ RT_ASSERT(desc != RT_NULL);
+
+ switch (cmd)
+ {
+ /* disable interrupt */
+ case RT_DEVICE_CTRL_CLR_INT:
+ usart_async_disable(desc);
+ break;
+ /* enable interrupt */
+ case RT_DEVICE_CTRL_SET_INT:
+ usart_async_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_async_descriptor* desc;
+
+ RT_ASSERT(serial != RT_NULL);
+ desc = (struct usart_async_descriptor *)serial->parent.user_data;
+
+ RT_ASSERT(desc != RT_NULL);
+
+ while (usart_async_is_tx_empty(desc) == 0);
+ _usart_async_write_byte(&TARGET_IO.device, (uint8_t)c);
+
+ 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_async_descriptor* desc;
+
+ RT_ASSERT(serial != RT_NULL);
+ desc = (struct usart_async_descriptor *)serial->parent.user_data;
+
+ RT_ASSERT(desc != RT_NULL);
+
+ ch = -1;
+ if (usart_async_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, 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;
+}
+
+/*@}*/
diff --git a/bsp/microchip/common/board/serial.h b/bsp/microchip/common/board/serial.h
new file mode 100644
index 0000000000..12e6811231
--- /dev/null
+++ b/bsp/microchip/common/board/serial.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Email Notes
+ * 2019-07-16 Kevin.Liu [email protected] First Release
+ */
+
+#ifndef __BOARD_SERIAL_H_
+#define __BOARD_SERIAL_H_
+
+#include <rtthread.h>
+
+/**
+ * @brief External function definitions
+ *
+ */
+int rt_hw_uart_init(void);
+
+#endif // __BOARD_SERIAL_H_