Skip to content

L4 integration: Adapted DMA to STM32L4 MCU series. #1916

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

Closed
wants to merge 1 commit into from

Conversation

tobbad
Copy link
Contributor

@tobbad tobbad commented Mar 22, 2016

This is the 5th PR in a series (#1888, #1890, #1903, #1904 ) of PR to support the STM32L4 series in micropython. (see http://forum.micropython.org/viewtopic.php?f=12&t=1332&sid=64e2f63af49643c3edee159171f4a365)

The topic is to change the dma code in a way, that the structure DMA_Stream_TypeDef (which is similar to DMA_Channel_TypeDef on stm32l4) is no more used outside of dma.c as this structure only exists for F4 series. Therefore I introduced a new structure (dma_descr_t) which handles all dma specific stuff for configuration. Further the periphery (spi, i2c, sdcard, dac) does not need to know the internals of the dma.

As a consequence a Periphery just asks for a dma to it self (defined by the enum periphery_t in dma.h) which instance of it self, and the direction of data transport. The DMA module then decides upon the Stream/Channel (stm32f4) or Channel/Request (stm32l4) should be used. These configuration are captured in the dma_transfer_info structure within dma.c. Further the initial setting (DMA_InitTypeDefs dma_init_struct_spi_i2c and dma_init_struct_sdio) is as well centralized in dma.c as these are as well MCU series specific.

This fix should work without the merge of the earlier PRs.

} dma_descr_t;

#define DMA_TX_TRANSFER DMA_MEMORY_TO_PERIPH
#define DMA_RX_TRANSFER DMA_PERIPH_TO_MEMORY
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tobbad why did you declare these 2 macros? Why not just use DMA_MEMORY_TO_PERIPH and DMA_PERIPH_TO_MEMORY directly? To me, these are much clearer in their meaning than tx/rx.

@dpgeorge
Copy link
Member

The way you have written the code is that each periph defines a dma_descr_t when it wants to use DMA. Eg for I2C it defines {dma_I2C, 1, DMA_TX_TRANSFER}. Then whenever dma_init or dma_invalidate_channel is called it must search the big table in dma.c (dma_transfer_info) for a match to this dma_descr_t info. This seems inefficient in speed and code size.

As an alternative, how about the following: expose each entry of the dma_transfer_info table in dma.h with a unique name, and then point to this from the peripheral that wants to use it. For example:

dma.h:
    typedef struct _dma_p2dma_t dma_p2dma_t;
    extern dma_p2dma_t dma_I2C_1_RX;
    extern dma_p2dma_t dma_SPI_3_RX;
    extern dma_p2dma_t dma_I2C_3_RX;
    extern dma_p2dma_t dma_I2C_2_RX;

dma.c:
    struct _dma_p2dma_t {
        // no need for dma_descr_t
    #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
        DMA_Stream_TypeDef  *instance;
    #elif defined(MCU_SERIES_L4)
        DMA_Channel_TypeDef *instance;
    #else
    #error "Unsupported Processor"
    #endif
        uint32_t        sub_instance;
        dma_id_t        id; 
        const DMA_InitTypeDef *init;
    } dma_p2dma_t;

    const dma_p2dma_t dma_I2C_1_RX = {DMA1_Stream0, DMA_CHANNEL_1, dma_id_0 , &dma_init_struct_spi_i2c},
    const dma_p2dma_t dma_SPI_3_RX = {DMA1_Stream2, DMA_CHANNEL_0, dma_id_2  , &dma_init_struct_spi_i2c},
    const dma_p2dma_t dma_I2C_3_RX = {DMA1_Stream2, DMA_CHANNEL_3, dma_id_2  , &dma_init_struct_spi_i2c},
    const dma_p2dma_t dma_I2C_2_RX = {DMA1_Stream2, DMA_CHANNEL_7, dma_id_2  , &dma_init_struct_spi_i2c},

i2c.c:
    typedef struct _pyb_i2c_obj_t {
        mp_obj_base_t base;
        I2C_HandleTypeDef *i2c;
        dma_p2dma_t *tx_dma;
        dma_p2dma_t *rx_dma;
    } pyb_i2c_obj_t;

    STATIC const pyb_i2c_obj_t pyb_i2c_obj[] = { 
        {{&pyb_i2c_type}, &I2CHandle1, &dma_I2C_1_TX, &dma_I2C1_RX},
        ...
    };

Does that make sense?

@tobbad
Copy link
Contributor Author

tobbad commented Apr 18, 2016

Thank you - good point. I was as well not satisfied with my solution.

Sometimes you have different alternatives for a periphery. Shall I call them eg. dma_I2C_1_RX_1 or just not declare them?

@dpgeorge
Copy link
Member

Sometimes you have different alternatives for a periphery. Shall I call them eg. dma_I2C_1_RX_1 or just not declare them?

If they're not used, don't declare them, just leave them as commented-out code in case they are needed later. Otherwise, if they are used, put a postfix of _A or _B.

@tobbad
Copy link
Contributor Author

