Giter VIP home page Giter VIP logo

Comments (18)

eriknyquist avatar eriknyquist commented on August 15, 2024

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.

eriknyquist avatar eriknyquist commented on August 15, 2024

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.

claudiaAl avatar claudiaAl commented on August 15, 2024

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.

eriknyquist avatar eriknyquist commented on August 15, 2024

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.

claudiaAl avatar claudiaAl commented on August 15, 2024

got it! thank you!

from arduinocore-arc32.

claudiaAl avatar claudiaAl commented on August 15, 2024

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 0

CTRL0 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

CTRL0 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() 1

CTRL0 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.

eriknyquist avatar eriknyquist commented on August 15, 2024

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.

eriknyquist avatar eriknyquist commented on August 15, 2024

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.

eriknyquist avatar eriknyquist commented on August 15, 2024

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.

claudiaAl avatar claudiaAl commented on August 15, 2024

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.

eriknyquist avatar eriknyquist commented on August 15, 2024

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.

claudiaAl avatar claudiaAl commented on August 15, 2024

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.

eriknyquist avatar eriknyquist commented on August 15, 2024

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.

claudiaAl avatar claudiaAl commented on August 15, 2024

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.

eriknyquist avatar eriknyquist commented on August 15, 2024

@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.

eriknyquist avatar eriknyquist commented on August 15, 2024

Try this change @claudiaAl #235

from arduinocore-arc32.

claudiaAl avatar claudiaAl commented on August 15, 2024

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.

eriknyquist avatar eriknyquist commented on August 15, 2024

"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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.