Comments (18)
Hi @claudiaAl,
#define PERIPH_CLK_GATE_CTRL (SCSS_REGISTER_BASE + 0x018)
This is actually a memory location, rather than a bitmask (it's the address of the PERIPH_CLK_GATE_CTRL register).
so, when we look at this line;
MMIO_REG_VAL(PERIPH_CLK_GATE_CTRL) &= DISABLE_SPI_MASTER_1;
it's saying "access the memory location PERIPH_CLK_GATE_CTRL, and apply the bitmask DISABLE_SPI_MASTER_1 to the value that lives there"
As to what bit is being changed, look in SPI_registers.h
#define ENABLE_SPI_MASTER_0 (0x1 << 14)
#define DISABLE_SPI_MASTER_0 (~ENABLE_SPI_MASTER_0)
#define ENABLE_SPI_MASTER_1 (0x1 << 15)
#define DISABLE_SPI_MASTER_1 (~ENABLE_SPI_MASTER_1)
So apparently it's bit 14 for SPI0, and bit 15 for SPI1
from arduinocore-arc32.
But-- an unrelated question-- is there any particular reason you need to re-implement SPI.end()
? why can't you just call the existing method to disable the SPI bus? And also, I believe that SPI is disabled anyway until you call SPI.begin()
or SPI1.begin()
, right?
from arduinocore-arc32.
Good question. I can. That's actually where I started, but I didn't see any change in my current readings, so in an effort to be as thorough as possible, I wanted to go in and read the registers and understand what was really happening. If this all eventually goes into a library, I am assuming I would just use my end() function rather than duplicating the code...?
from arduinocore-arc32.
like I said, I think SPI will be disabled by default anyway until you call *.begin()
. So calling SPI.end()
without first calling SPI.begin()
is effectively changing nothing.
from arduinocore-arc32.
got it! thank you!
from arduinocore-arc32.
ok, so I have played with calling begin and end in order to see what's happening in the register. It's just for my own learning and to prove to myself that I can see the changes. The register looks like this initially, and after calling SPI.begin(), SPI.end(), and SPI.begin() again... for anyone that is interested!
CTRL0 initial 0
SPIEN initial 0
SER initial 0
BAUDR initial 0
TXFL initial 0
RXFL initial 0
SR initial 0
IMR initial 0
DR initial 0CTRL0 after SPI begin() 1110000000000000000
SPIEN after SPI begin() 1
SER after SPI begin() 1
BAUDR after SPI begin() 1000
TXFL after SPI begin() 0
RXFL after SPI begin() 0
SR after SPI begin() 110
IMR after SPI begin() 0
DR after SPI begin() 0CTRL0 after SPI end() 1
SPIEN after SPI end() 1
SER after SPI end() 1
BAUDR after SPI end() 1
TXFL after SPI end() 1
RXFL after SPI end() 1
SR after SPI end() 1
IMR after SPI end() 1
DR after SPI end() 1CTRL0 after SPI begin() 1110000000000000000
SPIEN after SPI begin() 1
SER after SPI begin() 1
BAUDR after SPI begin() 1000
TXFL after SPI begin() 0
RXFL after SPI begin() 0
SR after SPI begin() 110
IMR after SPI begin() 0
DR after SPI begin() 0
from arduinocore-arc32.
Do you have the latest version? I do, and I can't see SPI1_M_REG_VAL
, only SPI_M_REG_VAL
.
Maybe you have an old version?
You have the right idea, though; if you are using the latest, then you can read it like this;
creg = SPI_M_REG_VAL(SOC_MST_SPI1_REGISTER_BASE, SPIEN);
But, there is a sneaky twist here; SPI (i.e. SPI.begin()
) actually uses the hardware SPI1 (i.e. SOC_MST_SPI1_REGISTER_BASE). So when I added support for SPI1 (i.e. SPI1.begin()
the remaining SPI controller available to use is unfortunately named SPI0. The result is that SPI.begin()
accesses SOC_MST_SPI1_REGISTER_BASE
, and SPI1.begin()
accesses SOC_MST_SPI0_REGISTER_BASE
. You can see this in SPI.cpp:
SPIClass SPI(SPIDEV_1);
SPIClass SPI1(SPIDEV_0);
and SPI.h:
#define SPIDEV_0 0
#define SPIDEV_1 1
...
int spidevs[NUM_SPIDEVS][4] =
{
/* base addr. Clk. enable value Clk. disable value SS GPIO */
{(int)SOC_MST_SPI0_REGISTER_BASE, ENABLE_SPI_MASTER_0, DISABLE_SPI_MASTER_0, SPI0_CS},
{(int)SOC_MST_SPI1_REGISTER_BASE, ENABLE_SPI_MASTER_1, DISABLE_SPI_MASTER_1, SPI1_CS}
};
So, you would test the Arduino SPI1 instance like this;
/* enable SPI1 */
SPI1.begin()
/* Read SPIEN */
creg = SPI_M_REG_VAL(SOC_MST_SPI0_REGISTER_BASE, SPIEN);
/* Disable SPI1 */
SPI1.end()
/* Read SPIEN */
creg = SPI_M_REG_VAL(SOC_MST_SPI0_REGISTER_BASE, SPIEN);
Does that make sense? it can get a bit confusing with all the back-and-forth between 0 and 1...
from arduinocore-arc32.
I just edited my last post- I had mistakenly used SOC_MST_SPI1_REGISTER_BASE
in the final example. It's correct now :)
from arduinocore-arc32.
And, I was answering the original question I saw in the email notification-- I didn't notice you had removed the question. Did you figure it out?
from arduinocore-arc32.
I think I am close... I ended up using this after referencing SPI_registers.h
creg = SPI1_M_REG_VAL(CTRL0);
I just compared the two versions and it looks like the definition changed from
/* Macro to access SPI1 Master controller register offset */
#define SPI1_M_REG_VAL(reg) \
MMIO_REG_VAL_FROM_BASE(SOC_MST_SPI1_REGISTER_BASE, (reg))
to
/* Macro to access SPI Master controller register offset */
#define SPI_M_REG_VAL(base, reg) MMIO_REG_VAL_FROM_BASE(base, (reg))
It looks like they do the same thing... but I need to change my code so that I am looking at SPI0 and not SPI1.
I thought that there was only going to be access to one of the SPIs because the other was attached to the BM160 by default. Is this still the case? Should I only be considering SPI0 when developing the low power lib?
Thanks!!!
from arduinocore-arc32.
CurieIMU class uses SOC_MST_SPI1_REGISTER_BASE (i.e. SPI.begin()
), but this SPI controller is only initialised by CurieIMUClass::begin()
Honestly, I don't think there's any point in re-implementing the SPI.end()
method for your low power lib. Simply not calling SPI.begin()
is already enough to ensure that the SPI controller is disabled.
from arduinocore-arc32.
Can we look at a quick use case? Let's say we have a sketch running that initializes the CurieIMU class because we want to be collecting information from the sensors... let's say we are focusing on the motion and temperature sensors to determine if a device is being worn. If we determine that the device is not being worn, I would like to disable the SPI bus (assuming that we can verify that disabling it will indeed provide power savings). It would then need to be woken up once we see that the device is being worn again... no clue how I'm doing this yet... baby steps!
This means that my SPI1 would be needing to go between begin() and end() calls, but my SPI0 can remain disabled the whole time... is that correct? Am I making this harder than it needs to be?
from arduinocore-arc32.
For sanity's sake, let's just talk about SPI
and SPI1 (i.e. Arduino's SPI.begin()
and SPI1.begin()
) from now on, even though we know now it's really SPI1 and SPI0 behind the scenes. As far as I'm aware, the CurieIMU class just uses SPI
, so in theory you could call CurieIMU.begin()
to use the IMU, then call SPI.end()
to disable the SPI controller, then call CurieIMU.begin()
to use the IMU again.
But, I'm not too sure of the details here, it may not be that simple. I'll have to go and look at what exactly CurieIMU.begin()
does.
So for your use case, it sounds like you basically need some kind of CurieIMUClass::end()
method, which doesn't exist right now. Maybe instead of messing with SPI, we should be thinking about adding an end()
method. @SidLeung @bigdinotech what do you think?
from arduinocore-arc32.
It doesn't look like CurieIMU.begin()
writes anything to the SPI Master 0 register. When I call SPI.begin()
and SPI.end()
I can see changes made in the SPI1 Register (SPIEN, CTRL0, etc.). When I call SPI1.begin()
and SPI1.end()
I see changes in the SPI0 Register as expected. The CurieIMU.begin()
method calls the ss_spi_init()
function which sets the peripheral to inactive so the clock can be gated, disables the SPI1 controller, and enables the controller clock to allow for register writes. That's followed by the BMI160 initialization. But nothing ever changes in the control register, and there are a number of things that the SPIClass.begin()
function does that the CurieIMU initialization doesn't.
I've confused myself... should I just be working with the SPI class??
from arduinocore-arc32.
@claudiaAl I was wrong, there are actually 3 SPI controllers in use. One goes to pins 10-13 (SPI.begin()
), another goes to the onboard SPI flash (SPI1.begin()
), and the third is used only for the BMI160 and is initialised with ss_spi_init()
. So, you want to look at the implementation of ss_spi_init()
, I guess.
I'm also going to implement a CurieIMU.end()
method, to disable the 3rd SPI controller.
from arduinocore-arc32.
Try this change @claudiaAl #235
from arduinocore-arc32.
Thank you Erik! I was able to successfully test the running and disabling of all three SPI buses. Interestingly enough, SPI and SPI1 behave as expected... running begin() and not doing anything consumes more energy than having it disabled. However, the CurieIMU.end() method causes more power consumption than its begin() method due to the setting of some pins.
from arduinocore-arc32.
"However, the CurieIMU.end() method causes more power consumption than its begin() method due to the setting of some pins"
Yes, that's why an Arduino101 board is really not the best option for testing your power savings library, since there are a lot of power-hungry components on the board that you can't turn off. Even if you take the whole Curie chip off, I'm sure there will still be a significant current draw from the rest of the board (and I confess, I don't have any better suggestions for you at this moment!).
from arduinocore-arc32.
Related Issues (20)
- Error compiling for board Arduino/Genuino 101. HOT 7
- Peripheral not connectable when broadcasting characteristic value
- Incorrect capitalization of true in CurieIMU documentation HOT 3
- some EEPROM.CPP ERROR HOT 1
- SPI.beginTransaction allows SPISettings faster than 8 MHz
- Cannot discover attributes HOT 1
- Limited error messages, when selecting the wrong COM port
- How to using UART ISR ?
- [Urgent][Stuck Problem] BLE setValue in callback function!
- Can't send BLE data less than 25ms? HOT 3
- Crashing when three or more characteristics are updated every 30ms? HOT 1
- CurieBLE - BLECommon dosen't existe .. HOT 2
- CurieBLE for HM-11
- Should extra_flags be empty in platform.txt? HOT 1
- SoftwareSerial core library
- IPAddress missing definition of operator!=()
- When I try to upload a simple sketch to the Arduino 101, I get the following error on Mac M1 (macOS Monterey) HOT 3
- No tag for 2.0.6 release
- error: #error "This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor." #error "This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor." HOT 2
- Placing the breadboard with BMI160 to horizontally(remapping axis) HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from arduinocore-arc32.