I am trying to implement dynamic address assignment on my arduino using an NRF24l01+, but I can't get a RHReliableDatagram initialized globally after my unit receives it's assigned address
This is what I have(which for some reason doesnt work:
manager = new RHReliableDatagram(driver, ID);
Error:
sketch_oct02b.ino: In function 'void setup()':
sketch_oct02b:47: error: no match for 'operator=' in 'manager = (((RHReliableDatagram*)operator new(267u)), (<anonymous>->RHReliableDatagram::RHReliableDatagram(((RHGenericDriver&)(& driver.RH_NRF24::<anonymous>.RHNRFSPIDriver::<anonymous>)), ((uint8_t)ID)), <anonymous>))'
C:\Users\****\Documents\HAS\HAS-mc\libraries\RadioHead/RHReliableDatagram.h:66: note: candidates are: RHReliableDatagram& RHReliableDatagram::operator=(const RHReliableDatagram&)
This is code that works, but I cant change the address during runtime.
RHReliableDatagram manager(driver, DHT1_ADDRESS);
A minimal reproduction of my problem here:
#include <RHReliableDatagram.h>
#include <RH_NRF24.h>
#include <SPI.h>
#include <DHT.h>
RH_NRF24 driver(8,10);
int ID = 255; //init ID, will be reassigned by server
RHReliableDatagram manager(driver,ID);//255 is the ID before init
void setup()
{
ID = 15;
manager = new RHReliableDatagram(driver, ID);//NOTE added this
//spi.setPins(13, 4, 3); //miso mosi sck
if (!manager.init()){
Serial.println("NRF failed to initialise");
digitalWrite(PIN_NRF_ERROR,HIGH);
} else {
Serial.println("NRF succesfully initialized");
}
}
void loop()
{
}
The documentation for the radio head library is here:
http://www.airspayce.com/mikem/arduino/RadioHead/classRHReliableDatagram.html
You need to assign the dynamic allocated object to the pointer of that object type, such as
type *p_var = new type(initializer)
In your code it should be remove
RHReliableDatagram manager(driver,ID);//255 is the ID before init
and change
manager = new RHReliableDatagram(driver, ID);//NOTE added this
to
RHReliableDatagram *manager = new RHReliableDatagram(driver, ID);//NOTE added this
Also you need to remember to use delete() to free the memory that the manager when it is no longer needed.
I am late but - there is a function to do that.
Use:
manager.setThisAddress(ID);
void RHDatagram::setThisAddress(uint8_t thisAddress)
{
_driver.setThisAddress(thisAddress);
// Use this address in the transmitted FROM header
setHeaderFrom(thisAddress);
_thisAddress = thisAddress;
}
Related
I’ve been recently getting into OS development (completely from scratch), and I’m stuck on an issue where plotting pixels to the screen does not seem to work at all.
For reference, I’m using EDK2 for the UEFI utilities and compiling my bootloader using its build system.
I obtain the framebuffer from the GOP handle after setting my wanted mode (which should be 1366x768, BGRA colour format), but writing any value to the framebuffer memory space seems to not translate anything to the screen. Here are the projects (bootloader and OS) for references:
* OS: https://github.com/kernel-dev/kernelOS
* Bootloader: https://github.com/kernel-dev/kernelOSBootloader
Furthermore, here are the relevant snippets of code that should work, but don’t:
* Function declarations: https://github.com/kernel-dev/kernelOS/blob/main/src/Kernel/Graphics/KernGraphics.c
* Calling the function for clearing the screen: https://github.com/kernel-dev/kernelOS/blob/main/src/Kernel/Kernel.c
Solved
The reason why it wasn't working is because I wasn't properly getting the passed down arguments in my kernel.
This is how it looked like:
// Entry point for kernel
VOID
KernMain (
IN EFI_RUNTIME_SERVICES *RT,
IN EFI_KERN_MEMORY_MAP *MemoryMap,
IN ACPI_DIFFERENTIATED_SYSTEM_DESCRIPTOR_TABLE *Dsdt,
IN KERN_FRAMEBUFFER *Framebuffer)
{
ScreenClearTerminal (Framebuffer);
//
// Should never reach here.
// Will be removed later.
//
while (TRUE) {};
}
However, the way I actually pass them down is like this:
//
// Prepare the arguments to be passed down.
//
LoaderBlock->MemoryMap = &MemoryMap;
LoaderBlock->Dsdt = Dsdt;
LoaderBlock->RT = SystemTable->RuntimeServices;
LoaderBlock->Framebuffer = FB;
//
// Exit boot services.
//
/* ... */
//
// Locate the EP function and call it with the arguments.
//
typedef void (__attribute__((ms_abi)) *EntryPointFunction) (LOADER_PARAMS *LP);
EntryPointFunction EntryPointPlaceholder = (EntryPointFunction) (BaseAddress + EntryPoint);
EntryPointPlaceholder (LoaderBlock);
It's contained inside of a struct. So the appropriate way to obtain them would be like this:
/**
A structure used to "contain" all
the parameters to be passed down
to the kernel's EP.
**/
typedef struct {
EFI_RUNTIME_SERVICES *RT; /// Pointer to the runtime services.
EFI_KERN_MEMORY_MAP *MemoryMap; /// Pointer to the EFI_KERN_MEMORY_MAP.
ACPI_DIFFERENTIATED_SYSTEM_DESCRIPTOR_TABLE **Dsdt; /// Pointer to the DSDT pointer.
KERN_FRAMEBUFFER *Framebuffer; /// Pointer to the KERN_FRAMEBUFFER.
} LOADER_PARAMS;
// Entry point for kernel
VOID
KernMain (
LOADER_PARAMS *LP)
{
ScreenClearTerminal (LP->Framebuffer);
//
// Should never reach here.
// Will be removed later.
//
while (TRUE) {};
}
or, alternatively keeping the old method, but alternating the way they're passed down:
//
// Locate the EP function and call it with the arguments.
//
typedef void (__attribute__((ms_abi)) *EntryPointFunction) (
EFI_RUNTIME_SERVICES *RT,
EFI_KERN_MEMORY_MAP *MemoryMap,
ACPI_DIFFERENTIATED_SYSTEM_DESCRIPTOR_TABLE **Dsdt,
KERN_FRAMEBUFFER *Framebuffer
);
EntryPointFunction EntryPointPlaceholder = (EntryPointFunction) (BaseAddress + EntryPoint);
EntryPointPlaceholder (
SystemTable->RuntimeServices,
&MemoryMap,
Dsdt,
FB);
Completely my bad lol.
Thank you to #user123 and #Dave S for helping me.
I have the following auto-generated (from HAL) pKeyAES array (there is also an initVectorAES that looks the same):
__ALIGN_BEGIN static const uint8_t pKeyAES[16] __ALIGN_END = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00};
Along with the init function such as:
void Hal_MX_init (void){
hcryp.Instance = AES;
hcryp.Init.DataType = CRYP_DATATYPE_8B;
hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT;
hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_CBC;
hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE;
hcryp.Init.pKey = (uint8_t *)pKeyAES;
hcryp.Init.pInitVect = (uint8_t *)pInitVectAES;
if (HAL_CRYP_Init(&hcryp) != HAL_OK)
{
Error_Handler();
}
}
Now I want to create a new function in this file generated by the HAL so that the "key" is always kept within the HAL. To do this I am thinking of using the pKeyAES to always keep the "key". However, I am not really sure on how to do this; for instace, if I want to create a new "set key" or "delete key" method, how would this look like when doing it within the HAL?
For instance, for "set key" I think it would be best to store it within the pKeyAES (having an in-param for getting the new key). And for "delete key" function, I would suspect you could "delete"/reset anything that is currently stored in pKeyAES array? However, I'm not entirely sure how to accomplish this code-wise.
Also, when doing "set-key" would I need to do something with the "initVector" that is provided as well, or just keep it as it is (currently holding the same value as the pKeyAES).
Any help, tips etc. Would be most helpful.
I can guess that I have to create a new init function for set key, such as "void setKey_init (){}" and add the same stuff from hcryp such as in the example code provided above; but where I have the new Key as a param input variable. hcryp.Init.pKey is a uint8_t pointer key; where I want my new key to be set. But my problem is how it would look code-wise to make it the most efficient when setting a new key here. I don't want to point to a key outside of my aes.c file (risky), but rather have a key sent in that I can add to the struct and init with the function.
If I understand correctly, it should be quite simple. Having a pointer to a new key (const uint8_t *pNewKeyAES), copy it to the pKeyAES storage and perform the initialization. In the following, if pNewKeyAESis NULL, the key is set to the all-zeroes key (corresponding to deleting the key):
#include <string.h>
#include <stdint.h>
// Discard `const` from pKeyAES to be able to modify it
__ALIGN_BEGIN static uint8_t pKeyAES[16] __ALIGN_END = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00};
void setKey_init (const uint8_t *pNewKeyAES)
{
if(pNewKeyAES != NULL)
{ // Use new key
memcpy(pKeyAES, pNewKeyAES, CRYP_KEYSIZE_128B);
}
else
{ // Delete key
memset(pKeyAES, 0, CRYP_KEYSIZE_128B);
}
Hal_MX_init(); // As defined in the question, may also copy contents here
}
I'm writing "threaded interpreter" using computed goto. How do I initialize address lookup table to be visible from different functions without additional runtime cost?
Label address is only visible at same function and static lookup table is initialized by compiler in data section without runtime cost at each call. But it's visible only in same function and I want to have another function to have access to it, for example to cache addresses and save lookups in main interpreter code. I can take pointer to this table and store it somewhere, but it will happen every time function is called, and it will get called frequently. Yes, it's just only one mov, but is there another way?
#include <stdio.h>
static void** table_ptr;
// how do i declare static variable and init it later once?
// Tried this. Generates runtime assigns at each call. Not unexpected
// static void** jumps_addr;
int main()
{
// labels are visible only inside the function
// generates runtime assigns at each call
// jumps_addr = (void* [10]){
// this initializes it in static data section, but name is only visible inside this function
static void* jumps_addr[10] = {
[1] = &&operation_print,
};
// want another way instead of this
table_ptr = jumps_addr;
// not optimize this
volatile int opcode = 1;
goto *jumps_addr[opcode];
return 0;
operation_print:;
printf("hello\n");
return 0;
}
void do_some_preprocessing_work(void){
// want access to jumps_addr table here
// without having to store it somewhere
// [do something with table_ptr]
// this is to prevent optimization to explore what compiler does on godbolt.org
// because it will optimize away table_ptr entirely if not used
volatile i = 1;
i += table_ptr[i];
//actual code here will store labbel addrs into opcode struct to save table lookup at runtime
}
The solution might sound unorthodox, but how about not to use any functions, but only goto.
Like so:
#include <stdio.h>
int main()
{
volatile int opcode;
static void* jumps_addr[10] = {
[0] = &&do_some_preprocessing_work,
[1] = &&operation_print
};
opcode = 0;
goto *jumps_addr[opcode];
return 1;
operation_print:
printf("hello\n");
return 0;
do_some_preprocessing_work:
printf("jumps_addr[%i]\n", ++opcode);
goto *jumps_addr[opcode];
return 1;
}
The definition to start a BLE scan is:
bool start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults), bool is_continue = false);
The second parameter seems to be the callback when a scan is complete, being somewhat new to this Im unsure how to define it.
fwiw Ive tried this:
void OnScanResults(BLEScanResults scanResults)
{ }
and used it like this:
scanResults = scan->start(60, OnScanResults, true);
but obvious to others, that didnt work.
Please help me decypher that signature
void (*scanCompleteCB)(BLEScanResults)
you need to add & to OnScanResults because:
void (*scanCompleteCB)(BLEScanResults)
is a pointer to a function which takes a BLEScanResults, returns nothing and is called scanCompleteCB
So your call should be:
scanResults = scan->start(60, &OnScanResults, true);
just as a pointer to a int points to the address of a int
int pointedTo;
int* ptr = &pointedTo;
I have a code that does OOP like Java.
I have separated the interface and the implementation in separate files names demo.h and demo.c.
demo.h
#ifndef DEMO_H
#define DEMO_H
typedef struct {
/*
This is the variable that will be set by setter method
and its value will be extracted by getter method.
This variable must not be directly accessible by the programmer.
*/
int num;
void (* setNum)(int); // This function will set the value of variable "num".
int (* getNum)(); // This function will return the value of variable "num".
} *Demo; // As objects in java are always called by reference.
Demo newDemo(); // This function will create an instance of class(struct here) Demo and return.
/* This is equivalent to:
Demo obj = new Demo();
int java.
I want my users to create instance of this class(struct here) like this:
Demo obj = newDemo();
here in this code.
*/
#endif
And the implementation:
demo.c
#include <stdlib.h>
#include "demo.h"
Demo demo; /* I have created a global variable so that it is accessible
in setNum and getNum functions. */
void setNum(int num) {
demo->num = num; // This is where the global demo is accessed.
}
int getNum(Demo obj) {
return demo->num; // This is where the global demo is accessed.
}
Demo newDemo() {
Demo obj; // This will be the returned object.
obj = (Demo)malloc(sizeof(*obj)); /* Allocating separate memory to
obj each time this function is called. */
/* Setting the function pointer. */
obj->setNum = setNum;
obj->getNum = getNum;
/* As obj is at different memory location every time this function is called,
I am assigning that new location the the global demo variable. So that each variable
of the Demo class(struct here) must have a different object at different memory
location. */
demo = obj;
return obj; // Finally returning the object.
}
This is how I have implemented the main function:
main.c
#include "demo.h"
#include <stdio.h>
int main() {
void displayData(Demo);
Demo obj1 = newDemo();
Demo obj2 = newDemo();
Demo obj3 = newDemo();
obj1->setNum(5);
obj2->setNum(4);
obj3->setNum(12);
displayData(obj1);
displayData(obj2);
displayData(obj3);
return 0;
}
void displayData(Demo obj) {
int num = obj->getNum();
fprintf(stdout, "%d\n", num);
}
On compilation and execution on my mac book pro:
> gcc -c demo.c
> gcc main.c demo.o -o Demo
> ./Demo
The output is:
12
12
12
But the desired output is:
5
4
12
What am I doing wrong?
Please help.
I don't want my users to pass the struct pointer as an argument as:
Demo obj = newDemo();
obj->setName(obj, "Aditya R.Singh"); /* Creating the program this way was successful as my
header file had the declaration as:
typedef struct demo {
int num;
void (* setNum)(struct demo, int); // This is what I don't desire.
void (* getNum)(struct demo); // This is what I don't desire.
} *Demo;
I want to keep it like the way it is in my current
demo.h*/
/* I don't want to pass obj as an argument. All I want to do this is this way. */
obj->setName("Aditya R.Singh");
Is there any way possible to do this and get the desired output?
Please help, thanks!
I have absolutely no idea of c++, but in your code, I think, demo = obj; is the problem. demo is global, right? It will get overwritten with evety call to newDemo().
Side effect : Memory leak.