Rust! I'm needing a push by one of you smart folks. TIA

Hi there and what a great resource when you have need for a little help.

I'm using Xiao nRf52840 BLE Sense device and Arduino IDE 2.02
I'm reading the NRF_FICR->DEVICEADDR[0] register and getting the upper and lower 8ea. Bytes of hex containing the ChipID and MAC address, Prints out ok.
some code below briefly, I have two of these devices btw.

void loop()
{
  Serial.print( "Device ID 0: " );
  Serial.println( NRF_FICR->DEVICEID[0], HEX );
  Serial.print( "Device ID 1: " );
  Serial.println( NRF_FICR->DEVICEID[1], HEX );

  Serial.print( "Device Address 0: " );
  Serial.println( NRF_FICR->DEVICEADDR[0], HEX );
  Serial.print( "Device Address 1: " );
  Serial.println( NRF_FICR->DEVICEADDR[1], HEX );

  delay ( 5000 );
 }

I get is this;
Output from one unit
Device ID 0: F4073F21
Device ID 1: EFC6E2E6
Device Address 0: 6378CF67
Device Address 1: 53BB210E

which is Awesome... I know it's good as here is the BLE scan and IDE board info pic.
so everything is true to the data sheet of the FICR.

I want to save the HEX contents of both ADDR[1] and ADDR[0] to a variable DEVSN and manipulate the resulting info to this;

DEVID: 53BB
MAC: 21:0E:63:78:CF:67

that's pretty much it, idunno if it's the HEX part or save it as a string maybe first. LOST in Space :wink:

My end game is to add the DEVID to the BLE advertised NO NAME BLE(see PIC) so I can discern one unit from another when scanning and connecting. If that make sense.
TIA for any pertinent suggestions.
GL :slight_smile:
PJ

Seems all the info is in whatever is pointed at by NRF_FICR

What’s the type of this pointer ?

You likely have a structure there, so you could either just keep using the pointer or make a copy of the structure

Thanks for the reply JML and your question to my question gave me some incite. The Device ID is an array read from the Factory information configuration registers (FICR ) are pre-programmed in factory. the mac address is part of it and YES I can just continue to use the copied data in those locations.
I'm closer to my needed result, the search and learning continues...I want to do something like this; below, but RUST with arrays and calling the function that returns a value...YOI!!
:-o also, more reading.

 void get_mac_address(uint8_t mac_address[6]) {
	unsigned int device_addr_0 = NRF_FICR->DEVICEADDR[0];
	unsigned int device_addr_1 = NRF_FICR->DEVICEADDR[1];
	const uint8_t* part_0 = reinterpret_cast<const uint8_t*>(&device_addr_0);
	const uint8_t* part_1 = reinterpret_cast<const uint8_t*>(&device_addr_1);
	mac_address[0] = part_1[1];
	mac_address[1] = part_1[0];
	mac_address[2] = part_0[3];
	mac_address[3] = part_0[2];
	mac_address[4] = part_0[1];
	mac_address[5] = part_0[0];
}

:wink:

Here is my Code rendition that indeed uses the existing structure, Thanks JML

#include <Arduino.h>
#include <Wire.h>
#include <U8x8lib.h>

//Create a instance of class
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* clock=*/ PIN_WIRE_SCL, /* data=*/ PIN_WIRE_SDA, /* reset=*/ U8X8_PIN_NONE);
// OLEDs without Reset of the Display
const int ledPin = LED_BUILTIN;
int BuzzerPin = A3;                 //A3 , P0.29 PIN 4
int buzzer = BuzzerPin;
int Vadc = analogRead(P0_31);
uint8_t mac_address[6];

void setup(){
 Serial.begin( 9600 );
 delay(2000);                       //relax...Get Ready for serial port
 Serial.println("Processor came out of reset.\n");
 startsound();
 setBatt();
 initdisplay();
 setupblink();  
 }
//
void loop(){
char buff[6];
get_id_address(mac_address);
sprintf(buff, "\nXiao Unit: %02lX%02lX\n",
          mac_address[0],mac_address[1]);
  Serial.print(buff);
  u8x8.clearDisplay();
  u8x8.setCursor(0,-1);
  u8x8.print(buff);
  u8x8.setCursor(6,6);
delay(2000);

char buffer[80];
char bufferu8[80];
get_mac_address(mac_address);
sprintf(buffer, "Xiao MAC: %02lX:%02lX:%02lX:%02lX:%02lX:%02lX\n",
          mac_address[0],mac_address[1],mac_address[2],mac_address[3],mac_address[4],mac_address[5] ,mac_address[6]);
  Serial.print(buffer);
  sprintf(bufferu8, "Xiao MAC: \n%02lX%02lX%02lX%02lX%02lX%02lX\n",
          mac_address[0],mac_address[1],mac_address[2],mac_address[3],mac_address[4],mac_address[5] ,mac_address[6]);
  u8x8.setCursor(0,3);
  u8x8.print(bufferu8);
delay (2000);
getBattery();
delay (2000);

}

