Skip to content

Commit

Permalink
ENC424J600 & SPI driver optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
jolivepetrus committed Apr 13, 2017
1 parent 82bf983 commit 799b155
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 140 deletions.
162 changes: 58 additions & 104 deletions components/lua_rtos/drivers/ENC424J600.c
Expand Up @@ -61,14 +61,14 @@

extern void spi_ethernetif_input(struct netif *neti);

#define ENC424J600_INT_MASK (EIR_LINKIF | EIR_PKTIF | EIR_TXIF | EIR_TXABTIF | EIR_RXABTIF | EIR_PCFULIF)
#define ENC424J600_INT_MASK (EIR_LINKIF | EIR_PKTIF)

static volatile int currentBank;
static uint16_t nextPacketPointer;
static int spi_device;
static struct netif *interface;

xQueueHandle ether_q;
static xQueueHandle ether_q = NULL;

static uint16_t exec_8_op(uint8_t op);
static uint16_t exec_16_op(uint8_t op, uint16_t data);
Expand All @@ -79,8 +79,6 @@ static uint16_t read_reg(uint16_t address);
static void write_phy_reg(uint8_t address, uint16_t Data);
static void bfs_reg(uint16_t address, uint16_t bitMask);
static void bfc_reg(uint16_t address, uint16_t bitMask);
static void suspend_interrupts();
static void reenable_interrupts();
static int phy_reset();
static void mac_flush(void);
static void write_n(uint8_t op, uint8_t* data, uint16_t len);
Expand Down Expand Up @@ -172,29 +170,6 @@ static uint16_t read_reg(uint16_t address) {
return returnValue;
}

#if 0
static uint16_t read_phy_reg(uint8_t address) {
uint16_t readed;

// Set the right address and start the register read operation
write_reg(MIREGADR, 0x0100 | address);
write_reg(MICMD, MICMD_MIIRD);

// Loop to wait until the PHY register has been read through the MII
// This requires 25.6us
while (read_reg(MISTAT) & MISTAT_BUSY)
;

// Stop reading
write_reg(MICMD, 0x0000);

// Obtain results and return
readed = read_reg(MIRD);

return readed;
}
#endif

