sandeepmistry / arduino-nRF5

Arduino Core for Nordic Semiconductor nRF5 based boards
Other
873 stars 278 forks source link

BBC microbit v2 #432

Closed jhmaloney closed 3 years ago

jhmaloney commented 3 years ago

This pull request adds support for the BBC micro:bit v2, which is based on the nrRF2833. In addition to adding a new variant and a new entry in boards.txt, it also extends wiring-digital.c an the Wire library to handle pin numbers >31 (i.e. pins in the second GPIO port) since the micro:bit v2 uses some of those pins. It also adds a linker script for the nrRF2833.

The softdevice menu currently only provides "none" as an option because I'm not sure how to configure the soft device options for the nrRF2833. I'm hoping someone else will fill in those options. Or I can give it a shot as a separate PR.

A final note is that the board definition file sets the CPU frequency to 64 MHz (BBCmicrobitV2.build.f_cpu=64000000). That seems correct even though other nRF52 boards that run at 64 MHz have that entry set to 16 MHz.

These changes have been tested with both the Arduino IDE 1.8.13 and with PlatformIO.

jhmaloney commented 3 years ago

Fix: swapped SDA/SCL pins for external I2C

luqmaanb commented 3 years ago

Hi

Great work on this pull request. I've managed to use I2C successfully with SSD1306 but I can't get SPI to work? I'm using the IM01 bridge from XinaBox that allows for SD card operations. Its working perfectly on microbit 1 but freezes at SD card initialization on microbit 2. The example I'm using the one from Arduino

/*
  SD card test

  This example shows how use the utility libraries on which the'
  SD library is based in order to get info about your SD card.
  Very useful for testing a card when you're not sure whether its working or not.

  The circuit:
    SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - depends on your SD card shield or module.
        Pin 4 used here for consistency with other Arduino examples

  created  28 Mar 2011
  by Limor Fried
  modified 9 Apr 2012
  by Tom Igoe
*/
// include the SD library:
#include <SPI.h>
#include <SD.h>

//#include <xOD01.h>

//xOD01 OD01;

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN
const int chipSelect = 16;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
//Wire.begin();
//OD01.begin();
//OD01.clear();

  Serial.print("\nInitializing SD card...");

  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    while (1);
  }

  Serial.print("Clusters:          ");
  Serial.println(volume.clusterCount());
  Serial.print("Blocks x Cluster:  ");
  Serial.println(volume.blocksPerCluster());

  Serial.print("Total Blocks:      ");
  Serial.println(volume.blocksPerCluster() * volume.clusterCount());
  Serial.println();

  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("V type is:    FAT");
  Serial.println(volume.fatType(), DEC);

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)
  Serial.print("V size (Kb):  ");
  Serial.println(volumesize);
  Serial.print("V size (Mb):  ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("V size (Gb):  ");
  Serial.println((float)volumesize / 1024.0);

  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);

  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}

void loop(void) {
}

Have you successfully tested the SPI? I'd like to rule out an SPI issue.

jhmaloney commented 3 years ago

I haven't tested SPI and, in fact, Sandeep mentioned that there could be an issue in the declaration of Wire1. You could tried changing that to:

TwoWire Wire1(NRF_TWIM0, NRF_TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, PIN_WIRE1_SDA, PIN_WIRE1_SCL);

Note that this change may make it impossible to use Wire1 and Wire at the same time. Both those are needed because the V2 uses separate internal and external I2C buses.

A better solution might be to change the SPI library to use SPI2 when running on an nRF52. It looks like that that avoids the conflict with both TWI0 and TWI1. The nRF51 might be limited to a single Wire instance (i.e. Wire1 could be #ifdef-ed out except on nRF52's.) @Sandeep, does that make sense?

luqmaanb commented 3 years ago

I haven't tested SPI and, in fact, Sandeep mentioned that there could be an issue in the declaration of Wire1. You could tried changing that to:

TwoWire Wire1(NRF_TWIM0, NRF_TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, PIN_WIRE1_SDA, PIN_WIRE1_SCL);

Note that this change may make it impossible to use Wire1 and Wire at the same time. Both those are needed because the V2 uses separate internal and external I2C buses.

A better solution might be to change the SPI library to use SPI2 when running on an nRF52. It looks like that that avoids the conflict with both TWI0 and TWI1. The nRF51 might be limited to a single Wire instance (i.e. Wire1 could be #ifdef-ed out except on nRF52's.) @sandeep, does that make sense?

Thanks. Changing that line of code made the SPI work but as you said, the I2C stopped working. I did, however, have to add these few lines in the variant.h file:

static const uint8_t SS   = 16 ;
static const uint8_t MOSI = PIN_SPI_MOSI ;
static const uint8_t MISO = PIN_SPI_MISO ;
static const uint8_t SCK  = PIN_SPI_SCK ;

I'm looking into the spi/i2c conflict. Will post if I get anything working.

sandeepmistry commented 3 years ago

@luqmaanb @jhmaloney could you please try out PR https://github.com/sandeepmistry/arduino-nRF5/pull/439, I've updated the nRF MDK so it's easier to add support for the micro:bit v2 (based on @jhmaloney's initial changes).

sandeepmistry commented 3 years ago

Closing in favour of https://github.com/sandeepmistry/arduino-nRF5/pull/439.