GreenWaves-Technologies / gap_sdk

SDK for Greenwaves Technologies' GAP8 IoT Application Processor
https://greenwaves-technologies.com/en/gap8-the-internet-of-things-iot-application-processor/
Apache License 2.0
137 stars 75 forks source link

AI-deck SPI communication GAP8-NINA with FreeRTOS #267

Open Manucar opened 3 years ago

Manucar commented 3 years ago

Hi!

I am trying to send simple data from the GAP8 chip to the NINA chip via SPI on the AI-deck board using FreeRTOS. The Wi-Fi example available on the AI-deck repo send JPEG images, so there are a lot of useless stuff for a simple SPI communication and also it uses PULPOS on the GAP8 side.

For my implementation I need FreeRTOS and so I made some changes following my second comment on this previous issue #190 in order to compile without errors (so please let me know if these changes are legit, or could break something).

The code for the GAP8 side is pretty simple:

/* PMSIS includes */
#include "pmsis.h"
#include "bsp/transport/nina_w10.h"
#include "stdio.h"

#define DATA_BUFF_LEN 16

uint8_t nina_send_buffer[DATA_BUFF_LEN] =  {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3}; 
struct pi_nina_w10_conf nina_conf;
struct pi_device esp32;
static volatile int trans_done;

static void spi_cb(void *arg)
{
  trans_done = 1;
  return;
}

/**
 * Main task.
 */
void vMainTask(void)
{
    pi_nina_w10_conf_init(&nina_conf);
    // Init device here
    nina_conf.ssid = "";
    nina_conf.passwd = "";
    nina_conf.ip_addr = "0.0.0.0";
    nina_conf.port = 5555;
    pi_open_from_conf(&esp32, &nina_conf);
    pi_transport_open(&esp32); 
    printf("\n\n\t *** transport open ***\n\n");
    pi_task_t nina_task;
    trans_done = 1;

    while( 1 )
    {
        if(trans_done)
        {
            //printf("\n\n\t *** while ***\n\n");

            nina_conf.transport.api->send_async(&esp32, nina_send_buffer, DATA_BUFF_LEN, pi_task_callback(&nina_task, spi_cb,(void *)&trans_done));
            trans_done = 0;
        }       
    }
    pmsis_exit(0);
}

/**
 * System kickoff.
 */
int main(void)
{
    printf("\n\n\t *** GAP8 to NINA test ***\n\n");
    return pmsis_kickoff((void *) vMainTask);
}

and the Makefile:

APP              = test
APP_SRCS        += src/main.c
APP_INC         += include
APP_CFLAGS      += -O3 -g

RUNNER_CONFIG = $(CURDIR)/config.ini

PMSIS_OS = freertos

include $(GAP_SDK_HOME)/tools/rules/pmsis_rules.mk

while on the NINA side, the code is almost identical to this example, I have only changed the function _img_sendingtask to directly send the data over Wi-Fi when they are read, avoiding in this way all the JPEG processing:

/* img_sending_task function reduced */
static void img_sending_task(void *pvParameters) 
{
  spi_init();
  vTaskDelay(pdMS_TO_TICKS(2000));

  while (1)
  {
    int32_t datalength = spi_read_data(&spi_buffer, CMD_PACKET_SIZE);

    if (datalength > 0) 
    {
      if (wifi_is_socket_connected())
      {
        wifi_send_packet( (const char*) spi_buffer, CMD_PACKET_SIZE);
      }
    } 
  }
}

I have tested the _wifi_sendpacket function with some hardcoded values and it works. The problem seems to rely on the GAP8 side, because if I add a printf in the while loop, it sends some data to the NINA and I receive them via Wi-FI, but after 1 or 2 minutes it stops and doesn't work anymore. Instead, if I comment the printf, it sends nothing, so I think it's a timing issue, but I don't know if it is related to the use of FreeRTOS, or something wrong in my code implementation or NINA API usage.

I am using the docker containers to flash both GAP8 and the NINA provided in the AI-deck repo.

Thank you as always for your support!

Manuel

gwtsivasiva commented 2 years ago

Hi @Manucar ,

Sorry for this delay. Since the released version of bsp does not have wifi on FreeRTOS, I am guessing the changes concern the event tasks and their data fields? If done correctly, it should not be an issue. Now that FreeRTOS supports Ai-deck, the wifi support will be released too asap.

As per your current issue, since you are using event callbacks, you probably want the callback to do some action when called? If that is not the case you could replace the event callback with a blocking event.

      while( 1 )
      {
            //printf("\n\n\t *** while ***\n\n");
            pi_task_block(&nina_task);
            nina_conf.transport.api->send_async(&esp32, nina_send_buffer, DATA_BUFF_LEN, &nina_task);
            // Do some stuff if needed while waiting for EOT.
            pi_task_wait_on(&nina_task);
      }

Or if you need callback, you should make use of a second event task, this one blocking.

      static void spi_cb(void *arg)
      {
          (pi_task_t *) task = (pi_task_t *) arg;
          pi_task_push(task);
      }

      pi_task_t wait_task;
      while( 1 )
      {
            //printf("\n\n\t *** while ***\n\n");
            pi_task_block(&wait_task);
            pi_task_callback(&nina_task, spi_cb, (void *) &wait_task)
            nina_conf.transport.api->send_async(&esp32, nina_send_buffer, DATA_BUFF_LEN, &nina_task);
            // Do some stuff if needed while waiting for EOT.
            pi_task_wait_on(&wait_task);
      }

This way is better for performances and consumption, since CPU will be less solicited.

Could you try with one of the methods above? The issue may be coming from the scheduler, since the driver has been initially implemented for PulpOs, it may trigger issues with preemptive RTOS like FreeRTOS.

Best,

pladosz commented 1 year ago

Hi @Manucar I appreciate this is quiet an old issue, but I do wonder if you could share the rest of your code? I am trying to do similar thing to you for AI deck but I am stuck at the same point as your previous issue (#190 ).