// 
//************************functions **********************
//
void get_id_address(uint8_t mac_address[6]) {
	unsigned int device_addr_0 = NRF_FICR->DEVICEADDR[0];
	unsigned int device_addr_1 = NRF_FICR->DEVICEADDR[1];
	const uint8_t* part_0 = reinterpret_cast<const uint8_t*>(&device_addr_0);
	const uint8_t* part_1 = reinterpret_cast<const uint8_t*>(&device_addr_1);
	mac_address[0] = part_1[3];   //changed from get_mac_address elements 0,1
	mac_address[1] = part_1[2];   //
}

void setBatt(){
  pinMode(P0_31, INPUT);    //Battery Voltage monitoring pin
  pinMode(P0_13, OUTPUT);   //Charge Current setting pin
  pinMode(P0_14, OUTPUT);   //Enable Battery Voltage monitoring pin
  digitalWrite(P0_13, LOW); //Charge Current 100mA   
  digitalWrite(P0_14, LOW); //Enable
  analogReference(AR_INTERNAL2V4);  //Vref=2.4V
  analogReadResolution(12);
}

void getBattery(){
  int Vadc = analogRead(P0_31);
  float Vbatt = ((510e3 + 1000e3) / 510e3) * 2.4 * Vadc / 4096;
  Serial.print("Battery Level "); 
  Serial.println( Vbatt, 3); 
  digitalWrite(LED_GREEN, HIGH);
  u8x8.clearDisplay();
  u8x8.setCursor(0,2);
  u8x8.print("Battery Monitor");
  u8x8.setCursor(6,6);
  u8x8.print(Vbatt, 3);
}

void get_mac_address(uint8_t mac_address[6]) {
	unsigned int device_addr_0 = NRF_FICR->DEVICEADDR[0];
	unsigned int device_addr_1 = NRF_FICR->DEVICEADDR[1];
	const uint8_t* part_0 = reinterpret_cast<const uint8_t*>(&device_addr_0);
	const uint8_t* part_1 = reinterpret_cast<const uint8_t*>(&device_addr_1);
	mac_address[0] = part_1[1];
	mac_address[1] = part_1[0];
	mac_address[2] = part_0[3];
	mac_address[3] = part_0[2];
	mac_address[4] = part_0[1];
	mac_address[5] = part_0[0];
}

void setupblink(){
  setLedRGB(false, false, true);  // set Blue LED 
    delay(1000);
    setLedRGB(false, true, false);  // Red
    delay(1000);
    setLedRGB(true, false, false);  // Green
    delay(1000);
    setLedRGB(false, false, false);  // OFF
}   

void initdisplay() {
 pinMode(LEDR, OUTPUT);         // initialize the LED pin as an output:
 pinMode(LEDG, OUTPUT);         // initialize the LED pin as an output:
 pinMode(LEDB, OUTPUT);
 pinMode(LED_BUILTIN, OUTPUT);      // initialize the LED pin as an output:
  u8x8.begin();
    u8x8.setFlipMode(1);   // set number from 1 to 3, the screen word will rotary 180
    u8x8.setFont(u8x8_font_8x13B_1x2_r);
    u8x8.clearDisplay();
    u8x8.setCursor(0, 0);
    u8x8.print("Power ON ");
}

void startsound() {
  tone (buzzer, 890);
    delay (220);
    noTone(buzzer);
    delay (20);
    tone (buzzer, 800);
    delay (220);
    noTone(buzzer);
    delay (20);
    tone (buzzer, 800);
    delay (220);
    noTone(buzzer);
    delay (20);
    tone (buzzer, 990);
    delay (420);
    noTone(buzzer);
    delay (20);
}

void setLedRGB(bool red, bool green, bool blue) {
   if (!red) { digitalWrite(LEDR, HIGH); } else { digitalWrite(LEDR, LOW); }
   if (!green) { digitalWrite(LEDG, HIGH); } else { digitalWrite(LEDG, LOW); }
   if (!blue) { digitalWrite(LEDB, HIGH); } else { digitalWrite(LEDB, LOW); }
}

Serial out put as well as the 128X64 display is AWESOME

#1
Processor came out of reset.
Xiao Unit: F529
Xiao MAC: BC:40:B1:F8:B3:4E
Battery Level 4.084

