sipeed / Maixduino

Arduino port on Maix board ( k210 )
https://maixduino.sipeed.com
Other
216 stars 96 forks source link

Using MD_PIN_MAP removes the ability to control K210 Chip IO Pins for SPI etc... #47

Open TheMindVirus opened 5 years ago

TheMindVirus commented 5 years ago

I have a project that requires advanced usage of the K210 IO pins on a Sipeed Maixduino board. However, the default digitalWrite, pinMode etc. methods use an array called MD_PIN_MAP for pin mapping. This is restrictive and doesn't allow full use of the K210 IO pins.

Provided that you know what you are doing, here is my fix:

void pinModeIO(uint8_t pin, uint8_t mode)
{
  fpioa_function_t function = (fpioa_function_t)(FUNC_GPIOHS0 + pin);
  fpioa_set_function(pin, function);
  gpiohs_set_drive_mode(pin, (gpio_drive_mode_t)mode);
}
#define digitalWriteIO(PIN, VALUE)   gpiohs_set_pin(PIN, (gpio_pin_value_t)VALUE)
#define digitalReadIO(PIN)           gpiohs_get_pin(PIN)

I am finding myself having to rewrite the SPI and UART library to accommodate this change too.

TheMindVirus commented 5 years ago

I have Serial working between the K210 and ESP32 using a custom class I wrote based on UARTClass: (Please note, to update the ESP32 firmware, the reset button must be held down during flashing)

Maix_UART.h

#ifndef MAIX_UART_H
#define MAIX_UART_H

class UART
{
public:
  UART(uint8_t rx = 6, uint8_t tx = 7,
       fpioa_function_t rx_func = FUNC_UART1_RX,
       fpioa_function_t tx_func = FUNC_UART1_TX,
       uart_bitwidth_t width = UART_BITWIDTH_8BIT,
       uart_stopbit_t stopbit = UART_STOP_1,
       uart_parity_t parity = UART_PARITY_NONE)
  {
    this->rx = rx;
    this->tx = tx;
    this->rx_func = rx_func;
    this->tx_func = tx_func;
    this->width = width;
    this->stopbit = stopbit;
    this->parity = parity;
  }

  void begin(uint32_t baud = 115200)
  {
    this->baud = baud;
    fpioa_set_function(rx, this->rx_func);
    fpioa_set_function(tx, this->tx_func);
    uart_init(this->handle);
    uart_configure(this->handle, this->baud, this->width, this->stopbit, this->parity);
    this->buffer = new RingBuffer();
    uart_set_receive_trigger(this->handle, UART_RECEIVE_FIFO_1);
    uart_irq_register(this->handle, UART_RECEIVE, this->receiveCB, this, 5);
    sysctl_enable_irq();
  }

  static int receiveCB(void* ctx)
  {
    char tmp = '\0';
    UART* uart = (UART*)ctx;
    while(uart_receive_data(uart->handle, &tmp, 1)) { uart->buffer->store_char(tmp); }
    return 0;
  }

  int available()
  {
    return this->buffer->available();
  }

  char read()
  {
    if(this->available()) { return this->buffer->read_char(); }
    return -1;
  }

  void print(char* data, int len = -1)
  {
    if(len < 0) len = strlen(data);
    for(int i = 0; i < len; ++i)
    {
      while(uart[this->handle]->LSR & (1u << 5)) { }
      uart[this->handle]->THR = data[i];
    }
  }

  void println(char* data, int len = -1)
  {
    char newline[] = "\n";
    this->print(data, len);
    this->print(newline, strlen(newline));
  }

private:
  uint32_t baud;
  uint8_t rx;
  uint8_t tx;
  fpioa_function_t rx_func;
  fpioa_function_t tx_func;
  uart_bitwidth_t width;
  uart_stopbit_t stopbit;
  uart_parity_t parity;
  uart_device_number_t handle;
  RingBuffer* buffer;
};

#endif//MAIX_UART_H

K210_Usage.ino

UART ESP32; //ESP32(6, 7);

void setup()
{
  ESP32.begin(115200);

  int nBytes = 0;
  char buffer[255] = "";
  char message[] = "Hello ESP32";
  while(1)
  {
    ESP32.println(message);
    nBytes = ESP32.available();
    if(nBytes > 0)
    {
      for(int i = 0; i < nBytes; ++i) { buffer[i] = (char)ESP32.read(); }
      buffer[nBytes] = '\0';
      Serial.println(buffer);
    }
    delay(1000);
  }
}

void loop() { }

ESP32_Usage.ino

void setup()
{
  Serial.begin(115200);

  int nBytes = 0;
  char buffer[255] = "";
  char message[] = "Hello ESP32";
  char response[] = "Hello K210";
  while(1)
  {
    nBytes = Serial.available();
    if(nBytes > 0)
    {
      for(int i = 0; i < nBytes; ++i) { buffer[i] = (char)Serial.read(); }
      buffer[nBytes] = '\0';
      Serial.print(buffer);
      if(strncmp(buffer, message, strlen(message)) == 0) { Serial.println(response); }
    }
    delay(500);
  }
}

void loop() { }
TheMindVirus commented 5 years ago

For printing floats, the print() method above may need to be modified to use sprintf() using preprocessor macros. This will make it more like the Arduino standard printer.