feat: 完成TCP2UART透传核心集成
集成CH390驱动、LwIP协议栈和FreeRTOS多任务透传框架,确保TCP Server/Client与UART链路按配置稳定联动。
This commit is contained in:
@@ -0,0 +1,615 @@
|
||||
/********************************** (C) COPYRIGHT *****************************
|
||||
* File Name : CH390.c
|
||||
* Author : WCH
|
||||
* Version : V1.1
|
||||
* Date : 2024/08/20
|
||||
* Description : CH390 Ethernet controller source file
|
||||
******************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
******************************************************************************/
|
||||
#include "CH390.h"
|
||||
#include "CH390_Interface.h"
|
||||
|
||||
/**
|
||||
* @name ch390_receive_packet
|
||||
* @brief Receive packet
|
||||
* @param buff - Size equal to CH390_PKT_MAX
|
||||
* @param rx_status - Output abnormal status while receiving packet.
|
||||
* It has the same meaning as RSR(06h).
|
||||
* @return Packet length
|
||||
*/
|
||||
uint32_t ch390_receive_packet(uint8_t *buff, uint8_t *rx_status)
|
||||
{
|
||||
uint8_t rx_ready;
|
||||
uint16_t rx_len = 0;
|
||||
uint8_t ReceiveData[4];
|
||||
|
||||
// Check packet ready or not
|
||||
ch390_read_reg(CH390_MRCMDX);
|
||||
rx_ready = ch390_read_reg(CH390_MRCMDX);
|
||||
|
||||
// if rxbyte != 1 or 0 reset pointer
|
||||
if (rx_ready & CH390_PKT_ERR)
|
||||
{
|
||||
// Reset RX FIFO pointer
|
||||
uint8_t rcr = ch390_read_reg(CH390_RCR);
|
||||
ch390_write_reg(CH390_RCR, rcr & ~RCR_RXEN); //RX disable
|
||||
ch390_write_reg(CH390_MPTRCR, 0x01); //Reset RX FIFO pointer
|
||||
ch390_write_reg(CH390_MRRH, 0x0c);
|
||||
ch390_delay_us(1000);
|
||||
ch390_write_reg(CH390_RCR, rcr | RCR_RXEN); //RX Enable
|
||||
return 0;
|
||||
}
|
||||
if (!(rx_ready & CH390_PKT_RDY))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ch390_read_mem(ReceiveData, 4);
|
||||
|
||||
*rx_status = ReceiveData[1];
|
||||
rx_len = ReceiveData[2] | (ReceiveData[3] << 8);
|
||||
|
||||
if(rx_len <= CH390_PKT_MAX)
|
||||
{
|
||||
ch390_read_mem(buff, rx_len);
|
||||
}
|
||||
|
||||
if ((*rx_status & 0x3f) || (rx_len > CH390_PKT_MAX))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return rx_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_send_packet
|
||||
* @brief Send packet
|
||||
* @param buff - Data to be sent
|
||||
* @param length - Less than 3k bytes.
|
||||
*/
|
||||
void ch390_send_packet(uint8_t *buff, uint16_t length)
|
||||
{
|
||||
// Write data to SRAM
|
||||
ch390_write_mem(buff, length);
|
||||
// Wait until last transmit complete
|
||||
while(ch390_read_reg(CH390_TCR) & TCR_TXREQ);
|
||||
// Set current packet length
|
||||
ch390_write_reg(CH390_TXPLL, length & 0xff);
|
||||
ch390_write_reg(CH390_TXPLH, (length >> 8) & 0xff);
|
||||
// Issue transmit request
|
||||
ch390_send_request();
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_send_request
|
||||
* @brief Issue transmit request
|
||||
*/
|
||||
void ch390_send_request()
|
||||
{
|
||||
uint8_t tcr = ch390_read_reg(CH390_TCR);
|
||||
ch390_write_reg(CH390_TCR, tcr | TCR_TXREQ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_drop_packet
|
||||
* @brief Drop packet in RX SRAM if don't want to read it. This function
|
||||
* modify the memory data read pointer and skip specified length
|
||||
* @param len - Skip length, length of the current packet.
|
||||
*/
|
||||
void ch390_drop_packet(uint16_t len)
|
||||
{
|
||||
uint16_t mdr = ch390_read_reg(CH390_MRRL) | (ch390_read_reg(CH390_MRRH) << 8);
|
||||
#ifdef CH390_INTERFACE_16_BIT
|
||||
mdr = mdr + (len + 1) / 2 * 2;
|
||||
#else
|
||||
mdr = mdr + len;
|
||||
#endif
|
||||
mdr = mdr < 0x4000 ? mdr : mdr - 0x3400;
|
||||
ch390_write_reg(CH390_MRRL, mdr & 0xff);
|
||||
ch390_write_reg(CH390_MRRH, (mdr >> 8) & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_read_phy
|
||||
* @brief Read PHY register
|
||||
* @param reg - PHY register address
|
||||
*/
|
||||
uint16_t ch390_read_phy(uint8_t reg)
|
||||
{
|
||||
ch390_write_reg(CH390_EPAR, CH390_PHY | reg);
|
||||
// Chose PHY, send read command
|
||||
ch390_write_reg(CH390_EPCR, EPCR_ERPRR | EPCR_EPOS);
|
||||
while(ch390_read_reg(CH390_EPCR) & 0x01);
|
||||
// Clear read command
|
||||
ch390_write_reg(CH390_EPCR, 0x00);
|
||||
return (ch390_read_reg(CH390_EPDRH) << 8) |
|
||||
(ch390_read_reg(CH390_EPDRL) & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_write_phy
|
||||
* @brief Write PHY register
|
||||
* @param reg - PHY register address
|
||||
* @param value - Value to be written
|
||||
*/
|
||||
void ch390_write_phy(uint8_t reg, uint16_t value)
|
||||
{
|
||||
ch390_write_reg(CH390_EPAR, CH390_PHY | reg);
|
||||
ch390_write_reg(CH390_EPDRL, (value & 0xff)); // Low byte
|
||||
ch390_write_reg(CH390_EPDRH, ((value >> 8) & 0xff)); // High byte
|
||||
// Chose PHY, send write command
|
||||
ch390_write_reg(CH390_EPCR, 0x0A);
|
||||
while(ch390_read_reg(CH390_EPCR) & 0x01);
|
||||
// Clear write command
|
||||
ch390_write_reg(CH390_EPCR, 0x00);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_write_eeprom
|
||||
* @brief Write EEPROM register
|
||||
* @param reg - EEPROM register address
|
||||
* @param value - Value to be written
|
||||
*/
|
||||
void ch390_write_eeprom(uint8_t reg, uint16_t value)
|
||||
{
|
||||
ch390_write_reg(CH390_EPAR, reg);
|
||||
ch390_write_reg(CH390_EPDRL, (value & 0xff)); // Low byte
|
||||
ch390_write_reg(CH390_EPDRH, ((value >> 8) & 0xff)); // High byte
|
||||
// Chose EEPROM, send write command
|
||||
ch390_write_reg(CH390_EPCR, EPCR_ERPRW);
|
||||
while(ch390_read_reg(CH390_EPCR) & 0x01);
|
||||
// Clear write command
|
||||
ch390_write_reg(CH390_EPCR, 0x00);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_software_reset
|
||||
* @brief Software reset CH390 by NCR
|
||||
*/
|
||||
void ch390_software_reset()
|
||||
{
|
||||
ch390_write_reg(CH390_NCR, NCR_RST);
|
||||
ch390_delay_us(10);
|
||||
ch390_write_reg(CH390_NCR, 0);
|
||||
ch390_write_reg(CH390_NCR, NCR_RST);
|
||||
ch390_delay_us(10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_default_config
|
||||
* @brief Config CH390 with default options:
|
||||
* LED mode 1;
|
||||
* Enable transmit check sum generation;
|
||||
* Enable RX;
|
||||
* Enable all interrupt and PAR
|
||||
*/
|
||||
void ch390_default_config()
|
||||
{
|
||||
// CH390 has built-in MAC, this is not necessary
|
||||
// uint8_t mac_addr[6] = { 0x50, 0x54, 0x7B, 0x84, 0x00, 0x73 };
|
||||
// Multicast address hash table
|
||||
uint8_t multicase_addr[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
ch390_set_phy_mode(CH390_AUTO);
|
||||
// Clear status
|
||||
ch390_write_reg(CH390_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
|
||||
ch390_write_reg(CH390_ISR, 0xFF); // Clear interrupt status
|
||||
ch390_write_reg(CH390_TCR2, 0x80); // LED mode 1
|
||||
ch390_write_reg(CH390_TCSCR, TCSCR_ALL); // Enable check sum generation
|
||||
|
||||
// ch390_set_mac_address(mac_addr);
|
||||
ch390_set_multicast(multicase_addr);
|
||||
|
||||
// Enable all interrupt and PAR
|
||||
ch390_write_reg(CH390_IMR, IMR_ALL);
|
||||
// Enable RX
|
||||
ch390_write_reg(CH390_RCR, RCR_DIS_CRC | RCR_RXEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_set_phy_mode
|
||||
* @brief Set PHY mode and enable PHY.
|
||||
* PHY mode: Auto-negotiation, 10M/100M, full-duplex/half-duplex
|
||||
* @param mode - PHY mode
|
||||
*/
|
||||
void ch390_set_phy_mode(enum ch390_phy_mode mode)
|
||||
{
|
||||
uint16_t BMCR_value = 0;
|
||||
uint16_t ANAR_value = 0;
|
||||
switch (mode)
|
||||
{
|
||||
case CH390_10MFD:
|
||||
BMCR_value = 0x1100;
|
||||
ANAR_value = 0x41;
|
||||
break;
|
||||
case CH390_100MFD:
|
||||
BMCR_value = 0x3100;
|
||||
ANAR_value = 0x101;
|
||||
break;
|
||||
case CH390_AUTO:
|
||||
BMCR_value = 0x1000;
|
||||
ANAR_value = 0x01E1;
|
||||
break;
|
||||
}
|
||||
ch390_write_phy(CH390_PHY_BMCR, BMCR_value);
|
||||
ch390_write_phy(CH390_PHY_ANAR, ANAR_value);
|
||||
ch390_write_reg(CH390_GPR, 0x00); // Enable PHY
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_set_mac_address
|
||||
* @brief Set mac address
|
||||
* @param mac_addr - 6-byte length mac address array
|
||||
*/
|
||||
void ch390_set_mac_address(uint8_t *mac_addr)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
ch390_write_reg(CH390_PAR + i, mac_addr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_set_multicast
|
||||
* @brief Set multicast address hash table
|
||||
* @param multicast_addr - 8-byte length multicast address hash table array
|
||||
*/
|
||||
void ch390_set_multicast(uint8_t *multicast_hash)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
ch390_write_reg(CH390_MAR + i, multicast_hash[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief reflect an 8bit value.
|
||||
* Only for "ch390_compute_hash_bit"
|
||||
*/
|
||||
static uint8_t reflect_8(uint8_t val)
|
||||
{
|
||||
int i;
|
||||
uint8_t resVal = 0;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if ((val & (1 << i)) != 0)
|
||||
{
|
||||
resVal |= 1 << (7 - i);
|
||||
}
|
||||
}
|
||||
return resVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the corresponding hash bit of the MAC address.
|
||||
* Only for "ch390_set_hash_bit"
|
||||
* @param mac - Destination address
|
||||
* @return Hash bit number
|
||||
*/
|
||||
static uint8_t ch390_compute_hash_bit(uint8_t *mac)
|
||||
{
|
||||
int i;
|
||||
const uint32_t poly = 0x4C11DB7;
|
||||
uint32_t crc = 0xffffffff;
|
||||
|
||||
int byte_i = 0;
|
||||
for(byte_i = 0; byte_i < 6; byte_i++)
|
||||
{
|
||||
uint8_t cur_byte = reflect_8(mac[byte_i]);
|
||||
crc ^= cur_byte << 24;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if ((crc & 0x80000000) != 0)
|
||||
{
|
||||
crc = (crc << 1) ^ poly;
|
||||
}
|
||||
else
|
||||
{
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (crc ^ 0xffffffff) >> 26;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set MAR bit for a particular MAC address
|
||||
* @param mac - Destination address
|
||||
*/
|
||||
void ch390_set_hash_bit(uint8_t *mac)
|
||||
{
|
||||
uint8_t bit = ch390_compute_hash_bit(mac);
|
||||
uint8_t mar = CH390_MAR + bit / 8;
|
||||
|
||||
uint8_t mar_val = ch390_read_reg(mar);
|
||||
mar_val |= 1 << (bit % 8);
|
||||
ch390_write_reg(mar, mar_val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_get_mac
|
||||
* @brief Get mac address
|
||||
* @param mac_addr - 6-byte length mac address output
|
||||
*/
|
||||
void ch390_get_mac(uint8_t *mac_addr)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
mac_addr[i] = ch390_read_reg(CH390_PAR + i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_get_multicast
|
||||
* @brief Get multicast address hash table
|
||||
* @param multicast_addr - 8-byte length multicast address hash table output
|
||||
*/
|
||||
void ch390_get_multicast(uint8_t *multicast_hash)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
multicast_hash[i] = ch390_read_reg(CH390_MAR + i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_get_vendor_id
|
||||
* @brief Get vendor ID
|
||||
* @return Vendor ID
|
||||
*/
|
||||
uint16_t ch390_get_vendor_id()
|
||||
{
|
||||
uint16_t id;
|
||||
id = (ch390_read_reg(CH390_VIDL) & 0xff);
|
||||
id |= ch390_read_reg(CH390_VIDH) << 8;
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_get_product_id
|
||||
* @brief Get product ID
|
||||
* @return Product ID
|
||||
*/
|
||||
uint16_t ch390_get_product_id()
|
||||
{
|
||||
uint16_t id;
|
||||
id = (ch390_read_reg(CH390_PIDL) & 0xff);
|
||||
id |= ch390_read_reg(CH390_PIDH) << 8;
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_get_revision
|
||||
* @brief Get chip revision
|
||||
* @return Chip revision
|
||||
*/
|
||||
uint8_t ch390_get_revision()
|
||||
{
|
||||
return ch390_read_reg(CH390_CHIPR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_interrupt_config
|
||||
* @brief Interrupt configuration
|
||||
* @param mask - Interrupt to be enabled, see "CH390.h" IMR_xxx
|
||||
*/
|
||||
void ch390_interrupt_config(uint8_t mask)
|
||||
{
|
||||
ch390_write_reg(CH390_IMR, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_rx_enable
|
||||
* @brief Enable or disable packet receive
|
||||
* @param op - 0: disable 1: enable
|
||||
*/
|
||||
void ch390_rx_enable(int op)
|
||||
{
|
||||
uint8_t rcr = ch390_read_reg(CH390_RCR);
|
||||
|
||||
if(op == 0)
|
||||
rcr &= ~RCR_RXEN;
|
||||
else
|
||||
rcr |= RCR_RXEN;
|
||||
|
||||
ch390_write_reg(CH390_RCR, rcr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_rx_filter_config
|
||||
* @brief Configure receive filter.
|
||||
* @param config - See "CH390.h" RCR_xxx
|
||||
*/
|
||||
void ch390_rx_filter_config(uint8_t config)
|
||||
{
|
||||
uint8_t rcr = ch390_read_reg(CH390_RCR) & RCR_RXEN;
|
||||
ch390_write_reg(CH390_RCR, rcr | config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_wakeup_config
|
||||
* @brief Enable or disable wakeup_function
|
||||
* @param events - Events that trigger wakeup
|
||||
* WCR_LINKEN - Link status change
|
||||
* WCR_SAMPLEEN - Sample frame
|
||||
* WCR_MAGICEN - Magic packet
|
||||
* 0 - Disable wakeup function
|
||||
*/
|
||||
void ch390_wakeup_config(uint8_t events)
|
||||
{
|
||||
uint8_t ncr = ch390_read_reg(CH390_NCR);
|
||||
if(events)
|
||||
ncr |= NCR_WAKEEN;
|
||||
else {
|
||||
ncr &= ~NCR_WAKEEN;
|
||||
}
|
||||
ch390_write_reg(CH390_NCR, ncr);
|
||||
ch390_write_reg(CH390_WCR, events);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_wake_notify
|
||||
* @brief Wait for Magic Packet or Sample Frame and discard all
|
||||
* other packets.
|
||||
* If the application needs to use Wake On LAN, call this
|
||||
* function every time before MCU enters low power mode.
|
||||
* An external interrupt signal is accessible on WOL pin
|
||||
* when wake up event occurred.
|
||||
*/
|
||||
void ch390_wake_notify(void)
|
||||
{
|
||||
uint8_t ncr = ch390_read_reg(CH390_NCR);
|
||||
ch390_write_reg(CH390_NCR, ncr ^ 0x10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_loop_back_enable
|
||||
* @brief Enable loop back mode
|
||||
* @param op - 0: disable 1: enable
|
||||
*/
|
||||
void ch390_loop_back_enable(int op)
|
||||
{
|
||||
uint8_t ncr = ch390_read_reg(CH390_NCR) & ~0x06;
|
||||
|
||||
if(op == 1) ncr |= NCR_LBK_MAC;
|
||||
|
||||
ch390_write_reg(CH390_NCR, ncr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_get_duplex_mode
|
||||
* @brief Get current duplex mode of the internal PHY
|
||||
* @return 0: Half-duplex 1: Full-duplex
|
||||
*/
|
||||
int ch390_get_duplex_mode()
|
||||
{
|
||||
return !!(ch390_read_reg(CH390_NCR) & NCR_FDX);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_get_phy_speed
|
||||
* @brief Get the speed of the internal PHY.
|
||||
* Only valid after PHY linked
|
||||
* @return 0: 100Mbps 1: 10Mbps
|
||||
*/
|
||||
int ch390_get_phy_speed()
|
||||
{
|
||||
return !!(ch390_read_reg(CH390_NSR) & NSR_SPEED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_get_link_status
|
||||
* @brief Get link status of the internal PHY
|
||||
* @return 0: Link failed 1: Link OK
|
||||
*/
|
||||
int ch390_get_link_status()
|
||||
{
|
||||
uint8_t nsr = ch390_read_reg(CH390_NSR);
|
||||
return !!(nsr & NSR_LINKST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_sleep_control
|
||||
* @brief Enter or exit sleep mode
|
||||
* @param op - 0: Power up 1: Power down
|
||||
*/
|
||||
void ch390_sleep_control(int op)
|
||||
{
|
||||
if(op)
|
||||
{
|
||||
ch390_write_reg(CH390_SCCR, 0x01);
|
||||
}
|
||||
else
|
||||
{
|
||||
ch390_read_reg(CH390_RSCCR);
|
||||
ch390_delay_us(100);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CH390_INTERFACE_16_BIT
|
||||
/**
|
||||
* @name ch390_gpio_config
|
||||
* @brief Config the input/output direction of GPIO1~3
|
||||
* In 8-bit mode, GPIO4~6 are output only
|
||||
* @param GPIOx - CH390_GPIO1 ~ CH390_GPIO3
|
||||
* dir - 0: Input 1: Output
|
||||
*/
|
||||
void ch390_gpio_config(uint8_t GPIOx, uint8_t dir)
|
||||
{
|
||||
uint8_t gpcr = ch390_read_reg(CH390_GPCR);
|
||||
if(dir)
|
||||
{
|
||||
gpcr |= GPIOx;
|
||||
}
|
||||
else {
|
||||
gpcr &= ~GPIOx;
|
||||
}
|
||||
ch390_write_reg(CH390_GPCR, gpcr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_gpio_write_bit
|
||||
* @brief Sets or clears the selected gpio bit.
|
||||
* In SPI mode, only GPIO1~3 are available
|
||||
* @param GPIOx - CH390_GPIO1 ~ CH390_GPIO6
|
||||
* level - 0: Clear pin 1: Set pin
|
||||
*/
|
||||
void ch390_gpio_write_bit(uint8_t GPIOx, uint8_t level)
|
||||
{
|
||||
uint8_t gpr = ch390_read_reg(CH390_GPR);
|
||||
if(level)
|
||||
{
|
||||
gpr |= GPIOx;
|
||||
}
|
||||
else {
|
||||
gpr &= ~GPIOx;
|
||||
}
|
||||
ch390_write_reg(CH390_GPR, gpr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_gpio_read_bit
|
||||
* @brief Read gpio input, only CH390_GPIO1 ~ 3 are available
|
||||
* @param GPIOx - CH390_GPIO1 ~ CH390_GPIO3
|
||||
* @return Input pin value
|
||||
*/
|
||||
uint8_t ch390_gpio_read_bit(uint8_t GPIOx)
|
||||
{
|
||||
uint8_t gpr = ch390_read_reg(CH390_GPR);
|
||||
return !!(gpr & GPIOx);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name ch390_int_pin_config
|
||||
* @brief Configure INT pin output type and polarity
|
||||
* @param type - INCR_TYPE_OD: Open drain output
|
||||
* INCR_TYPE_PP: Push pull output
|
||||
* pol - INCR_POL_L: Active low
|
||||
* INCR_POL_H: Active high
|
||||
*/
|
||||
void ch390_int_pin_config(uint8_t type, uint8_t pol)
|
||||
{
|
||||
ch390_write_reg(CH390_INTCR, type | pol);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ch390_get_int_status
|
||||
* @brief Get CH390 interrupt status and clear them
|
||||
* @return Interrupt status
|
||||
*/
|
||||
uint8_t ch390_get_int_status()
|
||||
{
|
||||
uint8_t int_status = ch390_read_reg(CH390_ISR);
|
||||
// Clear interrupt status by write 1
|
||||
ch390_write_reg(CH390_ISR, int_status);
|
||||
return int_status;
|
||||
}
|
||||
@@ -0,0 +1,623 @@
|
||||
/********************************** (C) COPYRIGHT *****************************
|
||||
* File Name : CH390.h
|
||||
* Author : WCH
|
||||
* Version : V1.1
|
||||
* Date : 2024/08/20
|
||||
* Description : CH390 Ethernet controller header file
|
||||
******************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
******************************************************************************/
|
||||
#ifndef __CH390_H
|
||||
#define __CH390_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/********************************************************************
|
||||
* Interface selection
|
||||
*/
|
||||
|
||||
#define CH390_INTERFACE_SPI // CH390H/CH390D
|
||||
// #define CH390_INTERFACE_8_BIT // CH390L/CH390F 8-bit mode
|
||||
// #define CH390_INTERFACE_16_BIT // CH390L 16-bit mode
|
||||
|
||||
/* PHY mode definition */
|
||||
enum ch390_phy_mode
|
||||
{
|
||||
CH390_10MFD, // 10M full-duplex
|
||||
CH390_100MFD, // 100M full-duplex
|
||||
CH390_AUTO, // Auto negotiation
|
||||
};
|
||||
|
||||
/********************************************************************
|
||||
* Register definition
|
||||
*
|
||||
* There are some differences between the register definitions of
|
||||
* CH390H and CH390L
|
||||
*/
|
||||
|
||||
#ifdef CH390_INTERFACE_SPI
|
||||
#define CH390_NCR 0x00
|
||||
#define NCR_WAKEEN (1<<6) // Enable wakeup function
|
||||
#define NCR_FDX (1<<3) // Duplex mode of the internal PHY
|
||||
#define NCR_LBK_MAC (1<<1) // MAC loop-back
|
||||
#define NCR_RST (1<<0) // Softwate reset
|
||||
#define CH390_NSR 0x01
|
||||
#define NSR_SPEED (1<<7) // Speed of internal PHY
|
||||
#define NSR_LINKST (1<<6) // Link status of internal PHY
|
||||
#define NSR_WAKEST (1<<5) // Wakeup event status
|
||||
#define NSR_TX2END (1<<3) // Tx packet B complete status
|
||||
#define NSR_TX1END (1<<2) // Tx packet A complete status
|
||||
#define NSR_RXOV (1<<1) // Rx fifo overflow
|
||||
#define NSR_RXRDY (1<<0)
|
||||
#define CH390_TCR 0x02
|
||||
#define TCR_TJDIS (1<<6) // Transmit jabber timer
|
||||
#define TCR_PAD_DIS2 (1<<4) // PAD appends for packet B
|
||||
#define TCR_CRC_DIS2 (1<<3) // CRC appends for packet B
|
||||
#define TCR_PAD_DIS1 (1<<2) // PAD appends for packet A
|
||||
#define TCR_CRC_DIS1 (1<<1) // CRC appends for packet A
|
||||
#define TCR_TXREQ (1<<0) // Tx request
|
||||
#define CH390_TSRA 0x03
|
||||
#define CH390_TSRB 0x04
|
||||
#define TSR_TJTO (1<<7) // Transmit jabber time out
|
||||
#define TSR_LC (1<<6) // Loss of carrier
|
||||
#define TSR_NC (1<<5) // No carrier
|
||||
#define TSR_LCOL (1<<4) // Late collision
|
||||
#define TSR_COL (1<<3) // Collision packet
|
||||
#define TSR_EC (1<<2) // Excessive collision
|
||||
#define CH390_RCR 0x05
|
||||
#define RCR_DEFAULT 0x00 // Default settings
|
||||
#define RCR_WTDIS (1<<6) // Disable 2048 bytes watch dog
|
||||
#define RCR_DIS_CRC (1<<4) // Discard CRC error packet
|
||||
#define RCR_ALL (1<<3) // Pass all multicast
|
||||
#define RCR_RUNT (1<<2) // Pass runt packet
|
||||
#define RCR_PRMSC (1<<1) // Promiscuous mode
|
||||
#define RCR_RXEN (1<<0) // Enable RX
|
||||
#define CH390_RSR 0x06
|
||||
#define RSR_RF (1<<7) // Rnt frame
|
||||
#define RSR_MF (1<<6) // Multicast frame
|
||||
#define RSR_LCS (1<<5) // Late collision seen
|
||||
#define RSR_RWTO (1<<4) // Receive watchdog time-out
|
||||
#define RSR_PLE (1<<3) // Physical layer error
|
||||
#define RSR_AE (1<<2) // Alignment error
|
||||
#define RSR_CE (1<<1) // CRC error
|
||||
#define RSR_FOE (1<<0) // FIFO overflow error
|
||||
#define CH390_ROCR 0x07
|
||||
#define CH390_BPTR 0x08
|
||||
#define CH390_FCTR 0x09
|
||||
#define FCTR_HWOT(ot) (( ot & 0xf ) << 4)
|
||||
#define FCTR_LWOT(ot) ( ot & 0xf )
|
||||
#define CH390_FCR 0x0A
|
||||
#define CH390_EPCR 0x0B
|
||||
#define EPCR_REEP (1<<5) // Reload EEPROM
|
||||
#define EPCR_EPOS (1<<3) // EEPROM or PHY operation select
|
||||
#define EPCR_ERPRR (1<<2) // EEPROM or PHY read command
|
||||
#define EPCR_ERPRW (1<<1) // EEPROM or PHY write command
|
||||
#define EPCR_ERRE (1<<0) // EEPROM or PHY access status
|
||||
#define CH390_EPAR 0x0C
|
||||
#define CH390_EPDRL 0x0D
|
||||
#define CH390_EPDRH 0x0E
|
||||
#define CH390_WCR 0x0F
|
||||
#define WCR_LINKEN (1<<5) // Link status change wakeup
|
||||
#define WCR_SAMPLEEN (1<<4) // Sample frame wakeup
|
||||
#define WCR_MAGICEN (1<<3) // Magic packet wakeup
|
||||
#define WCR_LINKST (1<<2) // Link status change event
|
||||
#define WCR_SAMPLEST (1<<1) // Sample frame event
|
||||
#define WCR_MAGICST (1<<0) // Magic packet event
|
||||
#define CH390_PAR 0x10
|
||||
#define CH390_MAR 0x16
|
||||
#define CH390_GPCR 0x1E
|
||||
#define CH390_GPR 0x1F
|
||||
#define CH390_TRPAL 0x22
|
||||
#define CH390_TRPAH 0x23
|
||||
#define CH390_RWPAL 0x24
|
||||
#define CH390_RWPAH 0x25
|
||||
#define CH390_VIDL 0x28
|
||||
#define CH390_VIDH 0x29
|
||||
#define CH390_PIDL 0x2A
|
||||
#define CH390_PIDH 0x2B
|
||||
#define CH390_CHIPR 0x2C
|
||||
#define CH390_TCR2 0x2D
|
||||
#define CH390_ATCR 0x30
|
||||
#define CH390_TCSCR 0x31
|
||||
#define TCSCR_ALL 0x1F
|
||||
#define TCSCR_IPv6TCPCSE (1<<4) // IPv6 TCP checksum generation
|
||||
#define TCSCR_IPv6UDPCSE (1<<3) // IPv6 UDP checksum generation
|
||||
#define TCSCR_UDPCSE (1<<2) // UDP checksum generation
|
||||
#define TCSCR_TCPCSE (1<<1) // TCP checksum generation
|
||||
#define TCSCR_IPCSE (1<<0) // IP checksum generation
|
||||
#define CH390_RCSCSR 0x32
|
||||
#define RCSCSR_UDPS (1<<7) // UDP checksum status
|
||||
#define RCSCSR_TCPS (1<<6) // TCP checksum status
|
||||
#define RCSCSR_IPS (1<<5) // IP checksum status
|
||||
#define RCSCSR_UDPP (1<<4) // UDP packet of current received packet
|
||||
#define RCSCSR_TCPP (1<<3) // TCP packet of current received packet
|
||||
#define RCSCSR_IPP (1<<2) // IP packet of current received packet
|
||||
#define RCSCSR_RCSEN (1<<1) // Receive checksum checking enable
|
||||
#define RCSCSR_DCSE (1<<0) // Discard checksum error packet
|
||||
#define CH390_MPAR 0x33
|
||||
#define CH390_SBCR 0x38
|
||||
#define CH390_INTCR 0x39
|
||||
#define INCR_TYPE_OD 0x02
|
||||
#define INCR_TYPE_PP 0x00
|
||||
#define INCR_POL_L 0x01
|
||||
#define INCR_POL_H 0x00
|
||||
#define CH390_ALNCR 0x4A
|
||||
#define CH390_SCCR 0x50
|
||||
#define CH390_RSCCR 0x51
|
||||
#define CH390_RLENCR 0x52
|
||||
#define CH390_BCASTCR 0x53
|
||||
#define CH390_INTCKCR 0x54
|
||||
#define CH390_MPTRCR 0x55
|
||||
#define CH390_MLEDCR 0x57
|
||||
#define CH390_MRCMDX 0x70
|
||||
#define CH390_MRCMDX1 0x71
|
||||
#define CH390_MRCMD 0x72
|
||||
#define CH390_MRRL 0x74
|
||||
#define CH390_MRRH 0x75
|
||||
#define CH390_MWCMDX 0x76
|
||||
#define CH390_MWCMD 0x78
|
||||
#define CH390_MWRL 0x7A
|
||||
#define CH390_MWRH 0x7B
|
||||
#define CH390_TXPLL 0x7C
|
||||
#define CH390_TXPLH 0x7D
|
||||
#define CH390_ISR 0x7E
|
||||
#define ISR_LNKCHG (1<<5) // Link status change
|
||||
#define ISR_ROO (1<<3) // Receive overflow counter overflow
|
||||
#define ISR_ROS (1<<2) // Receive overflow
|
||||
#define ISR_PT (1<<1) // Packet transmitted
|
||||
#define ISR_PR (1<<0) // Packet received
|
||||
#define CH390_IMR 0x7F
|
||||
#define IMR_NONE 0x00 // Disable all interrupt
|
||||
#define IMR_ALL 0xFF // Enable all interrupt
|
||||
#define IMR_PAR (1<<7) // Pointer auto-return mode
|
||||
#define IMR_LNKCHGI (1<<5) // Enable link status change interrupt
|
||||
#define IMR_UDRUNI (1<<4) // Enable transmit under-run interrupt
|
||||
#define IMR_ROOI (1<<3) // Enable receive overflow counter overflow interrupt
|
||||
#define IMR_ROI (1<<2) // Enable receive overflow interrupt
|
||||
#define IMR_PTI (1<<1) // Enable packet transmitted interrupt
|
||||
#define IMR_PRI (1<<0) // Enable packet received interrupt
|
||||
|
||||
// SPI commands
|
||||
#define OPC_REG_W 0x80 // Register Write
|
||||
#define OPC_REG_R 0x00 // Register Read
|
||||
#define OPC_MEM_DMY_R 0x70 // Memory Dummy Read
|
||||
#define OPC_MEM_WRITE 0xF8 // Memory Write
|
||||
#define OPC_MEM_READ 0x72 // Memory Read
|
||||
|
||||
// GPIO
|
||||
#define CH390_GPIO1 0x02
|
||||
#define CH390_GPIO2 0x04
|
||||
#define CH390_GPIO3 0x08
|
||||
|
||||
#else
|
||||
|
||||
#define CH390_NCR 0x00
|
||||
#define NCR_WAKEEN (1<<6) // Enable wakeup function
|
||||
#define NCR_FDX (1<<3) // Duplex mode of the internal PHY
|
||||
#define NCR_LBK_MAC (1<<1) // MAC loop-back
|
||||
#define NCR_RST (1<<0) // Softwate reset
|
||||
#define CH390_NSR 0x01
|
||||
#define NSR_SPEED (1<<7) // Speed of internal PHY
|
||||
#define NSR_LINKST (1<<6) // Link status of internal PHY
|
||||
#define NSR_WAKEST (1<<5) // Wakeup event status
|
||||
#define NSR_TX2END (1<<3) // Tx packet B complete status
|
||||
#define NSR_TX1END (1<<2) // Tx packet A complete status
|
||||
#define NSR_RXOV (1<<1) // Rx fifo overflow
|
||||
#define CH390_TCR 0x02
|
||||
#define TCR_TJDIS (1<<6) // Transmit jabber timer
|
||||
#define TCR_PAD_DIS2 (1<<4) // PAD appends for packet B
|
||||
#define TCR_CRC_DIS2 (1<<3) // CRC appends for packet B
|
||||
#define TCR_PAD_DIS1 (1<<2) // PAD appends for packet A
|
||||
#define TCR_CRC_DIS1 (1<<1) // CRC appends for packet A
|
||||
#define TCR_TXREQ (1<<0) // Tx request
|
||||
#define CH390_TSRA 0x03
|
||||
#define CH390_TSRB 0x04
|
||||
#define TSR_TJTO (1<<7) // Transmit jabber time out
|
||||
#define TSR_LC (1<<6) // Loss of carrier
|
||||
#define TSR_NC (1<<5) // No carrier
|
||||
#define TSR_LCOL (1<<4) // Late collision
|
||||
#define TSR_COL (1<<3) // Collision packet
|
||||
#define TSR_EC (1<<2) // Excessive collision
|
||||
#define CH390_RCR 0x05
|
||||
#define RCR_DEFAULT 0x00 // Default settings
|
||||
#define RCR_WTDIS (1<<6) // Disable 2048 bytes watch dog
|
||||
#define RCR_DIS_CRC (1<<4) // Discard CRC error packet
|
||||
#define RCR_ALL (1<<3) // Pass all multicast
|
||||
#define RCR_RUNT (1<<2) // Pass runt packet
|
||||
#define RCR_PRMSC (1<<1) // Promiscuous mode
|
||||
#define RCR_RXEN (1<<0) // Enable RX
|
||||
#define CH390_RSR 0x06
|
||||
#define RSR_RF (1<<7) // Rnt frame
|
||||
#define RSR_MF (1<<6) // Multicast frame
|
||||
#define RSR_LCS (1<<5) // Late collision seen
|
||||
#define RSR_RWTO (1<<4) // Receive watchdog time-out
|
||||
#define RSR_PLE (1<<3) // Physical layer error
|
||||
#define RSR_AE (1<<2) // Alignment error
|
||||
#define RSR_CE (1<<1) // CRC error
|
||||
#define RSR_FOE (1<<0) // FIFO overflow error
|
||||
#define CH390_ROCR 0x07
|
||||
#define CH390_BPTR 0x08
|
||||
#define CH390_FCTR 0x09
|
||||
#define FCTR_HWOT(ot) (( ot & 0xf ) << 4)
|
||||
#define FCTR_LWOT(ot) ( ot & 0xf )
|
||||
#define CH390_FCR 0x0A
|
||||
#define CH390_EPCR 0x0B
|
||||
#define EPCR_REEP (1<<5) // Reload EEPROM
|
||||
#define EPCR_EPOS (1<<3) // EEPROM or PHY operation select
|
||||
#define EPCR_ERPRR (1<<2) // EEPROM or PHY read command
|
||||
#define EPCR_ERPRW (1<<1) // EEPROM or PHY write command
|
||||
#define EPCR_ERRE (1<<0) // EEPROM or PHY access status
|
||||
#define CH390_EPAR 0x0C
|
||||
#define CH390_EPDRL 0x0D
|
||||
#define CH390_EPDRH 0x0E
|
||||
#define CH390_WCR 0x0F
|
||||
#define WCR_LINKEN (1<<5) // Link status change wakeup
|
||||
#define WCR_SAMPLEEN (1<<4) // Sample frame wakeup
|
||||
#define WCR_MAGICEN (1<<3) // Magic packet wakeup
|
||||
#define WCR_LINKST (1<<2) // Link status change event
|
||||
#define WCR_SAMPLEST (1<<1) // Sample frame event
|
||||
#define WCR_MAGICST (1<<0) // Magic packet event
|
||||
#define CH390_PAR 0x10
|
||||
#define CH390_MAR 0x16
|
||||
#define CH390_GPCR 0x1E
|
||||
#define CH390_GPR 0x1F
|
||||
#define CH390_TRPAL 0x22
|
||||
#define CH390_TRPAH 0x23
|
||||
#define CH390_RWPAL 0x24
|
||||
#define CH390_RWPAH 0x25
|
||||
#define CH390_VIDL 0x28
|
||||
#define CH390_VIDH 0x29
|
||||
#define CH390_PIDL 0x2A
|
||||
#define CH390_PIDH 0x2B
|
||||
#define CH390_CHIPR 0x2C
|
||||
#define CH390_TCR2 0x2D
|
||||
#define CH390_ETXCSR 0x30
|
||||
#define CH390_TCSCR 0x31
|
||||
#define TCSCR_ALL 0x1F
|
||||
#define TCSCR_IPv6TCPCSE (1<<4) // IPv6 TCP checksum generation
|
||||
#define TCSCR_IPv6UDPCSE (1<<3) // IPv6 UDP checksum generation
|
||||
#define TCSCR_UDPCSE (1<<2) // UDP checksum generation
|
||||
#define TCSCR_TCPCSE (1<<1) // TCP checksum generation
|
||||
#define TCSCR_IPCSE (1<<0) // IP checksum generation
|
||||
#define CH390_RCSCSR 0x32
|
||||
#define RCSCSR_UDPS (1<<7) // UDP checksum status
|
||||
#define RCSCSR_TCPS (1<<6) // TCP checksum status
|
||||
#define RCSCSR_IPS (1<<5) // IP checksum status
|
||||
#define RCSCSR_UDPP (1<<4) // UDP packet of current received packet
|
||||
#define RCSCSR_TCPP (1<<3) // TCP packet of current received packet
|
||||
#define RCSCSR_IPP (1<<2) // IP packet of current received packet
|
||||
#define RCSCSR_RCSEN (1<<1) // Receive checksum checking enable
|
||||
#define RCSCSR_DCSE (1<<0) // Discard checksum error packet
|
||||
#define CH390_MPAR 0x33
|
||||
#define CH390_LEDCR 0x34
|
||||
#define CH390_INTCR 0x39
|
||||
#define INCR_TYPE_OD 0x02
|
||||
#define INCR_TYPE_PP 0x00
|
||||
#define INCR_POL_L 0x01
|
||||
#define INCR_POL_H 0x00
|
||||
#define CH390_SCCR 0x50
|
||||
#define CH390_RSCCR 0x51
|
||||
#define CH390_RLENCR 0x52
|
||||
#define CH390_BCASTCR 0x53
|
||||
#define CH390_MPTRCR 0x55
|
||||
#define CH390_MRCMDX 0xF0
|
||||
#define CH390_MRCMDX1 0xF1
|
||||
#define CH390_MRCMD 0xF2
|
||||
#define CH390_MRRL 0xF4
|
||||
#define CH390_MRRH 0xF5
|
||||
#define CH390_MWCMDX 0xF6
|
||||
#define CH390_MWCMD 0xF8
|
||||
#define CH390_MWRL 0xFA
|
||||
#define CH390_MWRH 0xFB
|
||||
#define CH390_TXPLL 0xFC
|
||||
#define CH390_TXPLH 0xFD
|
||||
#define CH390_ISR 0xFE
|
||||
#define ISR_IOMODE (1<<7) // Parallel interface mode
|
||||
#define ISR_LNKCHG (1<<5) // Link status change
|
||||
#define ISR_UDRUN (1<<4) // Transmit under-run
|
||||
#define ISR_ROO (1<<3) // Receive overflow counter overflow
|
||||
#define ISR_ROS (1<<2) // Receive overflow
|
||||
#define ISR_PT (1<<1) // Packet transmitted
|
||||
#define ISR_PR (1<<0) // Packet received
|
||||
#define CH390_IMR 0xFF
|
||||
#define IMR_NONE 0x00 // Disable all interrupt
|
||||
#define IMR_ALL 0xFF // Enable all interrupt
|
||||
#define IMR_PAR (1<<7) // Pointer auto-return mode
|
||||
#define IMR_LNKCHGI (1<<5) // Enable link status change interrupt
|
||||
#define IMR_UDRUNI (1<<4) // Enable transmit under-run interrupt
|
||||
#define IMR_ROOI (1<<3) // Enable receive overflow counter overflow interrupt
|
||||
#define IMR_ROI (1<<2) // Enable receive overflow interrupt
|
||||
#define IMR_PTI (1<<1) // Enable packet transmitted interrupt
|
||||
#define IMR_PRI (1<<0) // Enable packet received interrupt
|
||||
|
||||
// GPIO
|
||||
#define CH390_GPIO1 0x02
|
||||
#define CH390_GPIO2 0x04
|
||||
#define CH390_GPIO3 0x08
|
||||
#define CH390_GPIO4 0x10
|
||||
#define CH390_GPIO5 0x20
|
||||
#define CH390_GPIO6 0x40
|
||||
#endif
|
||||
|
||||
// PHY registers
|
||||
#define CH390_PHY 0x40
|
||||
#define CH390_PHY_BMCR 0x00
|
||||
#define CH390_PHY_BMSR 0x01
|
||||
#define CH390_PHY_PHYID1 0x02
|
||||
#define CH390_PHY_PHYID2 0x03
|
||||
#define CH390_PHY_ANAR 0x04
|
||||
#define CH390_PHY_ANLPAR 0x05
|
||||
#define CH390_PHY_ANER 0x06
|
||||
#define CH390_PHY_PAGE_SEL 0x1F
|
||||
|
||||
// Packet status
|
||||
#define CH390_PKT_NONE 0x00 /* No packet received */
|
||||
#define CH390_PKT_RDY 0x01 /* Packet ready to receive */
|
||||
#define CH390_PKT_ERR 0xFE /* Un-stable states */
|
||||
#define CH390_PKT_MAX 1536 /* Received packet max size */
|
||||
#define CH390_PKT_MIN 64
|
||||
|
||||
/********************************************************************
|
||||
* Functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name ch390_receive_packet
|
||||
* @brief Receive packet
|
||||
* @param buff - Size equal to CH390_PKT_MAX
|
||||
* @param rx_status - Output abnormal status while receiving packet.
|
||||
* It has the same format as RSR(06h).
|
||||
* @return Packet length
|
||||
*/
|
||||
uint32_t ch390_receive_packet(uint8_t *buff, uint8_t *rx_status);
|
||||
|
||||
/**
|
||||
* @name ch390_send_packet
|
||||
* @brief Send packet
|
||||
* @param buff - Data to be sent
|
||||
* @param length - Less than 3k bytes.
|
||||
*/
|
||||
void ch390_send_packet(uint8_t *buff, uint16_t length);
|
||||
|
||||
/**
|
||||
* @name ch390_send_request
|
||||
* @brief Issue transmit request
|
||||
*/
|
||||
void ch390_send_request(void);
|
||||
|
||||
/**
|
||||
* @name ch390_drop_packet
|
||||
* @brief Drop packet in RX SRAM if don't want to read it. This function
|
||||
* modify the memory data read pointer and skip specified length
|
||||
* @param len - Skip length, length of the current packet.
|
||||
*/
|
||||
void ch390_drop_packet(uint16_t len);
|
||||
|
||||
/**
|
||||
* @name ch390_read_phy
|
||||
* @brief Read PHY register
|
||||
* @param reg - PHY register address
|
||||
*/
|
||||
uint16_t ch390_read_phy(uint8_t reg);
|
||||
|
||||
/**
|
||||
* @name ch390_write_phy
|
||||
* @brief Write PHY register
|
||||
* @param reg - PHY register address
|
||||
* @param value - Value to be written
|
||||
*/
|
||||
void ch390_write_phy(uint8_t reg, uint16_t value);
|
||||
|
||||
/**
|
||||
* @name ch390_write_eeprom
|
||||
* @brief Write EEPROM register
|
||||
* @param reg - EEPROM register address
|
||||
* @param value - Value to be written
|
||||
*/
|
||||
void ch390_write_eeprom(uint8_t reg, uint16_t value);
|
||||
|
||||
/**
|
||||
* @name ch390_software_reset
|
||||
* @brief Software reset CH390 by NCR
|
||||
*/
|
||||
void ch390_software_reset(void);
|
||||
|
||||
/**
|
||||
* @name ch390_default_config
|
||||
* @brief Config CH390 with default options:
|
||||
* LED mode 1;
|
||||
* Enable transmit check sum generation;
|
||||
* Enable RX;
|
||||
* Enable all interrupt and PAR
|
||||
*/
|
||||
void ch390_default_config(void);
|
||||
|
||||
/**
|
||||
* @name ch390_set_phy_mode
|
||||
* @brief Set PHY mode and enable PHY.
|
||||
* PHY mode: Auto-negotiation, 10M/100M, full-duplex/half-duplex
|
||||
* @param mode - PHY mode
|
||||
*/
|
||||
void ch390_set_phy_mode(enum ch390_phy_mode mode);
|
||||
|
||||
/**
|
||||
* @name ch390_set_mac_address
|
||||
* @brief Set mac address
|
||||
* @param mac_addr - 6-byte length mac address array
|
||||
*/
|
||||
void ch390_set_mac_address(uint8_t *mac_addr);
|
||||
|
||||
/**
|
||||
* @name ch390_set_multicast
|
||||
* @brief Set multicast address hash table
|
||||
* @param multicast_addr - 8-byte length multicast address hash table array
|
||||
*/
|
||||
void ch390_set_multicast(uint8_t *multicast_hash);
|
||||
|
||||
/**
|
||||
* @brief Set MAR bit for a particular MAC address
|
||||
* @param mac - Destination address
|
||||
*/
|
||||
void ch390_set_hash_bit(uint8_t *mac);
|
||||
|
||||
/**
|
||||
* @name ch390_get_mac
|
||||
* @brief Get mac address
|
||||
* @param mac_addr - 6 bytes mac address output
|
||||
*/
|
||||
void ch390_get_mac(uint8_t *mac_addr);
|
||||
|
||||
/**
|
||||
* @name ch390_get_multicast
|
||||
* @brief Get multicast address hash table
|
||||
* @param multicast_addr - 8-byte length multicast address hash table output
|
||||
*/
|
||||
void ch390_get_multicast(uint8_t *multicast_addr);
|
||||
|
||||
/**
|
||||
* @name ch390_get_vendor_id
|
||||
* @brief Get vendor ID
|
||||
* @return Vendor ID
|
||||
*/
|
||||
uint16_t ch390_get_vendor_id(void);
|
||||
|
||||
/**
|
||||
* @name ch390_get_product_id
|
||||
* @brief Get product ID
|
||||
* @return Product ID
|
||||
*/
|
||||
uint16_t ch390_get_product_id(void);
|
||||
|
||||
/**
|
||||
* @name ch390_get_revision
|
||||
* @brief Get chip revision
|
||||
* @return Chip revision
|
||||
*/
|
||||
uint8_t ch390_get_revision(void);
|
||||
|
||||
/**
|
||||
* @name ch390_interrupt_config
|
||||
* @brief Interrupt configuration
|
||||
* @param mask - Interrupt to be enabled, see "CH390.h" IMR_xxx
|
||||
*/
|
||||
void ch390_interrupt_config(uint8_t mask);
|
||||
|
||||
/**
|
||||
* @name ch390_rx_enable
|
||||
* @brief Enable or disable packet receive
|
||||
* @param op - 0: disable 1: enable
|
||||
*/
|
||||
void ch390_rx_enable(int op);
|
||||
|
||||
/**
|
||||
* @name ch390_rx_filter_config
|
||||
* @brief Configure receive filter.
|
||||
* @param config - See "CH390.h" RCR_xxx
|
||||
*/
|
||||
void ch390_rx_filter_config(uint8_t config);
|
||||
|
||||
/**
|
||||
* @name ch390_wakeup_config
|
||||
* @brief Enable or disable wakeup_function
|
||||
* @param events - Events that trigger wakeup,
|
||||
* WCR_LINKEN - Link status change
|
||||
* WCR_SAMPLEEN - Sample frame
|
||||
* WCR_MAGICEN - Magic packet
|
||||
* 0 - Disable wakeup function
|
||||
*/
|
||||
void ch390_wakeup_config(uint8_t events);
|
||||
|
||||
/**
|
||||
* @name ch390_wake_notify
|
||||
* @brief Wait for Magic Packet or Sample Frame and discard all
|
||||
* other packets.
|
||||
* If the application needs to use Wake On LAN, call this
|
||||
* function before MCU enters low power mode. An external
|
||||
* interrupt signal is accessible on WOL pin when wake
|
||||
* up event occurred.
|
||||
*/
|
||||
void ch390_wake_notify(void);
|
||||
|
||||
/**
|
||||
* @name ch390_loop_back_enable
|
||||
* @brief Enable loop back mode
|
||||
* @param op - 0: disable 1: enable
|
||||
*/
|
||||
void ch390_loop_back_enable(int op);
|
||||
|
||||
/**
|
||||
* @name ch390_get_duplex_mode
|
||||
* @brief Get current duplex mode of the internal PHY
|
||||
* @return 0: Half-duplex 1: Full-duplex
|
||||
*/
|
||||
int ch390_get_duplex_mode(void);
|
||||
|
||||
/**
|
||||
* @name ch390_get_phy_speed
|
||||
* @brief Get the speed of the internal PHY.
|
||||
* Only valid after PHY linked
|
||||
* @return 0: 100Mbps 1: 10Mbps
|
||||
*/
|
||||
int ch390_get_phy_speed(void);
|
||||
|
||||
/**
|
||||
* @name ch390_get_link_status
|
||||
* @brief Get link status of the internal PHY
|
||||
* @return 0: Link failed 1: Link OK
|
||||
*/
|
||||
int ch390_get_link_status(void);
|
||||
|
||||
/**
|
||||
* @name ch390_sleep_control
|
||||
* @brief Enter or exit sleep mode
|
||||
* @param op - 0: Power up 1: Power down
|
||||
*/
|
||||
void ch390_sleep_control(int op);
|
||||
|
||||
#ifndef CH390_INTERFACE_16_BIT
|
||||
/**
|
||||
* @name ch390_gpio_config
|
||||
* @brief Config the input/output direction of GPIO1~3
|
||||
* Only GPIO1~3 can be defined as input, GPIO4~6 are output only
|
||||
* @param GPIOx - CH390_GPIO1 ~ CH390_GPIO3
|
||||
* dir - 0: Input 1: Output
|
||||
*/
|
||||
void ch390_gpio_config(uint8_t GPIOx, uint8_t dir);
|
||||
|
||||
/**
|
||||
* @name ch390_gpio_write_bit
|
||||
* @brief Sets or clears the selected gpio bit.
|
||||
* @param GPIOx - CH390_GPIO1 ~ CH390_GPIO6
|
||||
* level - 0: Clear pin 1: Set pin
|
||||
*/
|
||||
void ch390_gpio_write_bit(uint8_t GPIOx, uint8_t level);
|
||||
|
||||
/**
|
||||
* @name ch390_gpio_read_bit
|
||||
* @brief Read gpio input, only CH390_GPIO1 ~ 3 are available
|
||||
* @param GPIOx - CH390_GPIO1 ~ CH390_GPIO3
|
||||
* @return Input pin value
|
||||
*/
|
||||
uint8_t ch390_gpio_read_bit(uint8_t GPIOx);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name ch390_int_pin_config
|
||||
* @brief Configure INT pin output type and polarity
|
||||
* @param type - INCR_TYPE_OD: Open drain output
|
||||
* INCR_TYPE_PP: Push pull output
|
||||
* pol - INCR_POL_L: Active low
|
||||
* INCR_POL_H: Active high
|
||||
*/
|
||||
void ch390_int_pin_config(uint8_t type, uint8_t pol);
|
||||
|
||||
/**
|
||||
* @name ch390_get_int_status
|
||||
* @brief Get CH390 interrupt status and clear them
|
||||
* @return Interrupt status
|
||||
*/
|
||||
uint8_t ch390_get_int_status(void);
|
||||
|
||||
#endif /* __CH390_H */
|
||||
@@ -0,0 +1,353 @@
|
||||
/********************************** (C) COPYRIGHT *****************************
|
||||
* File Name : CH390_Interface.c
|
||||
* Author : WCH (Modified for STM32 HAL)
|
||||
* Version : V1.1
|
||||
* Date : 2024/08/20
|
||||
* Description : CH390 interface for STM32 HAL Library (SPI mode)
|
||||
******************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*
|
||||
* Modified for STM32F103 HAL Library with FreeRTOS support.
|
||||
******************************************************************************/
|
||||
#include "stm32f1xx_hal.h"
|
||||
#include "CH390.h"
|
||||
#include "CH390_Interface.h"
|
||||
|
||||
/* FreeRTOS includes */
|
||||
#ifdef USE_FREERTOS
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file defines CH390 operation interface using STM32 HAL Library.
|
||||
* Only SPI mode is implemented for this project.
|
||||
*
|
||||
* Hardware connections:
|
||||
* - PA4: SPI1_NSS (directly controlled as GPIO for CS)
|
||||
* - PA5: SPI1_SCK
|
||||
* - PA6: SPI1_MISO
|
||||
* - PA7: SPI1_MOSI
|
||||
* - PB0: CH390 INT (EXTI0)
|
||||
* - PB1: CH390 RST
|
||||
*/
|
||||
|
||||
#ifdef CH390_INTERFACE_SPI
|
||||
|
||||
/* GPIO Pin Definitions - matching CubeMX configuration */
|
||||
#define CH390_CS_PORT GPIOA
|
||||
#define CH390_CS_PIN GPIO_PIN_4
|
||||
|
||||
#define CH390_RST_PORT GPIOB
|
||||
#define CH390_RST_PIN GPIO_PIN_1
|
||||
|
||||
#define CH390_INT_PORT GPIOB
|
||||
#define CH390_INT_PIN GPIO_PIN_0
|
||||
|
||||
/* External SPI handle from spi.c */
|
||||
extern SPI_HandleTypeDef hspi1;
|
||||
|
||||
/* Timeout for SPI operations (ms) */
|
||||
#define SPI_TIMEOUT 100
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Low-level GPIO operations
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Set CS pin state
|
||||
* @param state 0=low (select), 1=high (deselect)
|
||||
*/
|
||||
static inline void ch390_cs(uint8_t state)
|
||||
{
|
||||
HAL_GPIO_WritePin(CH390_CS_PORT, CH390_CS_PIN,
|
||||
state ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set RST pin state
|
||||
* @param state 0=low (reset), 1=high (normal)
|
||||
*/
|
||||
static inline void ch390_rst(uint8_t state)
|
||||
{
|
||||
HAL_GPIO_WritePin(CH390_RST_PORT, CH390_RST_PIN,
|
||||
state ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* SPI Communication
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Exchange one byte over SPI
|
||||
* @param byte Byte to send
|
||||
* @return Received byte
|
||||
*/
|
||||
static uint8_t ch390_spi_exchange_byte(uint8_t byte)
|
||||
{
|
||||
uint8_t rx_data = 0;
|
||||
HAL_SPI_TransmitReceive(&hspi1, &byte, &rx_data, 1, SPI_TIMEOUT);
|
||||
return rx_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a dummy byte (send 0x00)
|
||||
* @return Received byte
|
||||
*/
|
||||
#define ch390_spi_dummy_read() ch390_spi_exchange_byte(0x00)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Public Interface Functions
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initialize CH390 GPIO pins
|
||||
* @note CS and RST pins are configured here. SPI pins are handled by CubeMX.
|
||||
* INT pin (PB0) is configured as EXTI in CubeMX.
|
||||
*/
|
||||
void ch390_gpio_init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
|
||||
/* Enable GPIO clocks */
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
|
||||
/* Configure CS pin (PA4) as GPIO output - we control it manually */
|
||||
/* Note: CubeMX may configure PA4 as SPI1_NSS, we need to reconfigure it */
|
||||
HAL_GPIO_WritePin(CH390_CS_PORT, CH390_CS_PIN, GPIO_PIN_SET); /* Deselect */
|
||||
GPIO_InitStruct.Pin = CH390_CS_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(CH390_CS_PORT, &GPIO_InitStruct);
|
||||
|
||||
/* Configure RST pin (PB1) as output */
|
||||
HAL_GPIO_WritePin(CH390_RST_PORT, CH390_RST_PIN, GPIO_PIN_SET); /* Not reset */
|
||||
GPIO_InitStruct.Pin = CH390_RST_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(CH390_RST_PORT, &GPIO_InitStruct);
|
||||
|
||||
/* INT pin (PB0) is configured as EXTI input by CubeMX */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize CH390 interrupt (EXTI0 on PB0)
|
||||
* @note EXTI and NVIC are configured in CubeMX. This function can enable/disable.
|
||||
*/
|
||||
void ch390_interrupt_init(void)
|
||||
{
|
||||
/* EXTI0 is configured in CubeMX for PB0 */
|
||||
/* NVIC priority should be >= configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
/* for FreeRTOS compatibility */
|
||||
HAL_NVIC_SetPriority(EXTI0_IRQn, 6, 0);
|
||||
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize SPI for CH390
|
||||
* @note SPI1 is already initialized by CubeMX. This function reconfigures
|
||||
* for CH390 requirements (Mode 3: CPOL=High, CPHA=2Edge).
|
||||
*/
|
||||
void ch390_spi_init(void)
|
||||
{
|
||||
/* SPI1 is initialized by MX_SPI1_Init() in main.c */
|
||||
/* We need to ensure correct SPI mode for CH390: */
|
||||
/* - CPOL = High (idle clock is high) */
|
||||
/* - CPHA = 2Edge (data captured on second edge) */
|
||||
|
||||
/* Reconfigure SPI for CH390 if needed */
|
||||
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
|
||||
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
|
||||
hspi1.Init.NSS = SPI_NSS_SOFT; /* We control CS manually */
|
||||
|
||||
if (HAL_SPI_Init(&hspi1) != HAL_OK)
|
||||
{
|
||||
/* Handle error */
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get CH390 interrupt pin state
|
||||
* @return Non-zero if INT pin is high (active low interrupt)
|
||||
*/
|
||||
uint16_t ch390_get_int_pin(void)
|
||||
{
|
||||
return HAL_GPIO_ReadPin(CH390_INT_PORT, CH390_INT_PIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delay in microseconds
|
||||
* @param time Delay time in microseconds
|
||||
* @note Uses DWT cycle counter for accurate timing if available,
|
||||
* otherwise falls back to simple loop delay.
|
||||
*/
|
||||
void ch390_delay_us(uint32_t time)
|
||||
{
|
||||
#ifdef USE_FREERTOS
|
||||
/* For FreeRTOS, if delay is long enough, use vTaskDelay */
|
||||
if (time >= 1000)
|
||||
{
|
||||
/* Convert to milliseconds and use FreeRTOS delay if in task context */
|
||||
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(time / 1000));
|
||||
time = time % 1000;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Short delay using DWT or simple loop */
|
||||
if (time > 0)
|
||||
{
|
||||
/* Simple delay loop - approximately calibrated for 72MHz */
|
||||
/* Each iteration is roughly 1/9 us at 72MHz */
|
||||
volatile uint32_t count = time * 9;
|
||||
while (count--)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hardware reset CH390 by pulling RST pin low
|
||||
*/
|
||||
void ch390_hardware_reset(void)
|
||||
{
|
||||
ch390_rst(0); /* Assert reset (low) */
|
||||
ch390_delay_us(100); /* Hold reset for 100us (min 10us required) */
|
||||
ch390_rst(1); /* Release reset (high) */
|
||||
ch390_delay_us(10000); /* Wait 10ms for CH390 to initialize */
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* CH390 Register/Memory Access Functions (SPI Mode)
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Read a CH390 register
|
||||
* @param reg Register address
|
||||
* @return Register value
|
||||
*/
|
||||
uint8_t ch390_read_reg(uint8_t reg)
|
||||
{
|
||||
uint8_t value;
|
||||
|
||||
ch390_cs(0); /* CS low - select */
|
||||
ch390_spi_exchange_byte(reg | OPC_REG_R); /* Send read command */
|
||||
value = ch390_spi_dummy_read(); /* Read register value */
|
||||
ch390_cs(1); /* CS high - deselect */
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a CH390 register
|
||||
* @param reg Register address
|
||||
* @param value Value to write
|
||||
*/
|
||||
void ch390_write_reg(uint8_t reg, uint8_t value)
|
||||
{
|
||||
ch390_cs(0); /* CS low - select */
|
||||
ch390_spi_exchange_byte(reg | OPC_REG_W); /* Send write command */
|
||||
ch390_spi_exchange_byte(value); /* Write register value */
|
||||
ch390_cs(1); /* CS high - deselect */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from CH390 RX SRAM
|
||||
* @param data Buffer to store received data
|
||||
* @param length Number of bytes to read
|
||||
*/
|
||||
void ch390_read_mem(uint8_t *data, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
ch390_cs(0); /* CS low - select */
|
||||
ch390_spi_exchange_byte(OPC_MEM_READ); /* Send memory read command */
|
||||
|
||||
/* Read data bytes */
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
data[i] = ch390_spi_dummy_read();
|
||||
}
|
||||
|
||||
ch390_cs(1); /* CS high - deselect */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from CH390 RX SRAM using DMA (for larger transfers)
|
||||
* @param data Buffer to store received data
|
||||
* @param length Number of bytes to read
|
||||
* @note Falls back to polling mode for small transfers
|
||||
*/
|
||||
void ch390_read_mem_dma(uint8_t *data, int length)
|
||||
{
|
||||
/* For small transfers, use polling mode */
|
||||
if (length < 64)
|
||||
{
|
||||
ch390_read_mem(data, length);
|
||||
return;
|
||||
}
|
||||
|
||||
/* For larger transfers, could use DMA - currently using polling */
|
||||
/* TODO: Implement DMA transfer if needed for performance */
|
||||
ch390_read_mem(data, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write data to CH390 TX SRAM
|
||||
* @param data Data buffer to send
|
||||
* @param length Number of bytes to write
|
||||
*/
|
||||
void ch390_write_mem(uint8_t *data, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
ch390_cs(0); /* CS low - select */
|
||||
ch390_spi_exchange_byte(OPC_MEM_WRITE); /* Send memory write command */
|
||||
|
||||
/* Write data bytes */
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
ch390_spi_exchange_byte(data[i]);
|
||||
}
|
||||
|
||||
ch390_cs(1); /* CS high - deselect */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write data to CH390 TX SRAM using DMA (for larger transfers)
|
||||
* @param data Data buffer to send
|
||||
* @param length Number of bytes to write
|
||||
* @note Falls back to polling mode for small transfers
|
||||
*/
|
||||
void ch390_write_mem_dma(uint8_t *data, int length)
|
||||
{
|
||||
/* For small transfers, use polling mode */
|
||||
if (length < 64)
|
||||
{
|
||||
ch390_write_mem(data, length);
|
||||
return;
|
||||
}
|
||||
|
||||
/* For larger transfers, could use DMA - currently using polling */
|
||||
/* TODO: Implement DMA transfer if needed for performance */
|
||||
ch390_write_mem(data, length);
|
||||
}
|
||||
|
||||
#else /* CH390_INTERFACE_SPI */
|
||||
|
||||
/*
|
||||
* Non-SPI modes (8-bit/16-bit parallel) are not implemented for this project.
|
||||
* This project uses SPI interface only.
|
||||
*/
|
||||
#error "This project only supports CH390 SPI interface. Please define CH390_INTERFACE_SPI in CH390.h"
|
||||
|
||||
#endif /* CH390_INTERFACE_SPI */
|
||||
@@ -0,0 +1,55 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : CH390.h
|
||||
* Author : WCH
|
||||
* Version : V1.0
|
||||
* Date : 2024/08/20
|
||||
* Description : CH390 interface header file
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __CH390_INTERFACE_H
|
||||
#define __CH390_INTERFACE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "CH390.h"
|
||||
|
||||
void ch390_gpio_init(void);
|
||||
void ch390_interrupt_init(void);
|
||||
void ch390_spi_init(void);
|
||||
|
||||
uint16_t ch390_get_int_pin(void);
|
||||
void ch390_delay_us(uint32_t time);
|
||||
void ch390_hardware_reset(void);
|
||||
|
||||
/**
|
||||
* @name ch390_read_reg
|
||||
* @brief Read register
|
||||
* @param reg - Target register address
|
||||
* @return Register value
|
||||
*/
|
||||
uint8_t ch390_read_reg(uint8_t reg);
|
||||
|
||||
/**
|
||||
* @name ch390_write_reg
|
||||
* @brief Write register
|
||||
* @param reg - Target register address
|
||||
* @param value - Value to be written
|
||||
*/
|
||||
void ch390_write_reg(uint8_t reg, uint8_t value);
|
||||
|
||||
/**
|
||||
* @name ch390_read_mem
|
||||
* @brief Read data from RX SRAM
|
||||
* @param data - Data buffer
|
||||
* @param length - Length to read
|
||||
*/
|
||||
void ch390_read_mem(uint8_t *data, int length);
|
||||
|
||||
/**
|
||||
* @name ch390_write_mem
|
||||
* @brief Write data to TX SRAM
|
||||
* @param data - Data buffer
|
||||
* @param length - Length to write
|
||||
*/
|
||||
void ch390_write_mem(uint8_t *data, int length);
|
||||
|
||||
#endif /* __CH390_INTERFACE_H */
|
||||
Reference in New Issue
Block a user