#2
Processor came out of reset.
Xiao Unit: 53BB
Xiao MAC: 21:0E:63:78:CF:67
Battery Level 4.065

I'll next use the Unit # in the BLE local_name, so when advertising I'll know who is who...
GL:-)


thx for posting back your code and pictures !

when you do

void get_mac_address(uint8_t mac_address[6]) {
  unsigned int device_addr_0 = NRF_FICR->DEVICEADDR[0];
  unsigned int device_addr_1 = NRF_FICR->DEVICEADDR[1];
  const uint8_t* part_0 = reinterpret_cast<const uint8_t*>(&device_addr_0);
  const uint8_t* part_1 = reinterpret_cast<const uint8_t*>(&device_addr_1);
  mac_address[0] = part_1[1];
  mac_address[1] = part_1[0];
  mac_address[2] = part_0[3];
  mac_address[3] = part_0[2];
  mac_address[4] = part_0[1];
  mac_address[5] = part_0[0];
}

you are reordering the bytes. Our compiler is little endian and the nRF52840 is also little endian

so you might be creating a weird Mac address buffer but you reverse it again when you print so it all works.
you could have kept the bytes in the same order and use 2 memcpy() instructions to fill up your buffer rather than messing around with type changes etc :slight_smile:


just for documentation for others who would wonder what's going on there:

The hardware configuration in the IDE defines the NRF_FICR pointer to the FICR (Factory information configuration registers)

This pointer's is defined in this library (based on the type of chip, your Xiao nRf52840 BLE Sense uses an nRF52840 so recognised as an NRF52_SERIES chip)

in the file nrf52.h you'll see the NRF_FICR_Type type definition

and the info is described in the nRF documentation

Overview Register Offset Description
CODEPAGESIZE 0x010 Code memory page size
CODESIZE 0x014 Code memory size
DEVICEID[0] 0x060 Device identifier
DEVICEID[1] 0x064 Device identifier
ER[0] 0x080 Encryption Root, word 0
ER[1] 0x084 Encryption Root, word 1
ER[2] 0x088 Encryption Root, word 2
ER[3] 0x08C Encryption Root, word 3
IR[0] 0x090 Identity Root, word 0
IR[1] 0x094 Identity Root, word 1
IR[2] 0x098 Identity Root, word 2
IR[3] 0x09C Identity Root, word 3
DEVICEADDRTYPE 0x0A0 Device address type
DEVICEADDR[0] 0x0A4 Device address 0
DEVICEADDR[1] 0x0A8 Device address 1
INFO.PART 0x100 Part code
INFO.VARIANT 0x104 Part Variant, Hardware version and Production configuration
INFO.PACKAGE 0x108 Package option
INFO.RAM 0x10C RAM variant
INFO.FLASH 0x110 Flash variant
0x114 Reserved
0x118 Reserved
0x11C Reserved
TEMP.A0 0x404 Slope definition A0.
TEMP.A1 0x408 Slope definition A1.
TEMP.A2 0x40C Slope definition A2.
TEMP.A3 0x410 Slope definition A3.
TEMP.A4 0x414 Slope definition A4.
TEMP.A5 0x418 Slope definition A5.
TEMP.B0 0x41C y-intercept B0.
TEMP.B1 0x420 y-intercept B1.
TEMP.B2 0x424 y-intercept B2.
TEMP.B3 0x428 y-intercept B3.
TEMP.B4 0x42C y-intercept B4.
TEMP.B5 0x430 y-intercept B5.
TEMP.T0 0x434 Segment end T0.
TEMP.T1 0x438 Segment end T1.
TEMP.T2 0x43C Segment end T2.
TEMP.T3 0x440 Segment end T3.
TEMP.T4 0x444 Segment end T4.
NFC.TAGHEADER0 0x450 Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST.
NFC.TAGHEADER1 0x454 Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST.
NFC.TAGHEADER2 0x458 Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST.
NFC.TAGHEADER3 0x45C Default header for NFC Tag. Software can read these values to populate NFCID1_3RD_LAST, NFCID1_2ND_LAST and NFCID1_LAST.

that's where you'll read that

DEVICEADDR[0] contains the least significant bits of the device address. DEVICEADDR[1] contains the most significant bits of the device address. Only bits [15:0] of DEVICEADDR[1] are used

and so to build the full Mac address you need the 2 LSB from DEVICEADDR[1] and the 4 bytes from DEVICEADDR[0]

Thank you, Excellent ADD...
You probably got GIGA LOC's dev time in :owl:. or you're an Instructor...
You make this stuff more fun than work.
GL :slight_smile:

I’m just an old guy - so seen a lot :slight_smile: