Simulink Legacy Code Tool - custom Arduino servo write block problem - matlab

I'm trying to create my own servo.write block in Simulink for Arduino DUE deployment (and External Mode). Before you ask why if there is one available inside the Simulink Arduino Support Package, generally my final goal is to create a block that will use Arduino servo.writeMicroseconds function (there is no out of the box block for this one) but first i want to try with something simple to debug to see if i can get it to work....
I've been using this guide (https://www.mathworks.com/matlabcentral/fileexchange/39354-device-drivers) and one of working examples in there as a template and started modifying it (originally it implemented Digital Output driver). I took the LCT approach.
The the original digitalio_arduino.cpp/h files from the guide (example with digital read/out) were the files I modified as they were working without any issues out-of-the-box. Step by step i made following modifications:
Remove DIO read (leave only write) from CPP and H files
Change StartFcnSpec to digitalIOSetup and make changes in H file so port is always in OUTPUT mode
Include Servo.h library within CPP file and create Servo object
Up to this point, all edits went fine, no compile errors, all header files were detected by Simulink and diode kept blinking as it should so the code actually worked (i ran it in External Mode).
But as soon as i made the final modification and replaced pinMode() with myservo.attach() and digitalWrite() with myservo.write() (of course i changed the data type in writeDigitalPin function from boolean to uint8_T) the code, despite compiling and building without any issue didn't work at all. Specified servo port was completely dead, as it even wasn't initialised. Changing value on S-Function input didn't yield any results.
Of course If i replaced custom block with built in Servo Write block from Hardware Support Package, everything worked fine so its not hardware issue.
I'm completely out of ideas what could be wrong, especially that there are no errors so not even a hint where to look.
Here is the LCT *.m script used for generating S-Function:
def = legacy_code('initialize');
def.SFunctionName = 'dout_sfun';
def.OutputFcnSpec = 'void NO_OP(uint8 p1, uint8 u1)';
def.StartFcnSpec = 'void NO_OP(uint8 p1)';
legacy_code('sfcn_cmex_generate', def);
legacy_code('compile', def, '-DNO_OP=//')
def.SourceFiles = {fullfile(pwd,'..','src','digitalio_arduino.cpp')};
def.HeaderFiles = {'digitalio_arduino.h'};
def.IncPaths = {fullfile(pwd,'..','src'), 'C:\ProgramData\MATLAB\SupportPackages\R2021b\aIDE\libraries\Servo\src'};
def.OutputFcnSpec = 'void writeDigitalPin(uint8 p1, uint8 u1)';
def.StartFcnSpec = 'void digitalIOSetup(uint8 p1)';
legacy_code('sfcn_cmex_generate', def);
legacy_code('sfcn_tlc_generate', def);
legacy_code('rtwmakecfg_generate',def);
legacy_code('slblock_generate',def);
Here is digitalio_arduino.CPP file
#include <Arduino.h>
#include <Servo.h>
#include "digitalio_arduino.h"
Servo myservo;
// Digital I/O initialization
extern "C" void digitalIOSetup(uint8_T pin)
{
//pinMode(pin, OUTPUT);
myservo.attach(pin);
}
// Write a logic value to pin
extern "C" void writeDigitalPin(uint8_T pin, uint8_T val)
{
//digitalWrite(pin, val);
myservo.write(val);
}
// [EOF]
And here is digitalio_arduino.H file
#ifndef _DIGITALIO_ARDUINO_H_
#define _DIGITALIO_ARDUINO_H_
#include "rtwtypes.h"
#ifdef __cplusplus
extern "C" {
#endif
void digitalIOSetup(uint8_T pin);
void writeDigitalPin(uint8_T pin, uint8_T val);
#ifdef __cplusplus
}
#endif
#endif //_DIGITALIO_ARDUINO_H_
As I mentioned I've been using a working example as a reference. So I've modified it step by step to see if maybe there is a point when suddenly some error comes up but everything compiles yet does not work :/
I was wondering maybe if there is an issue with the Servo.h library or the Servo object and did some tinkering with these, like i removed Servo myservo; line of code to see if anything happens and just like expected, i started receiving errors that Servo is not defined. If I did not include Servo.h at all or forget to add IncPath to Servo.h as before compile errors about Servo not being supported symbol or not being able to find Servo.h library - so actually the code seems to be "working" in a way, it seems to have everything it needs to work :/
I also looked at the MathWorks implementation of Servo Write block, the MWServoReadWrite to see how Arduino API is being used and no surprise, it's being used in the same way as I've been trying to. They include Servo.h, they are using servo.attach() and servo.write() to control the servo port. And that's it. Yet for them it works, for me does not :/
When I inspect generated C code that runs on Arduino (with my custom S-Function block in it), it seems that all the functions are placed exactly where they are supposed to be, they receive correct arguments. I expected at least that I'll find a hint in there, i.e. missing code or anything else.

Related

ARM Eclipse debugging code in the RAM. Is it possible to see the source code`

I have a problem when try to debug the code which is copied to the SRAM and executed from there.
The code is overwriting the data - but it is done only during the system update. The sections where code is placed are correctly defined in the linker script file and the debuger correctly see the addresses. But when I step into the function (and the code in RAM is the correct one) it does not connect the source files with the code executed in the memory.
Do you know how can it be done. Debugging C code on the assembler level is not something which makes me happy :)
Any help appreciated.
The problem is a bit silly. When you call RAM function from the FLASH (the first call has to be done this way) it has to be done by the veneer. It was messing up the debugger. But having own calling macro (because of the distance it has to be done via the pointer) everything works fine
example calling macro.
#define RAMFCALL(func, ...) {unsigned (* volatile fptr)() = (unsigned (* volatile)())func; fptr(__VA_ARGS__);}

STM32H7 - IAR Placing Local Variables into 'Reserved Memory' (0x1FF20000 - 0x1FFFFFFF)

I started a new project using an STM32H7, currently using IAR EWARM V8, used the STM32CUBEMX to generate the configuration code, and get an initial project going.
I worked through a couple of the CUBEMX eval projects to get some hardware verified and working, and am able to step through code fine.
But there is something odd going on, in particular with variables if you assign them as local vars within a function, somehow IAR is placing them into the 'System Reserved' memory range...
ie within 0x1FF20000 - 0x1FFFFFFF
For example... the project example 'FMC_NOR' that STM provides, is test code for testing our a NOR flash, etc..
they created these two small arrays as globals vars just at the top of the main.c file.
(buffer_size is 0x1000)
uint16_t aTxBuffer[BUFFER_SIZE] = {0};
uint16_t aRxBuffer[BUFFER_SIZE] = {0};
When in the global space, they are allocated in the DTCM region (0x2000:0000)
When moved as local vars, they then become allocated into the 'reserved space'...
What happens is, when IAR encounters any arrays like this, the processor faults with an 'imprecise data access' hardware fault.
This same error occurs with code to initialize the JPEG module, as it attempts to load the arrays of Huffman tables, etc...
When using TrueStudio this problem does not occur... CubeMX auto-generates the linker files for whichever compiler you are using.
I didn't specifically see anything in the linker files pointing to the reserved memory address.
So not sure what could be going on? I'm new to using this processor, so I'm just starting to understand it's memory mapping.
Thanks for any help or suggestions, I'd like to get IAR figured out, as so far I like it a bit over TrueStudio.
I solved my own question... so no longer need help on this...
This is in the 'stm32h743xx_flash.icf' generated by STM CUBEMX for the STM32H7...
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x400;
define symbol __ICFEDIT_size_heap__ = 0x200;
/**** End of ICF editor section. ###ICF###*/
Bumped the 'size_cstack' up to 2k (0x800) and everything is fine...

stm32f4 HardFault_Handler - need debugging advice

I'm working on a project based on the stm32f4discovery board using IAR Embedded Workbench (though I'm very close to the 32kb limit on the free version so I'll have to find something else soon). This is a learning project for me and so far I've been able to solve most of my issues with a few google searches and a lot of trial and error. But this is the first time I've encountered a run-time error that doesn't appear to be caused by a problem with my logic and I'm pretty stuck. Any general debugging strategy advice is welcome.
So here's what happens. I have an interrupt on a button; each time the button is pressed, the callback function runs my void cal_acc(uint16_t* data) function defined in stm32f4xx_it.c. This function gathers some data, and on the 6th press, it calls my void gn(float32_t* data, float32_t* beta) function. Eventually, two functions are called, gn_resids and gn_jacobian. The functions are very similar in structure. Both take in 3 pointers to 3 arrays of floats and then modify the values of the first array based on the second two. Unfortunately, when the second function gn_jacobian exits, I get the HardFault.
Please look at the link (code structure) for a picture showing how the program runs up to the fault.
Thank you very much! I appreciate any advice or guidance you can give me,
-Ben
Extra info that might be helpful below:
Running in debug mode, I can step into the function and run through all the lines click by click and it's OK. But as soon as I run the last line and it should exit and move on to the next line in the function where it was called, it crashes. I have also tried rearranging the order of the calls around this function and it is always this one that crashes.
I had been getting a similar crash on the first function gn_resids when one of the input pointers pointed to an array that was not defined as "static". But now all the arrays are static and I'm quite confused - especially since I can't tell what is different between the gn_resids function that works and the gn_jacobian function that does not work.
acc1beta is declared as a float array at the beginning of main.c and then also as extern float32_t acc1beta[6] at the top of stm32f4xx_it.c. I want it as a global variable; there is probably a better way to do this, but it's been working so far with many other variables defined in the same way.
Here's a screenshot of what I see when it crashes during debug (after I pause the session) IAR view at crash
EDIT: I changed the code of gn_step to look like this for a test so that it just runs gn_resids twice and it crashes as soon as it gets to the second call - I can't even step into it. gn_jacobian is not the problem.
void gn_step(float32_t* data, float32_t* beta) {
static float32_t resids[120];
gn_resids(resids, data, beta);
arm_matrix_instance_f32 R;
arm_mat_init_f32(&R, 120, 1, resids);
// static float32_t J_f32[720];
// gn_jacobian(J_f32, data, beta);
static float32_t J_f32[120];
gn_resids(J_f32, data, beta);
arm_matrix_instance_f32 J;
arm_mat_init_f32(&J, 120, 1, J_f32);
Hardfaults on Cortex M devices can be generated by various error conditions, for example:
Access of data outside valid memory
Invalid instructions
Division by zero
It is possible to gather information about the source of the hardfault by looking into some processor registers. IAR provides a debugger macro that helps to automate that process. It can be found in the IAR installation directory arm\config\debugger\ARM\vector_catch.mac. Please refer to this IAR Technical Note on Debugging Hardfaults for details on using this macro.
Depending on the type of the hardfault that occurs in your program you should try to narrow down the root cause within the debugger.

LibOpenCM3 vector table is all blocking-handler

The answer to this question here
Libopencm3 interrupt table on STM32F4
explains the whole mechanism nicely but what I get is whole vector table filled with blocking handlers.
I know that because I see it in debugger (apart from the whole thing not working): disassembly screenshot showing vector table.
It is as though linker simply ignores my nicely defined interrupt handler function(s), e.g.:
void sys_tick_handler(void)
{
...
}
void tim1_up_isr(void)
{
...
}
I am using EmBitz IDE and have followed this tutorial here to get libopencm3 to work (and it does work except for this issue).
I have checked the function names n-fold and have tried several online examples including those from the libopencm3-examples project.
Everything compiles without a glitch and loads into the target board (STM32F103C8) and runs fine - except no ISRs get invoked (I do get interrupt(s) but they get stuck in blocking handlers).
Does anyone have an idea why is this happening?
It looks like linking with standard vector table (from ST's SPL or HAL).
To check this, try to rename your sys_tick_handler() to SysTick_Handler() and
tim1_up_isr() to TIM1_UP_IRQHandler().
If it works, find file with this SysTick_Handler and TIM1_UP_IRQHandler (I think, that will be startup*.s) and delete it from your project.

Implementing SPI library in Arduino (how do classes work?)

I am currently trying to self learn Arduino/C programming/Assembly. I am working on a project which requires a lot of data collection, and by research I discovered a chip called the "23K256" from Microchip (see here: http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en539039). Moreover, I have also discovered that an Arduino library taking advantage of this chip exists (see here: http://playground.arduino.cc/Main/SpiRAM). I downloaded the "spiRAM3a.zip" file, which I believe is the one most up-to-date. Note that I have only recently downloaded the Arduino software and thus have the latest version installed (I believe it's 1.0.6). Also note that I'm using Arduino Uno, although I will eventually need to use Arduino Mega (I just want this working on ANYTHING at this point). With this library is some code that exemplifies its use to read and write to the 23K256 (the file name is "SpiRAM_Example" included in the package I downloaded), effectively increasing the SRAM on Arduino available. Here is the actual, exact code:
#include <SPI.h>
#include <SpiRAM.h>
#define SS_PIN 10
byte clock = 0;
SpiRAM SpiRam(0, SS_PIN);
void setup() {
Serial.begin(9600);
}
void loop()
{
char data_to_chip[17] = "Testing 90123456";
char data_from_chip[17] = " ";
int i = 0;
// Write some data to RAM
SpiRam.write_stream(0, data_to_chip, 16);
delay(100);
// Read it back to a different buffer
SpiRam.read_stream(0, data_from_chip, 16);
// Write it to the serial port
for (i = 0; i < 16; i++) {
Serial.print(data_from_chip[i]);
}
Serial.print("\n");
delay(1000); // wait for a second
}
My problem is that when I complie the code, to test my confguration and try to learn its use, I surprisingly get an error. This is what I get:
SpiRAM_Example:7: error: 'SpiRAM' does not name a type
SpiRAM_Example.ino: In function 'void loop()':
SpiRAM_Example:20: 'SpiRAM' was not declared in this scope
So it's basically telling me that there's something wrong with the SpiRAM SpiRam(0, SS_PIN);line of code. My question is, why? Am I misunderstanding something very fundamental about how classes work? I feel like I must not be doing something because I highly doubt an incorrect piece of code would be published on Arduino's website. How can I get this code to compile, or at least be able to simply use this library? Should I post the code for the library itself ("SpiRAM.h"), which was included in the package I downloaded?
I would really appreciate any help I can get, and sincerely apologize if this is a really dumb question. I think this is the first I've worked with classes.
Did you download Attach:spiRAM3a.zip or the original? I installed this and your code. It complies on the IDE 1.05