Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STM32F4 support #218

Open
bernhard-thiele opened this issue Jun 20, 2017 · 22 comments
Open

STM32F4 support #218

bernhard-thiele opened this issue Jun 20, 2017 · 22 comments
Milestone

Comments

@bernhard-thiele
Copy link
Collaborator

PR #216 from @it-cosmos provided support for STM32F4 which I merged into an STM32F4-feature branch (ae66aef).

This ticket shall serve as a point for discussing this feature with the aim to finally merge the feature into the master branch (probably also interesting for @sjoelund who provided the AVR support in #170).

@it-cosmos
Copy link
Contributor

Can the makefile for compiling and creationg the binaries in Modelica_DeviceDrivers/EmbeddedTargets/STM32F4/Examples/STM32F4_Discovery/Blink/Makefile remain on this location?
Here also the blink_main.mos is checked in in this directory. Is this in line with the guide lines?
with the Makefile a Debug directory is created with all object code. Should the location be changed?

@bernhard-thiele
Copy link
Collaborator Author

I just looked a bit more into the code. You moved the third party code into Modelica_DeviceDrivers/3rdParty/STM, however the designated folder for third party code is Modelica_DeviceDrivers/Resources/thirdParty/. Please move the STM code below that directory.

If you have a look into the Resources/thirdParty folder, you can see that I listed the third party code in the Readme.txt. It's important to keep track of the licenses used for the thirdParty code so that the library can be used and shipped safely with (commercial) products. Maybe this could be even done a bit more clear than it is now.

Conventionally, all non Modelica files in a Modelica library are kept below the Resources directory.
Hence, also the blink_main.mos and the Makefile should go there. I should play with it myself to get a feeling of what works best, but the mos script should probably go below a folder Resources/Scripts/OpenModelica, e.g., Resources/Scripts/OpenModelica/EmbeddedTargets/STM32F4/Examples/STM32F_Discovery/ so that the location reflects the concerned model. The Makefile could go into the same directory as the mos file.

Notice that you can easily reference files in the resources directory from the documentation by a construct similar to <a href="modelica://Modelica_DeviceDrivers/Resources/Scripts/MyFile.xxx">MyFile</a>. This could be useful to reference from the documentation to the needed scripts or makefiles.

I maybe would rather create a directory named build instead of Debug. However, since the Makefile actually creates debug object files the name debug fits, too. I have no strong opinion on that.

@it-cosmos
Copy link
Contributor

  • I will move STM from 3rdParty to Resources/thirdParty.
  • The better place for mos and makefileI for the Blink Example I suggest Resources/Scripts/OpenModelica/EmbeddedTargets/STM32F4/Examples/STM32F_Discovery/Blink, since other examples in future will have different make- and mos files

@bernhard-thiele
Copy link
Collaborator Author

Yes, sounds good.

@it-cosmos
Copy link
Contributor

Shall we add the STMCube32F4 HAL interface into the thirdparty directory? I see no conflict in the license:
http://www.st.com/content/ccc/resource/legal/legal_agreement/license_agreement/de/fc/f7/32/a0/8b/4f/db/ultimate-liberty-v2.txt/files/ultimate-liberty-v2.txt/jcr:content/translations/en.ultimate-liberty-v2.txt
The size is quite big, so it could be provided as zip file.

@bernhard-thiele
Copy link
Collaborator Author

Well, the license seems okay. However, the zip file has almost 400MB and having a link to it in the documentation (as you currently have) seems to be a good way to handle it. It should not go into the thirdparty directory.

@it-cosmos
Copy link
Contributor

Ok, then only work left is to update the "README" file in the thirdParty folder.

Onother question:
I have a look onto the GPIO_EXTI example provided in the STM32F4Cube HAL. I would like to provide this in modelica. In this example the user interrupt is used triggered by the blue user button on the board. On the falling edge of the user button the user LED's are toggled in a callback function. In modelica, is see the only chance to provide the callback function as c-code, which the modelica user has to complete in c-code. As far as I know there is no export facility from modelica to c-function. Any suggestions are welcome.

@bernhard-thiele
Copy link
Collaborator Author

What would be nice, is having a block in which one can configure the external interrupt to use and use that interrupt to activate certain parts of the model. However, there is no direct mapping from Modelica elements to this behaviour, yet. It would be an interesting extension and I would like to see it prototyped in OMC.

For now, I see no nice way how to handle this. It might be possible to sort of use the generated "fmi2DoStep" as a callback function for the ISR, but that would entail some manual C code modifications by the user.

@bernhard-thiele
Copy link
Collaborator Author

Some comments to the build process.

I tried to build the example on my Ubuntu 14.04.5 LTS. It turned out that the cross-compiler packages for that release are not working correctly. This is related to https://stackoverflow.com/questions/26931979/gnu-arm-nano-specs-not-found in which I followed the last suggestion of installing the package gcc-arm-embedded which can be added by an PPA as described at http://yottadocs.mbed.com/#linux-cross-compile. After doing that, I could build the blink project. Today, I ordered the STM32F4 discovery board and I'm looking forward to testing things once the board is delivered.

It would be good to note the Ubuntu version which is the basis for the documentation in the documentation.

@it-cosmos
Copy link
Contributor

Sorry, I'm developing on debian jessy. It was a bit fast to assume ubuntu working in the same way. I will update the documentation for my part. Here I didn't got the problems mentioned. So I can only document developed and tested on debian jessy and problems/solutions/workarounds with ubuntu could be added by ubuntu tester. But for now I can add already mention the problems mentioned.

@it-cosmos
Copy link
Contributor

Regarding Interrupt handling I thought for now to provide a c-template, implementing empty void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin), which is used in the HAL interface, if the corresponding interrupt line is enabled. But before doing so, I would implement simple Digital GPIO read/write and provide an Blink example for that.

