feat: 保存已验证的CH390网络打通基线

This commit is contained in:
2026-04-17 07:09:55 +08:00
parent 59eecf428f
commit 6aba77df9a
44 changed files with 6428 additions and 3372 deletions
+175 -24
View File
@@ -11,6 +11,18 @@
******************************************************************************/
#include "CH390.h"
#include "CH390_Interface.h"
#include "../../App/app_runtime.h"
#include "../../Core/Inc/debug_log.h"
void ch390_probe_rx_header(uint8_t *head)
{
if (head == 0)
{
return;
}
ch390_read_mem(head, 4);
}
/**
* @name ch390_receive_packet
@@ -22,45 +34,133 @@
*/
uint32_t ch390_receive_packet(uint8_t *buff, uint8_t *rx_status)
{
static uint32_t s_rxrdy_miss_log_count = 0u;
uint32_t i;
uint8_t rx_ready;
uint8_t nsr;
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 (rx_status != 0)
{
*rx_status = 0u;
}
g_eth_last_rx_fail_stage = 0u;
g_eth_last_rx_status = 0u;
g_eth_last_rx_len = 0u;
g_eth_last_rx_head0 = 0u;
g_eth_last_rx_head1 = 0u;
g_eth_last_rx_head2 = 0u;
g_eth_last_rx_head3 = 0u;
g_eth_probe_rx_status = 0u;
g_eth_probe_rx_len = 0u;
g_eth_probe_head0 = 0u;
g_eth_probe_head1 = 0u;
g_eth_probe_head2 = 0u;
g_eth_probe_head3 = 0u;
for (i = 0u; i < 32u; ++i)
{
g_eth_probe_dump[i] = 0u;
}
g_eth_reprobe_rx_status = 0u;
g_eth_reprobe_rx_len = 0u;
g_eth_reprobe_head0 = 0u;
g_eth_reprobe_head1 = 0u;
g_eth_reprobe_head2 = 0u;
g_eth_reprobe_head3 = 0u;
// 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))
nsr = ch390_read_reg(CH390_NSR);
g_eth_last_nsr = nsr;
if ((nsr & NSR_RXRDY) == 0u)
{
g_eth_last_rx_fail_stage = 2u;
return 0;
}
rx_ready = 0u;
g_eth_last_rx_ready = 0u;
g_eth_last_mrcmdx = 0u;
g_eth_last_mrcmdx1 = 0u;
g_eth_last_mrrl = 0u;
g_eth_last_mrrh = 0u;
ch390_read_mem(ReceiveData, 4);
g_eth_last_rx_head0 = ReceiveData[0];
g_eth_last_rx_head1 = ReceiveData[1];
g_eth_last_rx_head2 = ReceiveData[2];
g_eth_last_rx_head3 = ReceiveData[3];
*rx_status = ReceiveData[1];
rx_len = ReceiveData[2] | (ReceiveData[3] << 8);
if (rx_status != 0)
{
*rx_status = ReceiveData[1];
}
rx_len = (uint16_t)ReceiveData[2] | ((uint16_t)ReceiveData[3] << 8);
g_eth_last_rx_status = ReceiveData[1];
g_eth_last_rx_len = rx_len;
if (((ReceiveData[1] & 0x3Fu) != 0u) ||
(rx_len < 14u) ||
(rx_len > CH390_PKT_MAX))
{
g_eth_last_rx_ready = rx_ready;
g_eth_last_mrcmdx = 0u;
g_eth_last_mrcmdx1 = 0u;
g_eth_last_mrrl = 0u;
g_eth_last_mrrh = 0u;
g_eth_last_rx_fail_stage = 2u;
g_eth_probe_attempted += 1u;
g_eth_probe_head0 = ReceiveData[0];
g_eth_probe_head1 = ReceiveData[1];
g_eth_probe_head2 = ReceiveData[2];
g_eth_probe_head3 = ReceiveData[3];
g_eth_probe_rx_status = ReceiveData[1];
for (i = 0u; i < 32u; ++i)
{
g_eth_probe_dump[i] = 0u;
}
g_eth_probe_rx_len = (uint32_t)rx_len;
g_eth_rx_fallback_reject_count += 1u;
s_rxrdy_miss_log_count += 1u;
if ((s_rxrdy_miss_log_count & 0xFFu) == 1u)
{
debug_log_printf("[ETH] rxhdr-bad #%lu nsr=0x%02X rr=0x%02X mrx=0x%02X mrx1=0x%02X mrr=0x%02X%02X h=%02X %02X %02X %02X\r\n",
(unsigned long)s_rxrdy_miss_log_count,
(unsigned int)nsr,
(unsigned int)rx_ready,
(unsigned int)g_eth_last_mrcmdx,
(unsigned int)g_eth_last_mrcmdx1,
(unsigned int)g_eth_last_mrrh,
(unsigned int)g_eth_last_mrrl,
(unsigned int)ReceiveData[0],
(unsigned int)ReceiveData[1],
(unsigned int)ReceiveData[2],
(unsigned int)ReceiveData[3]);
}
return 0;
}
g_eth_rx_gate_ok_count += 1u;
g_eth_rx_fallback_ok_count += 1u;
if(rx_len <= CH390_PKT_MAX)
{
ch390_read_mem(buff, rx_len);
}
if ((*rx_status & 0x3f) || (rx_len > CH390_PKT_MAX))
else
{
g_eth_last_rx_fail_stage = 3u;
}
if ((rx_len > CH390_PKT_MAX))
{
g_eth_last_rx_fail_stage = 4u;
return 0;
}
g_eth_last_rx_fail_stage = 5u;
return rx_len;
}
@@ -81,6 +181,13 @@ void ch390_send_packet(uint8_t *buff, uint16_t length)
ch390_write_reg(CH390_TXPLH, (length >> 8) & 0xff);
// Issue transmit request
ch390_send_request();
g_eth_last_tcr_after = (uint32_t)ch390_read_reg(CH390_TCR);
g_eth_last_nsr_after = (uint32_t)ch390_read_reg(CH390_NSR);
g_eth_last_tsra = (uint32_t)ch390_read_reg(CH390_TSRA);
g_eth_last_tsrb = (uint32_t)ch390_read_reg(CH390_TSRB);
g_eth_last_txpll_rb = (uint32_t)ch390_read_reg(CH390_TXPLL);
g_eth_last_txplh_rb = (uint32_t)ch390_read_reg(CH390_TXPLH);
}
/**
@@ -101,7 +208,7 @@ void ch390_send_request()
*/
void ch390_drop_packet(uint16_t len)
{
uint16_t mdr = ch390_read_reg(CH390_MRRL) | (ch390_read_reg(CH390_MRRH) << 8);
uint16_t mdr = (uint16_t)ch390_read_mrrl() | ((uint16_t)ch390_read_mrrh() << 8);
#ifdef CH390_INTERFACE_16_BIT
mdr = mdr + (len + 1) / 2 * 2;
#else
@@ -191,20 +298,23 @@ 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};
uint8_t multicase_addr[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
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_INTCR, (uint8_t)(INCR_TYPE_OD | INCR_POL_L));
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);
ch390_write_reg(CH390_BCASTCR, 0x00);
ch390_write_reg(CH390_MAR + 7, 0x80);
// Enable all interrupt and PAR
ch390_write_reg(CH390_IMR, IMR_ALL);
// Keep pointer auto-return enabled to stay aligned with the reference behavior.
ch390_write_reg(CH390_IMR, (uint8_t)(IMR_PAR | IMR_PRI | IMR_LNKCHGI | IMR_ROOI | IMR_ROI));
// Enable RX
ch390_write_reg(CH390_RCR, RCR_DIS_CRC | RCR_RXEN);
}
@@ -613,3 +723,44 @@ uint8_t ch390_get_int_status()
ch390_write_reg(CH390_ISR, int_status);
return int_status;
}
uint8_t ch390_runtime_poll(struct ch390_runtime_status *status)
{
uint8_t int_status = ch390_read_reg(CH390_ISR);
if (status != 0)
{
status->int_status = int_status;
status->nsr = ch390_read_reg(CH390_NSR);
status->bcastcr = ch390_read_reg(CH390_BCASTCR);
status->mar7 = ch390_read_reg(CH390_MAR + 7u);
status->mrcmdx = 0u;
status->mrcmdx1 = 0u;
status->mrrl = 0u;
status->mrrh = 0u;
status->link_up = ((status->nsr & NSR_LINKST) != 0u) ? 1u : 0u;
}
ch390_write_reg(CH390_ISR, int_status);
return int_status;
}
int ch390_runtime_link_up_from_status(const struct ch390_runtime_status *status)
{
if (status == 0)
{
return 0;
}
return (status->link_up != 0u) ? 1 : 0;
}
uint32_t ch390_runtime_receive_packet(uint8_t *buff, uint8_t *rx_status)
{
return ch390_receive_packet(buff, rx_status);
}
void ch390_runtime_send_packet(uint8_t *buff, uint16_t length)
{
ch390_send_packet(buff, length);
}
+54
View File
@@ -359,6 +359,19 @@ enum ch390_phy_mode
#define CH390_PKT_MAX 1536 /* Received packet max size */
#define CH390_PKT_MIN 64
struct ch390_runtime_status
{
uint8_t int_status;
uint8_t nsr;
uint8_t bcastcr;
uint8_t mar7;
uint8_t mrcmdx;
uint8_t mrcmdx1;
uint8_t mrrl;
uint8_t mrrh;
uint8_t link_up;
};
/********************************************************************
* Functions
*/
@@ -620,4 +633,45 @@ void ch390_int_pin_config(uint8_t type, uint8_t pol);
*/
uint8_t ch390_get_int_status(void);
/**
* @name ch390_runtime_poll
* @brief Poll runtime state, sample diagnostic registers, and clear ISR flags.
* @param status - Output runtime status snapshot
* @return Interrupt status snapshot
*/
uint8_t ch390_runtime_poll(struct ch390_runtime_status *status);
/**
* @name ch390_runtime_link_up_from_status
* @brief Get link state from a runtime status snapshot
* @param status - Runtime status snapshot
* @return 0: Link down 1: Link up
*/
int ch390_runtime_link_up_from_status(const struct ch390_runtime_status *status);
/**
* @name ch390_probe_rx_header
* @brief Diagnostic helper: read 4-byte RX header directly from RX SRAM.
* Caller must restore MRR if a non-destructive probe is required.
* @param head - Output buffer with at least 4 bytes.
*/
void ch390_probe_rx_header(uint8_t *head);
/**
* @name ch390_runtime_receive_packet
* @brief Runtime RX entry point for packet receive
* @param buff - Size equal to CH390_PKT_MAX
* @param rx_status - Output abnormal status while receiving packet
* @return Packet length
*/
uint32_t ch390_runtime_receive_packet(uint8_t *buff, uint8_t *rx_status);
/**
* @name ch390_runtime_send_packet
* @brief Runtime TX entry point for packet transmit
* @param buff - Data to be sent
* @param length - Less than 3k bytes.
*/
void ch390_runtime_send_packet(uint8_t *buff, uint16_t length);
#endif /* __CH390_H */
+121 -35
View File
@@ -12,6 +12,7 @@
* Modified for STM32F103 HAL Library with FreeRTOS support.
******************************************************************************/
#include "stm32f1xx_hal.h"
#include "main.h"
#include "CH390.h"
#include "CH390_Interface.h"
@@ -51,6 +52,15 @@ extern SPI_HandleTypeDef hspi1;
/* Timeout for SPI operations (ms) */
#define SPI_TIMEOUT 100
#define CH390_SPI_CHUNK_SIZE 64u
#ifdef USE_FREERTOS
#define CH390_SPI_ATOMIC_ENTER() taskENTER_CRITICAL()
#define CH390_SPI_ATOMIC_EXIT() taskEXIT_CRITICAL()
#else
#define CH390_SPI_ATOMIC_ENTER() ((void)0)
#define CH390_SPI_ATOMIC_EXIT() ((void)0)
#endif
/*----------------------------------------------------------------------------
* Low-level GPIO operations
@@ -64,6 +74,7 @@ static inline void ch390_cs(uint8_t state)
{
HAL_GPIO_WritePin(CH390_CS_PORT, CH390_CS_PIN,
state ? GPIO_PIN_SET : GPIO_PIN_RESET);
ch390_delay_us(2);
}
/**
@@ -88,10 +99,43 @@ static inline void ch390_rst(uint8_t state)
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);
if (HAL_SPI_TransmitReceive(&hspi1, &byte, &rx_data, 1, SPI_TIMEOUT) != HAL_OK)
{
return 0;
}
return rx_data;
}
static int ch390_spi_read_bytes(uint8_t *data, uint16_t length)
{
static const uint8_t dummy_tx[CH390_SPI_CHUNK_SIZE] = {0};
while (length > 0u)
{
uint16_t chunk = (length > CH390_SPI_CHUNK_SIZE) ? CH390_SPI_CHUNK_SIZE : length;
if (HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)dummy_tx, data, chunk, SPI_TIMEOUT) != HAL_OK)
{
return -1;
}
data += chunk;
length = (uint16_t)(length - chunk);
}
return 0;
}
static void ch390_spi_apply_mode(uint32_t polarity, uint32_t phase)
{
hspi1.Init.CLKPolarity = polarity;
hspi1.Init.CLKPhase = phase;
hspi1.Init.NSS = SPI_NSS_SOFT;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief Read a dummy byte (send 0x00)
* @return Received byte
@@ -155,21 +199,8 @@ void ch390_interrupt_init(void)
*/
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();
}
/* Reference CH390 SPI path uses mode 3. */
ch390_spi_apply_mode(SPI_POLARITY_HIGH, SPI_PHASE_2EDGE);
}
/**
@@ -220,10 +251,11 @@ void ch390_delay_us(uint32_t time)
*/
void ch390_hardware_reset(void)
{
ch390_delay_us(10000); /* Short delay before reset */
ch390_rst(0); /* Assert reset (low) */
ch390_delay_us(100); /* Hold reset for 100us (min 10us required) */
ch390_delay_us(3000); /* Hold reset for 3ms to satisfy datasheet minimum */
ch390_rst(1); /* Release reset (high) */
ch390_delay_us(10000); /* Wait 10ms for CH390 to initialize */
ch390_delay_us(50000); /* Wait 50ms for CH390 to initialize reliably */
}
/*----------------------------------------------------------------------------
@@ -238,15 +270,60 @@ void ch390_hardware_reset(void)
uint8_t ch390_read_reg(uint8_t reg)
{
uint8_t value;
CH390_SPI_ATOMIC_ENTER();
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 */
CH390_SPI_ATOMIC_EXIT();
return value;
}
static uint8_t ch390_read_rx_reg(uint8_t reg)
{
uint8_t tx_buf[3];
uint8_t rx_buf[3];
tx_buf[0] = OPC_MEM_DMY_R;
tx_buf[1] = reg;
tx_buf[2] = 0x00u;
CH390_SPI_ATOMIC_ENTER();
ch390_cs(0);
if (HAL_SPI_TransmitReceive(&hspi1, tx_buf, rx_buf, 3, SPI_TIMEOUT) != HAL_OK)
{
ch390_cs(1);
CH390_SPI_ATOMIC_EXIT();
return 0u;
}
ch390_cs(1);
CH390_SPI_ATOMIC_EXIT();
return rx_buf[2];
}
uint8_t ch390_read_mrcmdx(void)
{
return ch390_read_rx_reg(CH390_MRCMDX);
}
uint8_t ch390_read_mrcmdx1(void)
{
return ch390_read_rx_reg(CH390_MRCMDX1);
}
uint8_t ch390_read_mrrl(void)
{
return ch390_read_rx_reg(CH390_MRRL);
}
uint8_t ch390_read_mrrh(void)
{
return ch390_read_rx_reg(CH390_MRRH);
}
/**
* @brief Write a CH390 register
* @param reg Register address
@@ -254,10 +331,12 @@ uint8_t ch390_read_reg(uint8_t reg)
*/
void ch390_write_reg(uint8_t reg, uint8_t value)
{
CH390_SPI_ATOMIC_ENTER();
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 */
CH390_SPI_ATOMIC_EXIT();
}
/**
@@ -267,18 +346,19 @@ void ch390_write_reg(uint8_t reg, uint8_t value)
*/
void ch390_read_mem(uint8_t *data, int length)
{
int i;
if ((data == NULL) || (length <= 0))
{
return;
}
CH390_SPI_ATOMIC_ENTER();
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();
}
(void)ch390_spi_read_bytes(data, (uint16_t)length);
ch390_cs(1); /* CS high - deselect */
CH390_SPI_ATOMIC_EXIT();
}
/**
@@ -309,17 +389,23 @@ void ch390_read_mem_dma(uint8_t *data, int length)
void ch390_write_mem(uint8_t *data, int length)
{
int i;
if ((data == NULL) || (length <= 0))
{
return;
}
CH390_SPI_ATOMIC_ENTER();
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++)
for (i = 0; i < length; ++i)
{
ch390_spi_exchange_byte(data[i]);
(void)ch390_spi_exchange_byte(data[i]);
}
ch390_cs(1); /* CS high - deselect */
CH390_SPI_ATOMIC_EXIT();
}
/**
+28
View File
@@ -28,6 +28,34 @@ void ch390_hardware_reset(void);
*/
uint8_t ch390_read_reg(uint8_t reg);
/**
* @name ch390_read_mrcmdx
* @brief Read MRCMDX via memory-dummy-read opcode
* @return Register value
*/
uint8_t ch390_read_mrcmdx(void);
/**
* @name ch390_read_mrcmdx1
* @brief Read MRCMDX1 via memory-dummy-read opcode
* @return Register value
*/
uint8_t ch390_read_mrcmdx1(void);
/**
* @name ch390_read_mrrl
* @brief Read MRRL via memory-dummy-read opcode
* @return Register value
*/
uint8_t ch390_read_mrrl(void);
/**
* @name ch390_read_mrrh
* @brief Read MRRH via memory-dummy-read opcode
* @return Register value
*/
uint8_t ch390_read_mrrh(void);
/**
* @name ch390_write_reg
* @brief Write register
+3 -3
View File
@@ -128,7 +128,7 @@ u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
*/
err_t sys_mutex_new(sys_mutex_t *mutex)
{
*mutex = xSemaphoreCreateMutex();
*mutex = xSemaphoreCreateRecursiveMutex();
if (*mutex == NULL)
{
SYS_STATS_INC(mutex.err);
@@ -159,7 +159,7 @@ void sys_mutex_free(sys_mutex_t *mutex)
*/
void sys_mutex_lock(sys_mutex_t *mutex)
{
xSemaphoreTake(*mutex, portMAX_DELAY);
xSemaphoreTakeRecursive(*mutex, portMAX_DELAY);
}
/**
@@ -168,7 +168,7 @@ void sys_mutex_lock(sys_mutex_t *mutex)
*/
void sys_mutex_unlock(sys_mutex_t *mutex)
{
xSemaphoreGive(*mutex);
xSemaphoreGiveRecursive(*mutex);
}
/*---------------------------------------------------------------------------
+14
View File
@@ -55,6 +55,7 @@
#include "lwip/acd.h"
#include "lwip/prot/iana.h"
#include "netif/ethernet.h"
#include "../../../../../App/app_runtime.h"
#include <string.h>
@@ -694,6 +695,19 @@ etharp_input(struct pbuf *p, struct netif *netif)
from_us = (u8_t)ip4_addr_eq(&sipaddr, netif_ip4_addr(netif));
}
g_eth_lwip_arp_seen_count += 1u;
g_eth_lwip_arp_opcode = (uint32_t)lwip_htons(hdr->opcode);
g_eth_lwip_arp_for_us = (uint32_t)for_us;
g_eth_lwip_arp_from_us = (uint32_t)from_us;
g_eth_lwip_arp_sip[0] = ip4_addr1(&sipaddr);
g_eth_lwip_arp_sip[1] = ip4_addr2(&sipaddr);
g_eth_lwip_arp_sip[2] = ip4_addr3(&sipaddr);
g_eth_lwip_arp_sip[3] = ip4_addr4(&sipaddr);
g_eth_lwip_arp_dip[0] = ip4_addr1(&dipaddr);
g_eth_lwip_arp_dip[1] = ip4_addr2(&dipaddr);
g_eth_lwip_arp_dip[2] = ip4_addr3(&dipaddr);
g_eth_lwip_arp_dip[3] = ip4_addr4(&dipaddr);
/* ARP message directed to us?
-> add IP address in ARP cache; assume requester wants to talk to us,
can result in directly sending the queued packets for this host.
+18 -2
View File
@@ -11,6 +11,23 @@
#include <stdlib.h>
#include "lwip/errno.h"
#ifdef __cplusplus
extern "C" {
#endif
void lwip_platform_assert(const char *msg, const char *file, int line);
#ifdef __cplusplus
}
#endif
/*
* FreeRTOSConfig.h injects a global sys_now() macro. App sources that include
* FreeRTOS before lwIP would otherwise corrupt this declaration and the type
* aliases below. Remove the macro so lwIP uses the real port function.
*/
#ifdef sys_now
#undef sys_now
#endif
/* Use standard integer types from stdint.h */
#define LWIP_NO_STDINT_H 0
@@ -68,8 +85,7 @@ typedef uintptr_t mem_ptr_t;
/* Platform specific assertion handling */
#ifndef LWIP_PLATFORM_ASSERT
#define LWIP_PLATFORM_ASSERT(x) do { \
printf("Assertion \"%s\" failed at line %d in %s\n", x, __LINE__, __FILE__); \
while(1); \
lwip_platform_assert((x), __FILE__, __LINE__); \
} while(0)
#endif
+19 -12
View File
@@ -25,7 +25,7 @@
/* Enable netconn API (primary), disable socket API to save RAM */
#define LWIP_SOCKET 0
#define LWIP_NETCONN 1
#define LWIP_NETIF_API 0
#define LWIP_NETIF_API 1
/* Core locking: allows netconn_write/recv from any task without going through mbox */
#define LWIP_TCPIP_CORE_LOCKING 1
@@ -51,11 +51,11 @@
/* Heap size for dynamic memory allocation.
* With netconn: larger heap needed for netbuf allocation and connection management.
* 8KB provides headroom for 4 concurrent TCP connections. */
#define MEM_SIZE (8 * 1024)
#define MEM_SIZE (6 * 1024)
/* Number of pbufs in pool.
* 10 pools for 4 concurrent connections with some headroom. */
#define PBUF_POOL_SIZE 10
#define PBUF_POOL_SIZE 8
/* Size of each pbuf in pool (must hold one Ethernet frame) */
#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN)
@@ -77,20 +77,20 @@
/* Number of simultaneously queued TCP segments
* Increased for 4 concurrent connections */
#define MEMP_NUM_TCP_SEG 24
#define MEMP_NUM_TCP_SEG 16
/* Number of simultaneously active timeouts */
#define MEMP_NUM_SYS_TIMEOUT 8
/* Number of netbufs (for netconn API, one per pending recv) */
#define MEMP_NUM_NETBUF 8
#define MEMP_NUM_NETBUF 4
/* Number of netconns: 2 listeners + 2 accepted + 2 clients + 2 margin = 8 */
#define MEMP_NUM_NETCONN 8
#define MEMP_NUM_NETCONN 6
/* TCPIP message queue size (must be >= max simultaneous API calls) */
#define MEMP_NUM_TCPIP_MSG_API 8
#define MEMP_NUM_TCPIP_MSG_INPKT 8
#define MEMP_NUM_TCPIP_MSG_API 6
#define MEMP_NUM_TCPIP_MSG_INPKT 6
/*-----------------------------------------------------------------------------
* IP Configuration
@@ -149,13 +149,20 @@
#define TCP_MSS 536 /* Conservative value for compatibility */
/* TCP sender buffer space - increased for bridge throughput */
#define TCP_SND_BUF (8 * TCP_MSS)
#define TCP_SND_BUF (4 * TCP_MSS)
/* TCP sender buffer space (pbufs) */
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
/*
* Temporary phase-1 exception: current TCP queue sizing trips lwIP's compile-time
* sanity guard on this memory-constrained target. Keep the bypass in project
* configuration instead of patching lwIP core source logic.
*/
#define LWIP_DISABLE_TCP_SANITY_CHECKS 1
/* TCP receive window - increased for bridge throughput */
#define TCP_WND (8 * TCP_MSS)
#define TCP_WND (4 * TCP_MSS)
/* TCP writable space threshold */
#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1)
@@ -274,10 +281,10 @@
#define DEFAULT_THREAD_PRIO (configMAX_PRIORITIES - 3)
/* Mailbox sizes */
#define TCPIP_MBOX_SIZE 8
#define TCPIP_MBOX_SIZE 6
#define DEFAULT_RAW_RECVMBOX_SIZE 4
#define DEFAULT_UDP_RECVMBOX_SIZE 4
#define DEFAULT_TCP_RECVMBOX_SIZE 8
#define DEFAULT_TCP_RECVMBOX_SIZE 4
#define DEFAULT_ACCEPTMBOX_SIZE 4
/* Thread name length */
+30
View File
@@ -13,6 +13,36 @@
#include "lwip/arch.h"
#include <stdlib.h>
/*
* FreeRTOSConfig.h currently injects lwIP-related helper macros globally.
* Those overrides break the normal lwIP sys.h/sys_arch contract by replacing
* function declarations such as sys_now() with object-like macros.
* Undefine them here so lwIP uses the port's real sys_arch implementation.
*/
#ifdef sys_now
#undef sys_now
#endif
#ifdef sys_arch_protect
#undef sys_arch_protect
#endif
#ifdef sys_arch_unprotect
#undef sys_arch_unprotect
#endif
#ifdef SYS_ARCH_DECL_PROTECT
#undef SYS_ARCH_DECL_PROTECT
#endif
#ifdef SYS_ARCH_PROTECT
#undef SYS_ARCH_PROTECT
#endif
#ifdef SYS_ARCH_UNPROTECT
#undef SYS_ARCH_UNPROTECT
#endif
#ifdef __cplusplus
extern "C" {
#endif
+5 -1
View File
@@ -2,6 +2,8 @@
#define _ETHERNETIF_H_
#include "lwip/netif.h"
#include "lwip/err.h"
#include "lwip/ip4_addr.h"
extern struct netif ch390_netif;
@@ -18,9 +20,11 @@ struct ethernetif {
uint8_t rx_status;
};
void init_lwip_netif(const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw);
err_t ethernetif_init(struct netif *netif);
void ethernetif_input(struct netif *netif);
void lwip_netif_init(const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw);
void ethernetif_check_link(void);
void ethernetif_poll(void);
void print_netif(struct netif *netif);
+130
View File
@@ -0,0 +1,130 @@
/**
* @file ethernet.c
* @brief Minimal lwIP Ethernet helper implementation.
*/
#include "lwip/opt.h"
#if LWIP_ARP || LWIP_ETHERNET
#include "netif/ethernet.h"
#include "lwip/def.h"
#include "lwip/ip.h"
#include "lwip/pbuf.h"
#include "lwip/stats.h"
#include "lwip/prot/ethernet.h"
#include "../../../../App/app_runtime.h"
#include <string.h>
#if LWIP_IPV4 && LWIP_ARP
#include "lwip/etharp.h"
#endif
#if LWIP_IPV6
#include "lwip/ip6.h"
#endif
const struct eth_addr ethbroadcast = ETH_ADDR(0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
const struct eth_addr ethzero = ETH_ADDR(0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
err_t ethernet_output(struct netif *netif,
struct pbuf *p,
const struct eth_addr *src,
const struct eth_addr *dst,
u16_t eth_type)
{
struct pbuf *q;
struct eth_hdr *ethhdr;
LWIP_ASSERT("netif != NULL", netif != NULL);
LWIP_ASSERT("p != NULL", p != NULL);
LWIP_ASSERT("src != NULL", src != NULL);
LWIP_ASSERT("dst != NULL", dst != NULL);
q = pbuf_alloc(PBUF_RAW_TX, SIZEOF_ETH_HDR, PBUF_RAM);
if (q == NULL) {
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
return ERR_MEM;
}
pbuf_chain(q, p);
ethhdr = (struct eth_hdr *)q->payload;
SMEMCPY(&ethhdr->dest, dst, sizeof(struct eth_addr));
SMEMCPY(&ethhdr->src, src, sizeof(struct eth_addr));
ethhdr->type = lwip_htons(eth_type);
return netif->linkoutput(netif, q);
}
err_t ethernet_input(struct pbuf *p, struct netif *netif)
{
struct eth_hdr *ethhdr;
u16_t type;
LWIP_ASSERT("p != NULL", p != NULL);
LWIP_ASSERT("netif != NULL", netif != NULL);
if (p->len < SIZEOF_ETH_HDR) {
LINK_STATS_INC(link.lenerr);
LINK_STATS_INC(link.drop);
pbuf_free(p);
return ERR_OK;
}
ethhdr = (struct eth_hdr *)p->payload;
type = lwip_htons(ethhdr->type);
g_eth_lwip_eth_seen_count += 1u;
g_eth_lwip_eth_last_type = (uint32_t)type;
g_eth_lwip_eth_last_len = (uint32_t)p->len;
switch (type) {
#if LWIP_IPV4 && LWIP_ARP
case ETHTYPE_ARP:
g_eth_lwip_eth_arp_case_count += 1u;
if (netif->flags & NETIF_FLAG_ETHARP) {
if (pbuf_remove_header(p, SIZEOF_ETH_HDR)) {
pbuf_free(p);
return ERR_OK;
}
etharp_input(p, netif);
} else {
pbuf_free(p);
}
return ERR_OK;
case ETHTYPE_IP:
if (netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
if (pbuf_remove_header(p, SIZEOF_ETH_HDR)) {
pbuf_free(p);
return ERR_OK;
}
return ip_input(p, netif);
}
break;
#endif
#if LWIP_IPV6
case ETHTYPE_IPV6:
if (netif->flags & NETIF_FLAG_ETHERNET) {
if (pbuf_remove_header(p, SIZEOF_ETH_HDR)) {
pbuf_free(p);
return ERR_OK;
}
return ip6_input(p, netif);
}
break;
#endif
default:
break;
}
pbuf_free(p);
return ERR_OK;
}
#endif /* LWIP_ARP || LWIP_ETHERNET */
+355 -106
View File
@@ -10,7 +10,9 @@
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/etharp.h"
#include "lwip/netifapi.h"
#include "lwip/tcpip.h"
#include "lwip/ip4_addr.h"
#include "netif/ethernet.h"
#include "ethernetif.h"
@@ -21,6 +23,10 @@
#include "task.h"
#include "semphr.h"
#include "debug_log.h"
#include "config.h"
#include "app_runtime.h"
#include <string.h>
/* Interface name */
@@ -32,11 +38,57 @@ struct netif ch390_netif;
/* Mutex for SPI access protection */
static SemaphoreHandle_t spi_mutex = NULL;
static uint8_t s_rx_buffer[CH390_PKT_MAX];
static uint8_t s_tx_buffer[CH390_PKT_MAX];
static uint8_t s_garp_sent = 0u;
static void eth_diag_store_local_netif(const struct netif *netif)
{
uint16_t i;
const ip4_addr_t *ipaddr = netif_ip4_addr(netif);
const uint8_t *ipbytes = (const uint8_t *)&ipaddr->addr;
for (i = 0u; i < 6u; ++i)
{
g_eth_local_mac[i] = netif->hwaddr[i];
}
g_eth_local_ip[0] = ipbytes[0];
g_eth_local_ip[1] = ipbytes[1];
g_eth_local_ip[2] = ipbytes[2];
g_eth_local_ip[3] = ipbytes[3];
}
static void eth_diag_store_arp_fields(uint8_t is_tx, const uint8_t *arp)
{
uint16_t i;
volatile uint32_t *op_ptr = is_tx ? &g_eth_arp_tx_op : &g_eth_arp_rx_op;
volatile uint32_t *count_ptr = is_tx ? &g_eth_arp_tx_count : &g_eth_arp_rx_count;
volatile uint8_t *sha = is_tx ? g_eth_arp_tx_sha : g_eth_arp_rx_sha;
volatile uint8_t *spa = is_tx ? g_eth_arp_tx_spa : g_eth_arp_rx_spa;
volatile uint8_t *tha = is_tx ? g_eth_arp_tx_tha : g_eth_arp_rx_tha;
volatile uint8_t *tpa = is_tx ? g_eth_arp_tx_tpa : g_eth_arp_rx_tpa;
*op_ptr = (uint32_t)(((uint16_t)arp[6] << 8) | arp[7]);
*count_ptr += 1u;
for (i = 0u; i < 6u; ++i)
{
sha[i] = arp[8u + i];
tha[i] = arp[18u + i];
}
for (i = 0u; i < 4u; ++i)
{
spa[i] = arp[14u + i];
tpa[i] = arp[24u + i];
}
}
/* Forward declarations */
static void low_level_init(struct netif *netif);
static err_t low_level_output(struct netif *netif, struct pbuf *p);
static struct pbuf *low_level_input(struct netif *netif);
static void ethernetif_update_link(uint8_t link_status);
/*---------------------------------------------------------------------------
* Low Level Hardware Functions
@@ -49,6 +101,7 @@ static struct pbuf *low_level_input(struct netif *netif);
static void low_level_init(struct netif *netif)
{
struct ethernetif *ethernetif = netif->state;
const device_config_t *cfg = config_get();
/* Create SPI mutex */
if (spi_mutex == NULL)
@@ -65,6 +118,16 @@ static void low_level_init(struct netif *netif)
/* Configure CH390 with default settings */
ch390_default_config();
debug_log_printf("[ETH] cfg imr=0x%02X intcr=0x%02X rcr=0x%02X\r\n",
ch390_read_reg(CH390_IMR),
ch390_read_reg(CH390_INTCR),
ch390_read_reg(CH390_RCR));
debug_log_printf("[ETH] bc bcastcr=0x%02X mar7=0x%02X\r\n",
ch390_read_reg(CH390_BCASTCR),
ch390_read_reg(CH390_MAR + 7));
/* Apply configured MAC address to CH390 before reading it back into lwIP */
ch390_set_mac_address((uint8_t *)cfg->net.mac);
/* Set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;
@@ -76,7 +139,7 @@ static void low_level_init(struct netif *netif)
netif->mtu = 1500;
/* Device capabilities */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET;
/* Initialize state */
ethernetif->rx_len = 0;
@@ -95,6 +158,11 @@ static void low_level_init(struct netif *netif)
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
struct pbuf *q;
uint16_t offset;
uint16_t copy_len;
uint16_t i;
uint16_t tx_len;
(void)netif;
/* Take SPI mutex */
if (spi_mutex != NULL)
@@ -106,24 +174,52 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p)
pbuf_remove_header(p, ETH_PAD_SIZE);
#endif
/* Copy data to CH390 TX buffer */
offset = 0u;
/* Copy data to contiguous staging buffer */
for (q = p; q != NULL; q = q->next)
{
ch390_write_mem(q->payload, q->len);
if ((uint32_t)offset + (uint32_t)q->len > (uint32_t)sizeof(s_tx_buffer))
{
if (spi_mutex != NULL)
{
xSemaphoreGive(spi_mutex);
}
#if ETH_PAD_SIZE
pbuf_add_header(p, ETH_PAD_SIZE);
#endif
LINK_STATS_INC(link.drop);
return ERR_BUF;
}
MEMCPY(&s_tx_buffer[offset], q->payload, q->len);
offset = (uint16_t)(offset + q->len);
}
/* Wait until last transmit complete */
while (ch390_read_reg(CH390_TCR) & TCR_TXREQ)
tx_len = p->tot_len;
eth_diag_store_local_netif(netif);
g_eth_last_tx_len = tx_len;
copy_len = (tx_len < (uint16_t)sizeof(g_eth_last_tx_head)) ? tx_len : (uint16_t)sizeof(g_eth_last_tx_head);
for (i = 0u; i < (uint16_t)sizeof(g_eth_last_tx_head); ++i)
{
taskYIELD();
g_eth_last_tx_head[i] = 0u;
}
/* Set packet length */
ch390_write_reg(CH390_TXPLL, p->tot_len & 0xFF);
ch390_write_reg(CH390_TXPLH, (p->tot_len >> 8) & 0xFF);
/* Issue transmit request */
ch390_send_request();
for (i = 0u; i < copy_len; ++i)
{
g_eth_last_tx_head[i] = s_tx_buffer[i];
}
g_eth_tx_probe_count += 1u;
if ((tx_len >= 42u) && (s_tx_buffer[12] == 0x08u) && (s_tx_buffer[13] == 0x06u))
{
eth_diag_store_arp_fields(1u, &s_tx_buffer[14]);
}
ch390_runtime_send_packet(s_tx_buffer, tx_len);
g_eth_tx_count += 1u;
/* Release SPI mutex */
if (spi_mutex != NULL)
@@ -150,9 +246,10 @@ static struct pbuf *low_level_input(struct netif *netif)
struct ethernetif *ethernetif = netif->state;
struct pbuf *p = NULL;
struct pbuf *q;
uint16_t offset;
uint16_t len;
uint8_t rx_ready;
uint8_t rx_header[4];
uint32_t rx_len;
uint8_t rx_status;
/* Take SPI mutex */
if (spi_mutex != NULL)
@@ -160,48 +257,21 @@ static struct pbuf *low_level_input(struct netif *netif)
xSemaphoreTake(spi_mutex, portMAX_DELAY);
}
/* Check if packet is ready */
ch390_read_reg(CH390_MRCMDX); /* Dummy read */
rx_ready = ch390_read_reg(CH390_MRCMDX);
if (rx_ready & CH390_PKT_ERR)
rx_len = ch390_runtime_receive_packet(s_rx_buffer, &rx_status);
ethernetif->rx_status = rx_status;
ethernetif->rx_len = (uint16_t)rx_len;
if (rx_len == 0u)
{
/* RX error - reset RX FIFO */
ch390_write_reg(CH390_RCR, 0); /* 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_RXEN | RCR_DIS_CRC); /* RX Enable */
LINK_STATS_INC(link.drop);
ethernetif->rx_len = 0;
if (spi_mutex != NULL)
{
xSemaphoreGive(spi_mutex);
}
return NULL;
}
if (!(rx_ready & CH390_PKT_RDY))
{
/* No packet ready */
ethernetif->rx_len = 0;
if (spi_mutex != NULL)
{
xSemaphoreGive(spi_mutex);
}
return NULL;
}
/* Read RX header (status + length) */
ch390_read_mem(rx_header, 4);
ethernetif->rx_status = rx_header[1];
/* Length includes 4-byte CRC, subtract it */
ethernetif->rx_len = (rx_header[2] | (rx_header[3] << 8)) - 4;
len = ethernetif->rx_len;
len = (uint16_t)rx_len;
#if ETH_PAD_SIZE
len += ETH_PAD_SIZE;
#endif
@@ -211,31 +281,50 @@ static struct pbuf *low_level_input(struct netif *netif)
if (p != NULL)
{
offset = 0u;
#if ETH_PAD_SIZE
pbuf_remove_header(p, ETH_PAD_SIZE);
#endif
/* Read packet data into pbuf chain */
/* Copy packet data into pbuf chain */
for (q = p; q != NULL; q = q->next)
{
ch390_read_mem(q->payload, q->len);
MEMCPY(q->payload, &s_rx_buffer[offset], q->len);
offset = (uint16_t)(offset + q->len);
}
if ((ethernetif->rx_status & 0x3Fu) != 0u)
{
pbuf_free(p);
p = NULL;
LINK_STATS_INC(link.drop);
g_eth_rx_drop_count += 1u;
}
else
{
eth_diag_store_local_netif(netif);
if ((rx_len >= 42u) && (s_rx_buffer[12] == 0x08u) && (s_rx_buffer[13] == 0x06u))
{
eth_diag_store_arp_fields(0u, &s_rx_buffer[14]);
}
LINK_STATS_INC(link.recv);
g_eth_rx_count += 1u;
}
#if ETH_PAD_SIZE
pbuf_add_header(p, ETH_PAD_SIZE);
if (p != NULL)
{
pbuf_add_header(p, ETH_PAD_SIZE);
}
#endif
/* Skip CRC (4 bytes) */
ch390_drop_packet(4);
LINK_STATS_INC(link.recv);
}
else
{
/* No memory - drop packet */
ch390_drop_packet(ethernetif->rx_len + 4);
ch390_drop_packet(ethernetif->rx_len);
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
g_eth_rx_drop_count += 1u;
}
/* Release SPI mutex */
@@ -258,18 +347,36 @@ static struct pbuf *low_level_input(struct netif *netif)
void ethernetif_input(struct netif *netif)
{
struct pbuf *p;
err_t input_err;
uint16_t copy_len;
uint16_t i;
/* Get received packet */
p = low_level_input(netif);
if (p != NULL)
{
/* Pass to LwIP stack */
if (netif->input(p, netif) != ERR_OK)
g_eth_last_frame_len = p->tot_len;
copy_len = (p->tot_len < (uint16_t)sizeof(g_eth_last_frame_head)) ? (uint16_t)p->tot_len : (uint16_t)sizeof(g_eth_last_frame_head);
for (i = 0u; i < (uint16_t)sizeof(g_eth_last_frame_head); ++i)
{
g_eth_last_frame_head[i] = 0u;
}
pbuf_copy_partial(p, (void *)g_eth_last_frame_head, copy_len, 0u);
/* Pass to LwIP stack */
input_err = netif->input(p, netif);
g_eth_last_input_err = (int32_t)input_err;
if (input_err != ERR_OK)
{
g_eth_input_err_count += 1u;
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(p);
}
else
{
g_eth_input_ok_count += 1u;
}
}
}
@@ -325,44 +432,136 @@ err_t ethernetif_init(struct netif *netif)
*/
void lwip_netif_init(const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw)
{
err_t err;
g_netif_init_ok = 0;
g_netif_add_err = 0x7FFFFFFF;
g_netif_set_default_err = 0x7FFFFFFF;
g_netif_set_link_down_err = 0x7FFFFFFF;
g_netif_set_up_err = 0x7FFFFFFF;
g_netif_phase = 2u;
/* Add network interface */
netif_add(&ch390_netif, ipaddr, netmask, gw, NULL,
&ethernetif_init, &tcpip_input);
g_netif_phase = 3u;
err = netifapi_netif_add(&ch390_netif, ipaddr, netmask, gw, NULL,
&ethernetif_init, &tcpip_input);
g_netif_add_err = (int32_t)err;
if (err != ERR_OK) {
g_netif_init_ok = -1;
debug_log_printf("[ETH] netif-add fail err=%d\r\n", (int)err);
return;
}
g_netif_phase = 4u;
/* Set as default interface */
netif_set_default(&ch390_netif);
err = netifapi_netif_set_default(&ch390_netif);
g_netif_set_default_err = (int32_t)err;
if (err != ERR_OK) {
g_netif_init_ok = -1;
debug_log_printf("[ETH] set-default fail err=%d\r\n", (int)err);
return;
}
/* Set interface down initially */
netif_set_link_down(&ch390_netif);
netif_set_up(&ch390_netif);
err = netifapi_netif_set_link_down(&ch390_netif);
g_netif_set_link_down_err = (int32_t)err;
if (err != ERR_OK) {
g_netif_init_ok = -1;
debug_log_printf("[ETH] set-link-down fail err=%d\r\n", (int)err);
return;
}
err = netifapi_netif_set_up(&ch390_netif);
g_netif_set_up_err = (int32_t)err;
if (err != ERR_OK) {
g_netif_init_ok = -1;
debug_log_printf("[ETH] set-up fail err=%d\r\n", (int)err);
return;
}
g_netif_phase = 5u;
g_netif_phase = 6u;
g_netif_init_ok = 1;
}
void ethernetif_diag_ch390_init(void)
{
const device_config_t *cfg = config_get();
if (spi_mutex == NULL)
{
spi_mutex = xSemaphoreCreateMutex();
}
ch390_gpio_init();
ch390_spi_init();
ch390_hardware_reset();
ch390_default_config();
ch390_set_mac_address((uint8_t *)cfg->net.mac);
ch390_interrupt_init();
g_netif_init_ok = 1;
}
void ethernetif_diag_poll_status(void)
{
struct ch390_runtime_status runtime_status;
g_eth_poll_count += 1u;
if (spi_mutex != NULL)
{
xSemaphoreTake(spi_mutex, portMAX_DELAY);
}
(void)memset(&runtime_status, 0, sizeof(runtime_status));
ch390_runtime_poll(&runtime_status);
if (spi_mutex != NULL)
{
xSemaphoreGive(spi_mutex);
}
g_eth_last_isr = runtime_status.int_status;
g_eth_last_nsr = runtime_status.nsr;
g_eth_last_nsr_rxrdy = ((runtime_status.nsr & NSR_RXRDY) != 0u) ? 1u : 0u;
g_eth_last_mrcmdx = runtime_status.mrcmdx;
g_eth_last_mrcmdx1 = runtime_status.mrcmdx1;
g_eth_last_mrrl = runtime_status.mrrl;
g_eth_last_mrrh = runtime_status.mrrh;
g_eth_last_bcastcr = runtime_status.bcastcr;
g_eth_last_mar7 = runtime_status.mar7;
if ((runtime_status.int_status & ISR_PR) != 0u)
{
g_eth_isr_pr_count += 1u;
}
if (runtime_status.link_up != 0u)
{
if (g_eth_last_nsr != 0u)
{
g_eth_link_up_count += 0u;
}
}
}
/**
* @brief Check and handle CH390 link status
*/
void ethernetif_check_link(void)
static void ethernetif_update_link(uint8_t link_status)
{
uint8_t link_status;
/* Take SPI mutex */
if (spi_mutex != NULL)
{
xSemaphoreTake(spi_mutex, portMAX_DELAY);
}
link_status = ch390_get_link_status();
/* Release SPI mutex */
if (spi_mutex != NULL)
{
xSemaphoreGive(spi_mutex);
}
if (link_status)
{
if (!netif_is_link_up(&ch390_netif))
{
netif_set_link_up(&ch390_netif);
if ((s_garp_sent == 0u) && netif_is_up(&ch390_netif))
{
LOCK_TCPIP_CORE();
etharp_gratuitous(&ch390_netif);
UNLOCK_TCPIP_CORE();
s_garp_sent = 1u;
}
g_eth_link_up_count += 1u;
}
}
else
@@ -370,6 +569,8 @@ void ethernetif_check_link(void)
if (netif_is_link_up(&ch390_netif))
{
netif_set_link_down(&ch390_netif);
s_garp_sent = 0u;
g_eth_link_down_count += 1u;
}
}
}
@@ -379,7 +580,12 @@ void ethernetif_check_link(void)
*/
void ethernetif_poll(void)
{
uint8_t int_status;
struct ch390_runtime_status runtime_status;
struct pbuf *p;
err_t input_err;
uint16_t copy_len;
uint16_t i;
g_eth_poll_count += 1u;
/* Take SPI mutex */
if (spi_mutex != NULL)
@@ -387,11 +593,8 @@ void ethernetif_poll(void)
xSemaphoreTake(spi_mutex, portMAX_DELAY);
}
/* Read interrupt status */
int_status = ch390_read_reg(CH390_ISR);
/* Clear interrupt flags */
ch390_write_reg(CH390_ISR, int_status);
(void)memset(&runtime_status, 0, sizeof(runtime_status));
ch390_runtime_poll(&runtime_status);
/* Release SPI mutex */
if (spi_mutex != NULL)
@@ -399,35 +602,81 @@ void ethernetif_poll(void)
xSemaphoreGive(spi_mutex);
}
g_eth_last_isr = runtime_status.int_status;
g_eth_last_nsr = runtime_status.nsr;
g_eth_last_nsr_rxrdy = ((runtime_status.nsr & NSR_RXRDY) != 0u) ? 1u : 0u;
g_eth_last_mrcmdx = runtime_status.mrcmdx;
g_eth_last_mrcmdx1 = runtime_status.mrcmdx1;
g_eth_last_mrrl = runtime_status.mrrl;
g_eth_last_mrrh = runtime_status.mrrh;
g_eth_last_bcastcr = runtime_status.bcastcr;
g_eth_last_mar7 = runtime_status.mar7;
/* Handle link change */
if (int_status & ISR_LNKCHG)
if ((runtime_status.int_status & ISR_LNKCHG) != 0u)
{
ethernetif_check_link();
ethernetif_update_link((uint8_t)ch390_runtime_link_up_from_status(&runtime_status));
}
/* Handle RX overflow */
if (int_status & ISR_ROS)
if ((runtime_status.int_status & ISR_ROS) != 0u)
{
/* RX overflow - packets might be corrupted */
LINK_STATS_INC(link.err);
}
/* Process received packets */
if (int_status & ISR_PR)
if ((runtime_status.int_status & ISR_PR) != 0u)
{
/* Process all available packets */
while (1)
g_eth_isr_pr_count += 1u;
}
/* Always attempt to drain RX FIFO so packet handling does not depend only on ISR_PR timing. */
while (1)
{
p = low_level_input(&ch390_netif);
if (p == NULL)
{
struct pbuf *p = low_level_input(&ch390_netif);
if (p == NULL)
{
break;
}
if (ch390_netif.input(p, &ch390_netif) != ERR_OK)
{
pbuf_free(p);
}
break;
}
g_eth_last_frame_len = p->tot_len;
copy_len = (p->tot_len < (uint16_t)sizeof(g_eth_last_frame_head)) ? (uint16_t)p->tot_len : (uint16_t)sizeof(g_eth_last_frame_head);
for (i = 0u; i < (uint16_t)sizeof(g_eth_last_frame_head); ++i)
{
g_eth_last_frame_head[i] = 0u;
}
pbuf_copy_partial(p, (void *)g_eth_last_frame_head, copy_len, 0u);
input_err = ch390_netif.input(p, &ch390_netif);
g_eth_last_input_err = (int32_t)input_err;
if (input_err != ERR_OK)
{
g_eth_input_err_count += 1u;
pbuf_free(p);
}
else
{
g_eth_input_ok_count += 1u;
}
}
}
void ethernetif_check_link(void)
{
uint8_t link_status;
if (spi_mutex != NULL)
{
xSemaphoreTake(spi_mutex, portMAX_DELAY);
}
link_status = (uint8_t)ch390_get_link_status();
if (spi_mutex != NULL)
{
xSemaphoreGive(spi_mutex);
}
ethernetif_update_link(link_status);
}
+13
View File
@@ -6,8 +6,11 @@
#ifndef __ETHERNETIF_H__
#define __ETHERNETIF_H__
#include <stdint.h>
#include "lwip/netif.h"
#include "lwip/err.h"
#include "lwip/ip4_addr.h"
#ifdef __cplusplus
extern "C" {
@@ -44,6 +47,16 @@ void ethernetif_input(struct netif *netif);
*/
void lwip_netif_init(const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw);
/**
* @brief Initialize CH390 hardware without lwIP netif bring-up
*/
void ethernetif_diag_ch390_init(void);
/**
* @brief Poll CH390 status and update diagnostic globals without lwIP RX handoff
*/
void ethernetif_diag_poll_status(void);
/**
* @brief Check and handle CH390 interrupt status
* @note Call this from the LwIP task periodically or on interrupt
File diff suppressed because it is too large Load Diff
+520
View File
@@ -0,0 +1,520 @@
/*********************************************************************
* SEGGER Microcontroller GmbH *
* The Embedded Experts *
**********************************************************************
* *
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
* *
* www.segger.com Support: support@segger.com *
* *
**********************************************************************
* *
* SEGGER RTT * Real Time Transfer for embedded targets *
* *
**********************************************************************
* *
* All rights reserved. *
* *
* SEGGER strongly recommends to not make any changes *
* to or modify the source code of this software in order to stay *
* compatible with the RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* condition is met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this condition and the following disclaimer. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
* DAMAGE. *
* *
**********************************************************************
* *
* RTT version: 8.56a *
* *
**********************************************************************
---------------------------END-OF-HEADER------------------------------
File : SEGGER_RTT.h
Purpose : Implementation of SEGGER real-time transfer which allows
real-time communication on targets which support debugger
memory accesses while the CPU is running.
Revision: $Rev: 25842 $
----------------------------------------------------------------------
*/
#ifndef SEGGER_RTT_H
#define SEGGER_RTT_H
#include "SEGGER_RTT_Conf.h"
/*********************************************************************
*
* Defines, defaults
*
**********************************************************************
*/
#ifndef RTT_USE_ASM
//
// Some cores support out-of-order memory accesses (reordering of memory accesses in the core)
// For such cores, we need to define a memory barrier to guarantee the order of certain accesses to the RTT ring buffers.
// Needed for:
// Cortex-M7 (ARMv7-M)
// Cortex-M23 (ARM-v8M)
// Cortex-M33 (ARM-v8M)
// Cortex-A/R (ARM-v7A/R)
//
// We do not explicitly check for "Embedded Studio" as the compiler in use determines what we support.
// You can use an external toolchain like IAR inside ES. So there is no point in checking for "Embedded Studio"
//
#if (defined __CROSSWORKS_ARM) // Rowley Crossworks
#define _CC_HAS_RTT_ASM_SUPPORT 1
#if (defined __ARM_ARCH_7M__) // Cortex-M3
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
#define _CORE_HAS_RTT_ASM_SUPPORT 0
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#elif (defined(__ARM_ARCH_8_1M_MAIN__)) // Cortex-M85
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#else
#define _CORE_HAS_RTT_ASM_SUPPORT 0
#endif
#elif (defined __ARMCC_VERSION)
//
// ARM compiler
// ARM compiler V6.0 and later is clang based.
// Our ASM part is compatible to clang.
//
#if (__ARMCC_VERSION >= 6000000)
#define _CC_HAS_RTT_ASM_SUPPORT 1
#else
#define _CC_HAS_RTT_ASM_SUPPORT 0
#endif
#if (defined __ARM_ARCH_6M__) // Cortex-M0 / M1
#define _CORE_HAS_RTT_ASM_SUPPORT 0 // No ASM support for this architecture
#elif (defined __ARM_ARCH_7M__) // Cortex-M3
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
#define _CORE_HAS_RTT_ASM_SUPPORT 0
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#elif (defined __ARM_ARCH_8_1M_MAIN__) // Cortex-M85
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#elif \
((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) || \
((defined __ARM_ARCH_8A__) || (defined __ARM_ARCH_8R__))
//
// Cortex-A/R ARMv7-A/R & ARMv8-A/R
//
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#else
#define _CORE_HAS_RTT_ASM_SUPPORT 0
#endif
#elif ((defined __GNUC__) || (defined __clang__))
//
// GCC / Clang
//
#define _CC_HAS_RTT_ASM_SUPPORT 1
// ARM 7/9: __ARM_ARCH_5__ / __ARM_ARCH_5E__ / __ARM_ARCH_5T__ / __ARM_ARCH_5T__ / __ARM_ARCH_5TE__
#if (defined __ARM_ARCH_7M__) // Cortex-M3
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1 // Only Cortex-M7 needs a DMB but we cannot distinguish M4 and M7 here...
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
#define _CORE_HAS_RTT_ASM_SUPPORT 0
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#elif (defined __ARM_ARCH_8_1M_MAIN__) // Cortex-M85
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#elif \
(defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__) || \
(defined __ARM_ARCH_8A__) || (defined __ARM_ARCH_8R__)
//
// Cortex-A/R ARMv7-A/R & ARMv8-A/R
//
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
#else
#define _CORE_HAS_RTT_ASM_SUPPORT 0
#endif
#elif ((defined __IASMARM__) || (defined __ICCARM__))
//
// IAR assembler/compiler
//
#define _CC_HAS_RTT_ASM_SUPPORT 1
#if (__VER__ < 6300000)
#define VOLATILE
#else
#define VOLATILE volatile
#endif
#if (defined __ARM7M__) // Needed for old versions that do not know the define yet
#if (__CORE__ == __ARM7M__) // Cortex-M3
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#endif
#endif
#if (defined __ARM7EM__)
#if (__CORE__ == __ARM7EM__) // Cortex-M4/M7
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() asm VOLATILE ("DMB");
#endif
#endif
#if (defined __ARM8M_BASELINE__)
#if (__CORE__ == __ARM8M_BASELINE__) // Cortex-M23
#define _CORE_HAS_RTT_ASM_SUPPORT 0
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() asm VOLATILE ("DMB");
#endif
#endif
#if (defined __ARM8M_MAINLINE__)
#if (__CORE__ == __ARM8M_MAINLINE__) // Cortex-M33
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() asm VOLATILE ("DMB");
#endif
#endif
#if (defined __ARM8EM_MAINLINE__)
#if (__CORE__ == __ARM8EM_MAINLINE__) // Cortex-???
#define _CORE_HAS_RTT_ASM_SUPPORT 1
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() asm VOLATILE ("DMB");
#endif
#endif
#if\
((defined __ARM7A__) && (__CORE__ == __ARM7A__)) || \
((defined __ARM7R__) && (__CORE__ == __ARM7R__)) || \
((defined __ARM8A__) && (__CORE__ == __ARM8A__)) || \
((defined __ARM8R__) && (__CORE__ == __ARM8R__))
//
// Cortex-A/R ARMv7-A/R & ARMv8-A/R
//
#define _CORE_NEEDS_DMB 1
#define RTT__DMB() asm VOLATILE ("DMB");
#endif
#else
//
// Other compilers
//
#define _CC_HAS_RTT_ASM_SUPPORT 0
#define _CORE_HAS_RTT_ASM_SUPPORT 0
#endif
//
// If IDE and core support the ASM version, enable ASM version by default
//
#ifndef _CORE_HAS_RTT_ASM_SUPPORT
#define _CORE_HAS_RTT_ASM_SUPPORT 0 // Default for unknown cores
#endif
#if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT)
#define RTT_USE_ASM (1)
#else
#define RTT_USE_ASM (0)
#endif
#endif
#ifndef _CORE_NEEDS_DMB
#define _CORE_NEEDS_DMB 0
#endif
#ifndef RTT__DMB
#if _CORE_NEEDS_DMB
#error "Don't know how to place inline assembly for DMB"
#else
#define RTT__DMB()
#endif
#endif
#ifndef SEGGER_RTT_CPU_CACHE_LINE_SIZE
#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (0) // On most target systems where RTT is used, we do not have a CPU cache, therefore 0 is a good default here
#endif
#ifndef SEGGER_RTT_UNCACHED_OFF
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE
#error "SEGGER_RTT_UNCACHED_OFF must be defined when setting SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
#else
#define SEGGER_RTT_UNCACHED_OFF (0)
#endif
#endif
#if RTT_USE_ASM
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE
#error "RTT_USE_ASM is not available if SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
#endif
#endif
#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
/*********************************************************************
*
* Defines, fixed
*
**********************************************************************
*/
//
// Determine how much we must pad the control block to make it a multiple of a cache line in size
// Assuming: U8 = 1B
// U16 = 2B
// U32 = 4B
// U8/U16/U32* = 4B
//
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE // Avoid division by zero in case we do not have any cache
#define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (((NumBytes + SEGGER_RTT_CPU_CACHE_LINE_SIZE - 1) / SEGGER_RTT_CPU_CACHE_LINE_SIZE) * SEGGER_RTT_CPU_CACHE_LINE_SIZE)
#else
#define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (NumBytes)
#endif
#define SEGGER_RTT__CB_SIZE (16 + 4 + 4 + (SEGGER_RTT_MAX_NUM_UP_BUFFERS * 24) + (SEGGER_RTT_MAX_NUM_DOWN_BUFFERS * 24))
#define SEGGER_RTT__CB_PADDING (SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(SEGGER_RTT__CB_SIZE) - SEGGER_RTT__CB_SIZE)
/*********************************************************************
*
* Types
*
**********************************************************************
*/
//
// Description for a circular buffer (also called "ring buffer")
// which is used as up-buffer (T->H)
//
typedef struct {
const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
char* pBuffer; // Pointer to start of buffer
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
unsigned WrOff; // Position of next item to be written by either target.
volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host.
unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
} SEGGER_RTT_BUFFER_UP;
//
// Description for a circular buffer (also called "ring buffer")
// which is used as down-buffer (H->T)
//
typedef struct {
const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
char* pBuffer; // Pointer to start of buffer
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host.
unsigned RdOff; // Position of next item to be read by target (down-buffer).
unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
} SEGGER_RTT_BUFFER_DOWN;
//
// RTT control block which describes the number of buffers available
// as well as the configuration for each buffer
//
//
typedef struct {
char acID[16]; // Initialized to "SEGGER RTT"
int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host
SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target
#if SEGGER_RTT__CB_PADDING
unsigned char aDummy[SEGGER_RTT__CB_PADDING];
#endif
} SEGGER_RTT_CB;
/*********************************************************************
*
* Global data
*
**********************************************************************
*/
extern SEGGER_RTT_CB _SEGGER_RTT;
/*********************************************************************
*
* RTT API functions
*
**********************************************************************
*/
#ifdef __cplusplus
extern "C" {
#endif
int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
int SEGGER_RTT_GetKey (void);
unsigned SEGGER_RTT_HasData (unsigned BufferIndex);
int SEGGER_RTT_HasKey (void);
unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex);
void SEGGER_RTT_Init (void);
unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName);
int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName);
int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags);
int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags);
int SEGGER_RTT_WaitKey (void);
unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s);
void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c);
unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c);
unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c);
unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex);
unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex);
//
// Function macro for performance optimization
//
#define SEGGER_RTT_HASDATA(n) (((SEGGER_RTT_BUFFER_DOWN*)((uintptr_t)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_DOWN*)((uintptr_t)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff)
#if RTT_USE_ASM
#define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock
#endif
/*********************************************************************
*
* RTT transfer functions to send RTT data via other channels.
*
**********************************************************************
*/
unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
#define SEGGER_RTT_HASDATA_UP(n) (((SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
/*********************************************************************
*
* RTT "Terminal" API functions
*
**********************************************************************
*/
int SEGGER_RTT_SetTerminal (unsigned char TerminalId);
int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s);
/*********************************************************************
*
* RTT printf functions (require SEGGER_RTT_printf.c)
*
**********************************************************************
*/
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...);
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
#ifdef __cplusplus
}
#endif
#endif // ifndef(SEGGER_RTT_ASM)
//
// For some environments, NULL may not be defined until certain headers are included
//
#ifndef NULL
#define NULL ((void*)0)
#endif
/*********************************************************************
*
* Defines
*
**********************************************************************
*/
//
// Operating modes. Define behavior if buffer is full (not enough space for entire message)
//
#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default)
#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits.
#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer.
#define SEGGER_RTT_MODE_MASK (3)
//
// Control sequences, based on ANSI.
// Can be used to control color, and clear the screen
//
#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors
#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left
#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m"
#define RTT_CTRL_TEXT_RED "\x1B[2;31m"
#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m"
#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m"
#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m"
#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m"
#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m"
#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m"
#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m"
#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m"
#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m"
#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m"
#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m"
#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m"
#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m"
#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m"
#define RTT_CTRL_BG_BLACK "\x1B[24;40m"
#define RTT_CTRL_BG_RED "\x1B[24;41m"
#define RTT_CTRL_BG_GREEN "\x1B[24;42m"
#define RTT_CTRL_BG_YELLOW "\x1B[24;43m"
#define RTT_CTRL_BG_BLUE "\x1B[24;44m"
#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m"
#define RTT_CTRL_BG_CYAN "\x1B[24;46m"
#define RTT_CTRL_BG_WHITE "\x1B[24;47m"
#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m"
#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m"
#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m"
#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m"
#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m"
#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m"
#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m"
#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m"
#endif
/*************************** End of file ****************************/
+440
View File
@@ -0,0 +1,440 @@
/*********************************************************************
* SEGGER Microcontroller GmbH *
* The Embedded Experts *
**********************************************************************
* *
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
* *
* www.segger.com Support: support@segger.com *
* *
**********************************************************************
* *
* SEGGER RTT * Real Time Transfer for embedded targets *
* *
**********************************************************************
* *
* All rights reserved. *
* *
* SEGGER strongly recommends to not make any changes *
* to or modify the source code of this software in order to stay *
* compatible with the RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* condition is met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this condition and the following disclaimer. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
* DAMAGE. *
* *
**********************************************************************
* *
* RTT version: 8.56a *
* *
**********************************************************************
---------------------------END-OF-HEADER------------------------------
File : SEGGER_RTT_Conf.h
Purpose : Implementation of SEGGER real-time transfer (RTT) which
allows real-time communication on targets which support
debugger memory accesses while the CPU is running.
Revision: $Rev: 24316 $
*/
#ifndef SEGGER_RTT_CONF_H
#define SEGGER_RTT_CONF_H
#ifdef __IAR_SYSTEMS_ICC__
#include <intrinsics.h>
#endif
/*********************************************************************
*
* Defines, configurable
*
**********************************************************************
*/
//
// Take in and set to correct values for Cortex-A systems with CPU cache
//
//#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (32) // Largest cache line size (in bytes) in the current system
//#define SEGGER_RTT_UNCACHED_OFF (0xFB000000) // Address alias where RTT CB and buffers can be accessed uncached
//
// Most common case:
// Up-channel 0: RTT
// Up-channel 1: SystemView
//
#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (1) // Max. number of up-buffers (T->H) available on this target (Default: 3)
#endif
//
// Most common case:
// Down-channel 0: RTT
// Down-channel 1: SystemView
//
#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (1) // Max. number of down-buffers (H->T) available on this target (Default: 3)
#endif
#ifndef BUFFER_SIZE_UP
#define BUFFER_SIZE_UP (2048) // Size of the buffer for terminal output of target, up to host (Default: 1k)
#endif
#ifndef BUFFER_SIZE_DOWN
#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16)
#endif
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64)
#endif
#ifndef SEGGER_RTT_MODE_DEFAULT
#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0)
#endif
/*********************************************************************
*
* RTT memcpy configuration
*
* memcpy() is good for large amounts of data,
* but the overhead is big for small amounts, which are usually stored via RTT.
* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead.
*
* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions.
* This is may be required with memory access restrictions,
* such as on Cortex-A devices with MMU.
*/
#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP
#define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop
#endif
//
// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets
//
//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__))
// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes))
//#endif
//
// Target is not allowed to perform other RTT operations while string still has not been stored completely.
// Otherwise we would probably end up with a mixed string in the buffer.
// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here.
//
// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4.
// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches.
// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly.
// (Higher priority = lower priority number)
// Default value for embOS: 128u
// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC
// or define SEGGER_RTT_LOCK() to completely disable interrupts.
//
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20)
#endif
/*********************************************************************
*
* RTT lock configuration for SEGGER Embedded Studio,
* Rowley CrossStudio and GCC
*/
#if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32))
#if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__))
#define SEGGER_RTT_LOCK() { \
unsigned int _SEGGER_RTT__LockState; \
__asm volatile ("mrs %0, primask \n\t" \
"movs r1, #1 \n\t" \
"msr primask, r1 \n\t" \
: "=r" (_SEGGER_RTT__LockState) \
: \
: "r1", "cc" \
);
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \
: \
: "r" (_SEGGER_RTT__LockState) \
: \
); \
}
#elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__))
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
#endif
#define SEGGER_RTT_LOCK() { \
unsigned int _SEGGER_RTT__LockState; \
__asm volatile ("mrs %0, basepri \n\t" \
"mov r1, %1 \n\t" \
"msr basepri, r1 \n\t" \
: "=r" (_SEGGER_RTT__LockState) \
: "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \
: "r1", "cc" \
);
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \
: \
: "r" (_SEGGER_RTT__LockState) \
: \
); \
}
#elif (defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__))
#define SEGGER_RTT_LOCK() { \
unsigned int _SEGGER_RTT__LockState; \
__asm volatile ("mrs r1, CPSR \n\t" \
"mov %0, r1 \n\t" \
"orr r1, r1, #0xC0 \n\t" \
"msr CPSR_c, r1 \n\t" \
: "=r" (_SEGGER_RTT__LockState) \
: \
: "r1", "cc" \
);
#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
"mrs r1, CPSR \n\t" \
"bic r1, r1, #0xC0 \n\t" \
"and r0, r0, #0xC0 \n\t" \
"orr r1, r1, r0 \n\t" \
"msr CPSR_c, r1 \n\t" \
: \
: "r" (_SEGGER_RTT__LockState) \
: "r0", "r1", "cc" \
); \
}
#elif defined(__riscv) || defined(__riscv_xlen)
#define SEGGER_RTT_LOCK() { \
unsigned int _SEGGER_RTT__LockState; \
__asm volatile ("csrr %0, mstatus \n\t" \
"csrci mstatus, 8 \n\t" \
"andi %0, %0, 8 \n\t" \
: "=r" (_SEGGER_RTT__LockState) \
: \
: \
);
#define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \
"or %0, %0, a1 \n\t" \
"csrs mstatus, %0 \n\t" \
: \
: "r" (_SEGGER_RTT__LockState) \
: "a1" \
); \
}
#else
#define SEGGER_RTT_LOCK()
#define SEGGER_RTT_UNLOCK()
#endif
#endif
/*********************************************************************
*
* RTT lock configuration for IAR EWARM
*/
#ifdef __ICCARM__
#if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \
(defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__))
#define SEGGER_RTT_LOCK() { \
unsigned int _SEGGER_RTT__LockState; \
_SEGGER_RTT__LockState = __get_PRIMASK(); \
__set_PRIMASK(1);
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \
}
#elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \
(defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \
(defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \
(defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__))
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
#endif
#define SEGGER_RTT_LOCK() { \
unsigned int _SEGGER_RTT__LockState; \
_SEGGER_RTT__LockState = __get_BASEPRI(); \
__set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
#define SEGGER_RTT_UNLOCK() __set_BASEPRI(_SEGGER_RTT__LockState); \
}
#elif (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || \
(defined (__ARM7R__) && (__CORE__ == __ARM7R__))
#define SEGGER_RTT_LOCK() { \
unsigned int _SEGGER_RTT__LockState; \
__asm volatile ("mrs r1, CPSR \n\t" \
"mov %0, r1 \n\t" \
"orr r1, r1, #0xC0 \n\t" \
"msr CPSR_c, r1 \n\t" \
: "=r" (_SEGGER_RTT__LockState) \
: \
: "r1", "cc" \
);
#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
"mrs r1, CPSR \n\t" \
"bic r1, r1, #0xC0 \n\t" \
"and r0, r0, #0xC0 \n\t" \
"orr r1, r1, r0 \n\t" \
"msr CPSR_c, r1 \n\t" \
: \
: "r" (_SEGGER_RTT__LockState) \
: "r0", "r1", "cc" \
); \
}
#endif
#endif
/*********************************************************************
*
* RTT lock configuration for IAR RX
*/
#ifdef __ICCRX__
#define SEGGER_RTT_LOCK() { \
unsigned long _SEGGER_RTT__LockState; \
_SEGGER_RTT__LockState = __get_interrupt_state(); \
__disable_interrupt();
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \
}
#endif
/*********************************************************************
*
* RTT lock configuration for IAR RL78
*/
#ifdef __ICCRL78__
#define SEGGER_RTT_LOCK() { \
__istate_t _SEGGER_RTT__LockState; \
_SEGGER_RTT__LockState = __get_interrupt_state(); \
__disable_interrupt();
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \
}
#endif
/*********************************************************************
*
* RTT lock configuration for KEIL ARM
*/
#ifdef __CC_ARM
#if (defined __TARGET_ARCH_6S_M)
#define SEGGER_RTT_LOCK() { \
unsigned int _SEGGER_RTT__LockState; \
register unsigned char _SEGGER_RTT__PRIMASK __asm( "primask"); \
_SEGGER_RTT__LockState = _SEGGER_RTT__PRIMASK; \
_SEGGER_RTT__PRIMASK = 1u; \
__schedule_barrier();
#define SEGGER_RTT_UNLOCK() _SEGGER_RTT__PRIMASK = _SEGGER_RTT__LockState; \
__schedule_barrier(); \
}
#elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M))
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
#endif
#define SEGGER_RTT_LOCK() { \
unsigned int _SEGGER_RTT__LockState; \
register unsigned char BASEPRI __asm( "basepri"); \
_SEGGER_RTT__LockState = BASEPRI; \
BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \
__schedule_barrier();
#define SEGGER_RTT_UNLOCK() BASEPRI = _SEGGER_RTT__LockState; \
__schedule_barrier(); \
}
#endif
#endif
/*********************************************************************
*
* RTT lock configuration for TI ARM
*/
#ifdef __TI_ARM__
#if defined (__TI_ARM_V6M0__)
#define SEGGER_RTT_LOCK() { \
unsigned int _SEGGER_RTT__LockState; \
_SEGGER_RTT__LockState = __get_PRIMASK(); \
__set_PRIMASK(1);
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \
}
#elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__))
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
#endif
#define SEGGER_RTT_LOCK() { \
unsigned int _SEGGER_RTT__LockState; \
_SEGGER_RTT__LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
#define SEGGER_RTT_UNLOCK() _set_interrupt_priority(_SEGGER_RTT__LockState); \
}
#endif
#endif
/*********************************************************************
*
* RTT lock configuration for CCRX
*/
#ifdef __RX
#include <machine.h>
#define SEGGER_RTT_LOCK() { \
unsigned long _SEGGER_RTT__LockState; \
_SEGGER_RTT__LockState = get_psw() & 0x010000; \
clrpsw_i();
#define SEGGER_RTT_UNLOCK() set_psw(get_psw() | _SEGGER_RTT__LockState); \
}
#endif
/*********************************************************************
*
* RTT lock configuration for embOS Simulation on Windows
* (Can also be used for generic RTT locking with embOS)
*/
#if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS)
void OS_SIM_EnterCriticalSection(void);
void OS_SIM_LeaveCriticalSection(void);
#define SEGGER_RTT_LOCK() { \
OS_SIM_EnterCriticalSection();
#define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \
}
#endif
/*********************************************************************
*
* RTT lock configuration fallback
*/
#ifndef SEGGER_RTT_LOCK
#define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts)
#endif
#ifndef SEGGER_RTT_UNLOCK
#define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state)
#endif
/*********************************************************************
*
* If SEGGER_RTT_SECTION is defined but SEGGER_RTT_BUFFER_SECTION
* is not, use the same section for SEGGER_RTT_BUFFER_SECTION.
*/
#ifndef SEGGER_RTT_BUFFER_SECTION
#if defined(SEGGER_RTT_SECTION)
#define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
#endif
#endif
#endif
/*************************** End of file ****************************/