static void write_phy_reg(uint8_t address, uint16_t Data) {
// Write the register address
write_reg(MIREGADR, 0x0100 | address);
Expand Down Expand Up @@ -223,17 +198,6 @@ static void bfc_reg(uint16_t address, uint16_t bitMask) {
exec_16_op(BFC | (address & 0x1F), bitMask);
}

static void suspend_interrupts() {
// Disable global interrupts while processing this interrupt
// to avoid loose events
bfc_reg(EIE, EIE_INTIE);
}

static void reenable_interrupts() {
// Reenable ENC global interrupts
bfs_reg(EIE, EIE_INTIE);
}

static int phy_reset() {
uint16_t ret = 0;
time_t start, now;
Expand Down Expand Up @@ -283,63 +247,42 @@ static int phy_reset() {
return 0;
}

/*
* SPI Ethernet task. Waits the ISR for process an interrupt.
*
*/
static void ether_task(void *taskArgs) {
uint16_t flag;
uint8_t dummy;

for(;;) {
xQueueReceive(ether_q, &flag, portMAX_DELAY);
// Wait the ISR
xQueueReceive(ether_q, &dummy, portMAX_DELAY);

if (flag & EIR_LINKIF) {
link_status_change();
bfc_reg(EIR, EIR_LINKIF);
}

if (flag & EIR_PKTIF) {
spi_ethernetif_input(interface);
bfc_reg(EIR, EIR_PKTIF);
}
// Get cause
unsigned int flag = read_reg(EIR);

if (flag & EIR_TXIF) {
// Packet transmission has completed
bfc_reg(EIR, EIR_TXIF);
}

if (flag & EIR_TXABTIF) {
// Packet transmission has been aborted due to an error
bfc_reg(EIR, EIR_TXABTIF);
}

if (flag & EIR_RXABTIF) {
// An RX packet was dropped because there is insufficient space in the
// RX buffer to store the complete packet
bfc_reg(EIR, EIR_RXABTIF);
}

if (flag & EIR_PCFULIF) {
// PKTCNT field has reached FFh. Software must decrement the packet
// counter to prevent the next RX packet from being dropped
bfc_reg(EIR, EIR_PCFULIF);
}
if (flag) {
if (flag & EIR_LINKIF) {
link_status_change();
}

gpio_intr_enable(CONFIG_SPI_ETHERNET_INT);
if (flag & EIR_PKTIF) {
spi_ethernetif_input(interface);
}

// Reenable interrupts
reenable_interrupts();
// Clear all interrupt flags
bfc_reg(EIR, 0xfff);
}
}
}

static void ether_intr(void* arg) {
// Disable interrupt on GPIO
gpio_intr_disable(CONFIG_SPI_ETHERNET_INT);
uint8_t dummy = 0;

// Suspend interrupts
suspend_interrupts();

// Get cause of this interrupt
unsigned int flag = read_reg(EIR);

// Send to ethernet task
xQueueSendFromISR(ether_q, &flag, NULL);
// Inform the ethernet task that there is a new interrupt
// for process. A dummy value is queued, because we don't
// want to pass data.
xQueueSendFromISR(ether_q, &dummy, NULL);
}

static void mac_flush(void) {
Expand Down Expand Up @@ -518,7 +461,20 @@ int enc424j600_init(struct netif *netif) {
// Enable RX packet reception
bfs_reg(ECON1, ECON1_RXEN);

// Configure external interrupt line
// Disable all interrupts
bfc_reg(EIE, 0xfff);

// Clear all interrupt flags
bfc_reg(EIR, 0xfff);

// Configure external interrupt line
if (!ether_q) {
ether_q = xQueueCreate(100, sizeof(uint8_t));
}

// ISR related task must run on the same core that ISR handler is added
xTaskCreatePinnedToCore(ether_task, "eth", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 6, NULL, xPortGetCoreID());

if (!status_get(STATUS_ISR_SERVICE_INSTALLED)) {
gpio_install_isr_service(0);

Expand All @@ -530,17 +486,6 @@ int enc424j600_init(struct netif *netif) {
gpio_set_intr_type(CONFIG_SPI_ETHERNET_INT, GPIO_INTR_NEGEDGE);
gpio_isr_handler_add(CONFIG_SPI_ETHERNET_INT, ether_intr, NULL);

ether_q = xQueueCreate(100, sizeof(unsigned int));

// ISR related task must run on the same core that ISR handler is added
xTaskCreatePinnedToCore(ether_task, "eth", CONFIG_LUA_RTOS_LUA_THREAD_STACK_SIZE, NULL, CONFIG_LUA_RTOS_LUA_THREAD_PRIORITY, NULL, xPortGetCoreID());

// Disable all interrupts
bfc_reg(EIE, 0xfff);

// Clear all interrupt flags
bfc_reg(EIR, 0xfff);

// Enable interrupts
bfs_reg(EIE, ENC424J600_INT_MASK);

Expand All @@ -550,28 +495,37 @@ int enc424j600_init(struct netif *netif) {
struct pbuf *enc424j600_input(struct netif *netif) {
RXSTATUS statusVector;
uint16_t newRXTail;
struct pbuf *p, *q;
struct pbuf *p = NULL, *q = NULL;
u16_t len = 0;
u16_t frame_size = 0;

// Ensure that are pending packets
if (!(read_reg(ESTAT) & 0b11111111)) {
return NULL;
}

// Set the RX Read Pointer to the beginning of the next unprocessed packet
write_reg(ERXRDPT, nextPacketPointer);

// Read the adress of next packet
read_memory_window(RX_WINDOW, (uint8_t*) & nextPacketPointer, sizeof (nextPacketPointer));
read_memory_window(RX_WINDOW, (uint8_t*) & statusVector, sizeof (statusVector));

len = statusVector.bits.ByteCount - 4;

if (statusVector.bits.Zero || statusVector.bits.ZeroH ||
statusVector.bits.CRCError ||
statusVector.bits.ByteCount > 1522u ||
!statusVector.bits.ReceiveOk) {
// Read the receive status vector
read_memory_window(RX_WINDOW, (uint8_t*) & statusVector, sizeof (statusVector));

// Check the packet
if (
statusVector.bits.Zero || statusVector.bits.ZeroH || statusVector.bits.CRCError ||
statusVector.bits.ByteCount > 1522u || !statusVector.bits.ReceiveOk
) {
goto exit;
}

// Get the packet length
len = statusVector.bits.ByteCount - 4;

// If we don't receive nothing, exit
if (len <= 0) {
if (len == 0) {
goto exit;
}

Expand Down
2 changes: 1 addition & 1 deletion components/lua_rtos/drivers/ENC424J600.h
Expand Up @@ -68,7 +68,7 @@
// ENC424J600 config
#define ENC424J600_RAMSIZE (0x6000)
#define ENC424J600_TXSTART (0x0000)
#define ENC424J600_RXSTART (030000) // Should be an even memory address
#define ENC424J600_RXSTART (0x3000) // Should be an even memory address

void enc424j600Init(void);
uint16_t enc424j600PacketReceive(uint16_t maxlen, uint8_t* packet);
Expand Down
26 changes: 11 additions & 15 deletions components/lua_rtos/drivers/spi.c
Expand Up @@ -161,11 +161,11 @@ static void _spi_init() {
spi_bus[3].mtx = xSemaphoreCreateRecursiveMutex();
}

static void IRAM_ATTR spi_lock(uint8_t unit) {
static void spi_lock(uint8_t unit) {
xSemaphoreTakeRecursive(spi_bus[unit].mtx, portMAX_DELAY);
}

static void IRAM_ATTR spi_unlock(uint8_t unit) {
static void spi_unlock(uint8_t unit) {
while (xSemaphoreGiveRecursive(spi_bus[unit].mtx) == pdTRUE);
}

Expand Down Expand Up @@ -462,8 +462,6 @@ static void spi_setup_bus(uint8_t unit) {
*
*/
int spi_ll_setup(uint8_t unit, uint8_t master, uint8_t cs, uint8_t mode, uint32_t speed, int *deviceid) {
spi_lock(unit);

// Check if there's some device un bus with the same cs
// If there's one, we want to reconfigure device
int device = spi_get_device_by_cs(unit, cs);
Expand All @@ -473,7 +471,6 @@ int spi_ll_setup(uint8_t unit, uint8_t master, uint8_t cs, uint8_t mode, uint32_
device = spi_get_free_device(unit);
if (device < 0) {
// No more devices
spi_unlock(unit);
return -1;
}
} else {
Expand Down Expand Up @@ -528,8 +525,6 @@ int spi_ll_setup(uint8_t unit, uint8_t master, uint8_t cs, uint8_t mode, uint32_
spi_bus[unit].setup = 1;
spi_bus[unit].device[device].setup = 1;

spi_unlock(unit);

*deviceid = (unit << 8) | device;

return 0;
Expand All @@ -539,16 +534,13 @@ void spi_ll_get_speed(int deviceid, uint32_t *speed) {
int unit = (deviceid & 0xff00) >> 8;
int device = (deviceid & 0x00ff);

spi_lock(unit);
*speed = spi_bus[unit].device[device].speed;
spi_unlock(unit);
}

void spi_ll_set_speed(int deviceid, uint32_t speed) {
int unit = (deviceid & 0xff00) >> 8;
int device = (deviceid & 0x00ff);

spi_lock(unit);
spi_bus[unit].last_device = -1;
spi_bus[unit].device[device].speed = speed;
#if !SPI_USE_IDF_DRIVER
Expand All @@ -569,7 +561,6 @@ void spi_ll_set_speed(int deviceid, uint32_t speed) {
assert(ret==ESP_OK);

#endif
spi_unlock(unit);
}

void IRAM_ATTR spi_ll_transfer(int deviceid, uint8_t data, uint8_t *read) {
Expand Down Expand Up @@ -674,8 +665,6 @@ void IRAM_ATTR spi_ll_select(int deviceid) {
int unit = (deviceid & 0xff00) >> 8;
int device = (deviceid & 0x00ff);

spi_lock(unit);

if (spi_bus[unit].last_device != deviceid) {
#if !SPI_USE_IDF_DRIVER
// Complete operations, if pending
Expand Down Expand Up @@ -744,8 +733,6 @@ void IRAM_ATTR spi_ll_deselect(int deviceid) {

// Deselect device
gpio_ll_pin_set(spi_bus[unit].device[device].cs);

spi_unlock(unit);
}


Expand Down Expand Up @@ -798,9 +785,12 @@ driver_error_t *spi_setup(uint8_t unit, uint8_t master, uint8_t cs, uint8_t mode
}

// Low-level setup
spi_lock(unit);
if (spi_ll_setup(unit, master, cs, mode, speed, deviceid) != 0) {
spi_unlock(unit);
return driver_operation_error(SPI_DRIVER, SPI_ERR_NO_MORE_DEVICES_ALLOWED, NULL);
}
spi_unlock(unit);

return NULL;
}
Expand All @@ -822,6 +812,7 @@ driver_error_t *spi_select(int deviceid) {
return driver_operation_error(SPI_DRIVER, SPI_ERR_DEVICE_NOT_SETUP, NULL);
}

spi_lock(unit);
spi_ll_select(deviceid);

return NULL;
Expand All @@ -845,6 +836,7 @@ driver_error_t *spi_deselect(int deviceid) {
}

spi_ll_deselect(deviceid);
spi_unlock(unit);

return NULL;
}
Expand All @@ -866,7 +858,9 @@ driver_error_t *spi_get_speed(int deviceid, uint32_t *speed) {
return driver_operation_error(SPI_DRIVER, SPI_ERR_DEVICE_NOT_SETUP, NULL);
}

spi_lock(unit);
spi_ll_get_speed(deviceid, speed);
spi_unlock(unit);

return NULL;
}
Expand All @@ -888,7 +882,9 @@ driver_error_t *spi_set_speed(int deviceid, uint32_t speed) {
return driver_operation_error(SPI_DRIVER, SPI_ERR_DEVICE_NOT_SETUP, NULL);
}

spi_lock(unit);
spi_ll_set_speed(deviceid, speed);
spi_unlock(unit);

return NULL;
}
Expand Down

0 comments on commit 799b155

Please sign in to comment.