tobbad commented Apr 21, 2016

I have now a solution at hand and debugging it.

Is there an automated build, deploy and test framework for directly testing the code on a hardware? For the DMA I started to build some code which:

  1. Checkout a given branch if the code is not dirty.
  2. Builds the code.
  3. Deploys the code to the correct board (Board must match the build target) even if there are several boards connected to the PC.
  4. Runs python test code over serial connection on the correct board and checks the code result.
    Of course there is need for some polishing but as concept my python code works.

Is there a function in mp where I can get the information which is returned during a cold reset eg:

PYB: sync filesystems
PYB: soft reboot
MicroPython v1.7-240-gd7cd205-dirty on 2016-04-21; L476-DISCO with STM32L476
Type "help()" for more information.

What I am interested in is the version, date, board and CPU information.

@dpgeorge
Copy link
Member

Is there a function in mp where I can get the information which is returned during a cold reset eg:

Try os.uname()

@tobbad tobbad force-pushed the l4_integration_dma branch 3 times, most recently from d5deeac to 148035f Compare April 22, 2016 06:16
@tobbad
Copy link
Contributor Author

tobbad commented Apr 25, 2016

Thank you.

I modified the PR according to your suggestions and collected all concerned file in this PR. I did some test (spi/i2c transfer on stm32f4disco and stm32l476disco) which passed.

I hope that it can be merged now.

@dpgeorge
Copy link
Member

I see that there are modifications to adc.c. Are they relevant to DMA? If not can you please separate the ADC changes into a separate commit (can be within this PR, just a separate commit to the DMA changes). Thanks!

@tobbad tobbad force-pushed the l4_integration_dma branch from 148035f to e0a2e58 Compare April 25, 2016 14:57
@tobbad
Copy link
Contributor Author

tobbad commented Apr 25, 2016

Ops - that somehow sneaked in.

The adc changes are already merged in d49a547.

I did an update.

@tobbad tobbad closed this Apr 25, 2016
@tobbad tobbad reopened this Apr 25, 2016
#define DMA2_ENABLE_MASK 0xff00 // Bits in dma_enable_mask corresponding to DMA2
#define DMA_INVALID_CHANNEL 0xff // Value stored in dma_last_channel which means invalid

#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
#define DMA_CHANNEL_AS_UINT8(dma_channel) (((dma_channel) & DMA_SxCR_CHSEL) >> 24)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tobbad this macro is now wrong (or it's called incorrectly) because the argument is a dma_id_t which is not a channel. So this macro will always evaluate to 0 for the F4/F7.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. But this macro is anyway wrong. In the data sheet the channel selection bits start a position 25 so the shift should be 25.

The macro should return the Stream number on f4/f7 which is in the range 0..7 and the channel number on l4 which is in the range 1..7. If we keep it simple we can use for both cases the macro
#define DMA_CHANNEL_AS_UINT8(dma_descr) ((dma_descr->id) % NSTREAMS_PER_CONTROLLER)
If would like to really have the values 1..7 instead of 0..6 for L4 we have to adapt the Macro accordingly.

I make the simple modification and re-push the stuff.

@tobbad tobbad force-pushed the l4_integration_dma branch 6 times, most recently from 2a9d24a to 7b061b8 Compare April 28, 2016 09:20
@@ -33,9 +33,145 @@
#include "py/obj.h"
#include "irq.h"

#define NSTREAMS_PER_CONTROLLER_LOG2 (3)
#define NSTREAMS_PER_CONTROLLER (1 << NSTREAMS_PER_CONTROLLER_LOG2)
Copy link
Contributor Author

@tobbad tobbad Apr 28, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As NSTREAMS_PER_CONTROLLER_LOG2 is 3 for F-series we have 8 streams. but on L4 there are only 7 streams. The use of this #define in dma_tickle is therefore no more possible. Therefore I removed NSTREAMS_PER_CONTROLLER_LOG2.

@tobbad tobbad force-pushed the l4_integration_dma branch 2 times, most recently from c138232 to 5c8c67e Compare April 28, 2016 09:46
.MemBurst = DMA_MBURST_INC4,
.PeriphBurst = DMA_PBURST_INC4,
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to dma.c.

@tobbad
Copy link
Contributor Author

tobbad commented Apr 28, 2016

Updated the code and did some clean ups. Did some simple i2c/spi test on stm32f4disco, stm32F429disco, stm32l4Disco, limifrog.

@tobbad tobbad force-pushed the l4_integration_dma branch from 5c8c67e to 78457cd Compare April 30, 2016 07:28
@dpgeorge
Copy link
Member

dpgeorge commented May 5, 2016

I did a little bit of tidying up (mostly white space changes and reordering some things in dma.c) and merged it in e64032d. Thank you!

@dpgeorge dpgeorge closed this May 5, 2016
@tobbad tobbad deleted the l4_integration_dma branch May 7, 2016 14:56
tannewt pushed a commit to tannewt/circuitpython that referenced this pull request Jun 12, 2019
Removed warning box regarding SAMD21 builds
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy