Thanks to visit codestin.com
Credit goes to github.com

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
#define NCONTROLLERS (2)

#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 define these macros? To me it's clearer to just use the original mem-to-periph or periph-to-mem names.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I defined theses macros to make the transfer of the information in the datasheet less error-prone. In the data sheet (RM0351, rev 2, Page 309 ff) there is always a SPI2_TX and SPI2_RX.. So I though it would be a good thing to define macros which are close to what is written in the datasheet.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, I see. But I still think using the macro adds unnecessary complexity. For example, in the datasheet there are also the names DAC1, DAC2, CRYPT_IN, CRYPT_OUT, TIM3_CH1, etc, that have nothing to do with tx/rx. So you can keep the names SPI2_TX etc, but just use DMA_MEMORY_TO_PERIPH and DMA_PERIPH_TO_MEMORY.

@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