@bernhard-thiele
Copy link
Collaborator Author

Anyway, many times Ubuntu and Debian packages work similarly and it is only some small things that differ. I can test from the Ubuntu side and can complement the documentation where needed.

@bernhard-thiele
Copy link
Collaborator Author

@it-cosmos @sjoelund I received the board and could get it working :-)

This is what needs to be done for Ubuntu 14.04.5 LTS (probably this can be improved, but just for not forgetting it):

sudo apt-get install git libusb-1.0.0-dev pkg-config autotools-dev
git clone https://github.com/texane/stlink.git

It seems one needs to install stlink. I tried without it, but I never could connect to the board. Installation and configuration hints are given on the project site, compilation is described in https://github.com/texane/stlink/blob/master/doc/compiling.md and I did basically:

cd stlink
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make
make install
udevadm control --reload-rules
udevadm trigger

Now one probably should set up an stlink group like described in the documentation for getting the access rights correct. I didn't do that in this experiment and simply used sudo everywhere:

sudo st-util

Check the number of the opened port (default for me: 4242). I needed to start st-util first before I could connect with gdb:

sudo arm-none-eabi-gdb
# Now in the debugger console enter
target remote localhost:4242
monitor reset halt
file Blink_main.elf
load
monitor reset
continue

@it-cosmos
Copy link
Contributor

I missed that part, I think I got it easy since I started experimenting with TrueStudio lite, where st-link could be easily selected for connection. But I already forgot what I've really done. Good, that it's working now.

@it-cosmos
Copy link
Contributor

