|  | @@ -59,7 +59,7 @@ static TimerHandle_t fpga_timesync_timer;
 | 
	
		
			
				|  |  |  static SemaphoreHandle_t spi_mutex;
 | 
	
		
			
				|  |  |  static EventGroupHandle_t spi_done_evgroup;
 | 
	
		
			
				|  |  |  static volatile bool spi_abort_all;
 | 
	
		
			
				|  |  | -static const volatile struct esplink_timesync *tsync_addr;
 | 
	
		
			
				|  |  | +static struct esplink_head head;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #define NOTIFY_INDEX	0
 | 
	
		
			
				|  |  |  #define NOTIFY_FPGA	(1 << 0)
 | 
	
	
		
			
				|  | @@ -235,8 +235,6 @@ static void fpga_poll_set_time(void);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static bool fpga_online(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    struct esplink_head head;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      fpga_io_read(FPGA_CMD_ACK(EL_UIRQ_READY), ESPLINK_HDR_ADDR,
 | 
	
		
			
				|  |  |  		 &head, sizeof head);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -255,8 +253,6 @@ static bool fpga_online(void)
 | 
	
		
			
				|  |  |  	   head.board.major, head.board.minor,
 | 
	
		
			
				|  |  |  	   head.board.fixes, head.board.fpga);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    tsync_addr = head.tsync;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      printf("[FPGA] online, signature \"%.*s\"\n",
 | 
	
		
			
				|  |  |  	   (int)(sizeof head.signature - 1), head.signature);
 | 
	
		
			
				|  |  |      esplink_start(&head);
 | 
	
	
		
			
				|  | @@ -272,7 +268,7 @@ static bool fpga_online(void)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void fpga_offline(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    tsync_addr = NULL;
 | 
	
		
			
				|  |  | +    memset(&head, 0, sizeof head);
 | 
	
		
			
				|  |  |      xSemaphoreTakeRecursive(spi_mutex, portMAX_DELAY);
 | 
	
		
			
				|  |  |      xTimerStop(fpga_timesync_timer, portMAX_DELAY);
 | 
	
		
			
				|  |  |      setenv_bool("status.max80.fpga", false);
 | 
	
	
		
			
				|  | @@ -363,7 +359,7 @@ fail:
 | 
	
		
			
				|  |  |      return err;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -esp_err_t fpga_io_write(unsigned int cmd, const void *addr,
 | 
	
		
			
				|  |  | +esp_err_t fpga_io_write(unsigned int cmd, const volatile void *addr,
 | 
	
		
			
				|  |  |  			const void *data, size_t len)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      struct fpga_iov iov;
 | 
	
	
		
			
				|  | @@ -376,7 +372,7 @@ esp_err_t fpga_io_write(unsigned int cmd, const void *addr,
 | 
	
		
			
				|  |  |      return fpga_iov(&iov, 1);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -esp_err_t fpga_io_read(unsigned int cmd, const void *addr,
 | 
	
		
			
				|  |  | +esp_err_t fpga_io_read(unsigned int cmd, const volatile void *addr,
 | 
	
		
			
				|  |  |  		       void *data, size_t len)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      struct fpga_iov iov;
 | 
	
	
		
			
				|  | @@ -406,7 +402,7 @@ static void fpga_get_time(void)
 | 
	
		
			
				|  |  |  	struct esplink_timesync_buf get;
 | 
	
		
			
				|  |  |      } tsbuf;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (!tsync_addr) {
 | 
	
		
			
				|  |  | +    if (!head.tsync) {
 | 
	
		
			
				|  |  |  	fpga_io_status(FPGA_CMD_ACK(EL_UIRQ_TIME));
 | 
	
		
			
				|  |  |  	return;
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -422,7 +418,7 @@ static void fpga_get_time(void)
 | 
	
		
			
				|  |  |      trans.base.rxlength = sizeof tsbuf << 3;
 | 
	
		
			
				|  |  |      trans.base.rx_buffer = &tsbuf;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    trans.base.addr = (size_t)&tsync_addr->get;
 | 
	
		
			
				|  |  | +    trans.base.addr = (size_t)&head.tsync->get;
 | 
	
		
			
				|  |  |      trans.base.cmd  = FPGA_CMD_RD | FPGA_CMD_ACK(EL_UIRQ_TIME);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      xSemaphoreTakeRecursive(spi_mutex, portMAX_DELAY);
 | 
	
	
		
			
				|  | @@ -454,7 +450,7 @@ static void fpga_get_time(void)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void fpga_poll_set_time(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    if (!tsync_addr)
 | 
	
		
			
				|  |  | +    if (!head.tsync)
 | 
	
		
			
				|  |  |  	return;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (!time_net_sync_status) {
 | 
	
	
		
			
				|  | @@ -494,7 +490,7 @@ static void fpga_poll_set_time(void)
 | 
	
		
			
				|  |  |      trans.length = sizeof tset << 3;
 | 
	
		
			
				|  |  |      trans.tx_buffer = &tset;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    trans.addr = (size_t)&tsync_addr->set;
 | 
	
		
			
				|  |  | +    trans.addr = (size_t)&head.tsync->set;
 | 
	
		
			
				|  |  |      trans.cmd  = FPGA_CMD_WR | FPGA_CMD_IRQ(EL_DIRQ_TIME) |
 | 
	
		
			
				|  |  |  	FPGA_CMD_ACK(EL_UIRQ_TIME);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -533,6 +529,34 @@ uint32_t fpga_io_status(unsigned int cmd)
 | 
	
		
			
				|  |  |      return err ? 0 : *(const uint32_t *)trans.rx_data;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static int fpga_read_func(token_t token, void *buf, size_t len)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    const void **pp = token;
 | 
	
		
			
				|  |  | +    const char *p = *pp;
 | 
	
		
			
				|  |  | +    esp_err_t err;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    err = fpga_io_read(0, p, buf, len);
 | 
	
		
			
				|  |  | +    if (err)
 | 
	
		
			
				|  |  | +	return -1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    p += len;
 | 
	
		
			
				|  |  | +    *pp = p;
 | 
	
		
			
				|  |  | +    return len;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void fpga_ota_update(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    struct esplink_ota ota;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    fpga_io_read(0, head.ota, &ota, sizeof ota);
 | 
	
		
			
				|  |  | +    if (!ota.data)
 | 
	
		
			
				|  |  | +	return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    esp_update(fpga_read_func, &ota.data, ota.len);
 | 
	
		
			
				|  |  | +    fpga_io_status(FPGA_CMD_ACK(EL_UIRQ_OTA)|FPGA_CMD_IRQ(EL_DIRQ_DONE));
 | 
	
		
			
				|  |  | +    reboot_delayed();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void fpga_service_task(void *dummy)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      (void)dummy;
 | 
	
	
		
			
				|  | @@ -565,17 +589,18 @@ static void fpga_service_task(void *dummy)
 | 
	
		
			
				|  |  |  	  printf("[FPGA] FPGA status flags = 0x%08x\n", status);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	  if (!digitalRead(PIN_FPGA_INT)) {
 | 
	
		
			
				|  |  | -	      for (unsigned int i = 2; i < 8; i++) {
 | 
	
		
			
				|  |  | +	      for (unsigned int i = 1; i < 8; i++) {
 | 
	
		
			
				|  |  |  		  if (status & (0x100 << i))
 | 
	
		
			
				|  |  |  		      status = fpga_io_status(FPGA_CMD_ACK(i));
 | 
	
		
			
				|  |  |  	      }
 | 
	
		
			
				|  |  |  	      if ((status & 0x301) == 0x300) {
 | 
	
		
			
				|  |  | -		  if (fpga_online())
 | 
	
		
			
				|  |  | +		  if (fpga_online()) {
 | 
	
		
			
				|  |  |  		      fpga_state = FPGA_ONLINE;
 | 
	
		
			
				|  |  | +		      break;
 | 
	
		
			
				|  |  | +		  }
 | 
	
		
			
				|  |  |  	      }
 | 
	
		
			
				|  |  | -	  } else {
 | 
	
		
			
				|  |  | -	      notifiers = notify_wait_for(NOTIFY_FPGA|NOTIFY_DISABLE);
 | 
	
		
			
				|  |  |  	  }
 | 
	
		
			
				|  |  | +	  notifiers = notify_wait_for(NOTIFY_FPGA|NOTIFY_DISABLE);
 | 
	
		
			
				|  |  |  	  break;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	case FPGA_ONLINE:
 | 
	
	
		
			
				|  | @@ -604,7 +629,10 @@ static void fpga_service_task(void *dummy)
 | 
	
		
			
				|  |  |  		if (status & (0x100 << EL_UIRQ_RINGBUF))
 | 
	
		
			
				|  |  |  		    esplink_poll();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		for (unsigned int i = 4; i < 8; i++) {
 | 
	
		
			
				|  |  | +		if (status & (0x100 << EL_UIRQ_OTA))
 | 
	
		
			
				|  |  | +		    fpga_ota_update();
 | 
	
		
			
				|  |  | +		
 | 
	
		
			
				|  |  | +		for (unsigned int i = 5; i < 8; i++) {
 | 
	
		
			
				|  |  |  		    if (status & (0x100 << i)) {
 | 
	
		
			
				|  |  |  			printf("[FPGA] Invalid interrupt %u received\n", i);
 | 
	
		
			
				|  |  |  			status = fpga_io_status(FPGA_CMD_ACK(i));
 |