I implemented GPIO Read and Write. The example here doesn't work because the Read Block is just initialized to false. The intension is, that when the blue user button is pressed all user leds should blink.
In DigitalReadBoolean Block I have:
protected Functions.Digital.InitRead digital = Functions.Digital.InitRead(init, port, pin); equation y = Functions.Digital.read(digital, pin); annotation(Icon(graphics = {Text(extent = {{-95, -95}, {95, 95}}, textString =

in BlinkGPIO.mo:
connect(User.y, LED6.u) annotation( Line(points = {{-50, 20}, {-10, 20}, {-10, -14}}, color = {255, 0, 255}));
the generated code shows:
`typedef struct BlinkGPIO_fmi2Component_s {
fmi2Real currentTime;
fmi2Integer fmi2IntegerVars[1];
fmi2Boolean fmi2BooleanVars[1];
void* extObjs[7];
} BlinkGPIO_fmi2Component;

BlinkGPIO_fmi2Component BlinkGPIO_component = {
.fmi2IntegerVars = {
0 /synchronizeRealtime1._tick/,
},
.fmi2BooleanVars = {
fmi2False /User._y/,
},
};`

The problem is that fmi2BooleanVars is intitialised to false and never gets updated with the current value in time the Function.Digital.read is never called in the code. How to solve this?

@sjoelund
Copy link
Contributor

sjoelund commented Jul 1, 2017

I think you need to sample the read. Impure/external calls should not be performed in a continuous-time equation.

@it-cosmos
Copy link
Contributor

Manually inserting the line comp->fmi2BooleanVars[0] = Modelica__DeviceDrivers_EmbeddedTargets_STM32F4_Functions_Digital_read(comp, comp->extObjs[9], 1) in the generated code, function BlinkGPIO_functionOutputs,, the example works.
Shouldn"t that be generated from the equotion in the protected Functions.Digital.InitRead digital = Functions.Digital.InitRead(init, port, pin); equation y = Functions.Digital.read(digital, pin);?

@sjoelund
Copy link
Contributor

sjoelund commented Jul 1, 2017

I think in some parts of the backend, it might detect that the function doesn't vary over time and only reads it once. Anyway, the Modelica specification has some restrictions on calling impure functions (that we do not check, but if you don't follow them you might get unexpected results). Perhaps adding the impure keyword (or annotation) to the read function also fixes this (it should be added almost everywhere as a compiler hint).

@it-cosmos
Copy link
Contributor

Unfortunately sample doesn't work yet. With the modification of the equation;
equation when sample(0, sampleTime) then y = Functions.Digital.read(digital, pin); end when;
I get the output:
[CodegenEmbeddedC.tpl:490:28-490:28:writable] Error: Template error: daeExpCallBuiltin: Not supported: sample(1, 0.0, User.sampleTime).
[CodegenEmbeddedC.tpl:346:14-346:14:writable] Error: Template error: Unsupported equation: ....
"

@it-cosmos
Copy link
Contributor

Right, just adding the impure keyword to the read function fixes the problem. Thanks.

@it-cosmos
Copy link
Contributor

Whith the pull request #221 the GPIO configuration for the speed and pull is hard coded in
"MDDSTM32F4Digital.h";
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Pull = @@GPIO_PULLUP;//for output_PP GPIO Mode
The speed at least could be made configurable in Modelica with above parameters as default.

@it-cosmos
Copy link
Contributor

I think there is a problem with the omc compiler. Please check https://github.com/it-cosmos/Modelica_DeviceDrivers/tree/STM32F4.
In Blink.mo is: Functions.ClockConfig.Init clockConf = Functions.ClockConfig.Init(HALinit, mcu.clock, mcu.pllM, mcu.pllN, mcu.pllP,mcu.pllQ, mcu.ahbPre, mcu.apb1Pre, mcu.apb2Pre, mcu.pwrRegVoltage, mcu.overdrive, mcu.preFlash); Blocks.SynchronizeRealtime synchronizeRealtime1(clockConf = clockConf, timerFrequency = 10000, timerPeriod = 10000) annotation( Placement(visible = true, transformation(origin = {42, 62}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
clocConf is definitly passed to synchronizeRealtime but in the generated code (Blink_main.c) one can see:
typedef struct Blink_fmi2Component_s { fmi2Real currentTime; fmi2Boolean fmi2BooleanVars[1]; fmi2Real fmi2RealParameter[1]; void* extObjs[5]; } Blink_fmi2Component;
and further:
fmi2Status Blink_fmi2EnterInitializationMode(fmi2Component comp) { comp->extObjs[0] /* HALinit EXTOBJ: Modelica_DeviceDrivers.EmbeddedTargets.STM32F4.Functions.HAL.Init */ = Modelica__DeviceDrivers_EmbeddedTargets_STM32F4_Functions_HAL_Init_constructor(comp); comp->extObjs[2] /* led._digital EXTOBJ: Modelica_DeviceDrivers.EmbeddedTargets.STM32F4.Functions.Digital.InitLed */ = Modelica__DeviceDrivers_EmbeddedTargets_STM32F4_Functions_Digital_InitLed_constructor(comp, comp->extObjs[0] /* HALinit EXTOBJ: Modelica_DeviceDrivers.EmbeddedTargets.STM32F4.Functions.HAL.Init */, 1); comp->extObjs[4] /* led1 EXTOBJ: Modelica_DeviceDrivers.EmbeddedTargets.STM32F4.Functions.Digital.InitLed */ = Modelica__DeviceDrivers_EmbeddedTargets_STM32F4_Functions_Digital_InitLed_constructor(comp, comp->extObjs[0] /* HALinit EXTOBJ: Modelica_DeviceDrivers.EmbeddedTargets.STM32F4.Functions.HAL.Init */, 2); comp->extObjs[1] /* clockConf EXTOBJ: Modelica_DeviceDrivers.EmbeddedTargets.STM32F4.Functions.ClockConfig.Init */ = Modelica__DeviceDrivers_EmbeddedTargets_STM32F4_Functions_ClockConfig_Init_constructor(comp, comp->extObjs[0] /* HALinit EXTOBJ: Modelica_DeviceDrivers.EmbeddedTargets.STM32F4.Functions.HAL.Init */, 4, 8, 336, 1, 7, 1, 3, 2, 1, comp->fmi2BooleanVars[0] /* mcu._overdrive CONST */, fmi2True); comp->extObjs[6] /* synchronizeRealtime1._sync EXTOBJ: Modelica_DeviceDrivers.EmbeddedTargets.STM32F4.Functions.RealTimeSynchronization.Init */ = Modelica__DeviceDrivers_EmbeddedTargets_STM32F4_Functions_RealTimeSynchronization_Init_constructor(comp, comp->extObjs[5] /* synchronizeRealtime1._clockConf EXTOBJ: Modelica_DeviceDrivers.EmbeddedTargets.STM32F4.Functions.ClockConfig.Init */, 10000, 10000); return fmi2OK; }

extObj[5] and [6] is assigned, although only 5 range from 0 to 4 are initialized. Further: As clockconf is passed in the modelica code to synchronizeRealtime1, it is not reflected in the generated code. The corret generated code would be:
comp->extObjs[3] /* synchronizeRealtime1._sync EXTOBJ: Modelica_DeviceDrivers.EmbeddedTargets.STM32F4.Functions.RealTimeSynchronization.Init */ = Modelica__DeviceDrivers_EmbeddedTargets_STM32F4_Functions_RealTimeSynchronization_Init_constructor(comp, comp->extObjs[1] /* synchronizeRealtime1._clockConf EXTOBJ: Modelica_DeviceDrivers.EmbeddedTargets.STM32F4.Functions.ClockConfig.Init */, 10000, 10000); return fmi2OK;
Please check.

@bernhard-thiele bernhard-thiele modified the milestones: v1.6.0, v1.7.0 Nov 21, 2018
@bernhard-thiele bernhard-thiele modified the milestones: v1.7.0, v1.8.0 Mar 28, 2019
@bernhard-thiele bernhard-thiele removed this from the v1.8.0 milestone Jan 11, 2020
@bernhard-thiele bernhard-thiele added this to the undecided milestone Jan 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants