[PATCH] Properly flush cache when writing to MPC55XX flash.

Joel Sherrill joel.sherrill at oarcorp.com
Wed Aug 20 20:59:41 UTC 2014


Something went wrong. :(

Applying: Properly flush cache when writing to MPC55XX flash.
fatal: corrupt patch at line 11
Patch failed at 0001 Properly flush cache when writing to MPC55XX flash.

How about you compress it and sent it to me privately as an attachment
in case the mail client is doing something

--joel
On 8/20/2014 3:48 PM, Peter Dufault wrote:
> Also cleanup:
> * Remove un-needed interrupt disables.
> * Address errata "e989: FLASH: Disable Prefetch during programming and erase"
> * Use RTEMS_ARRAY_SIZE() macro instead of own macro.
> ---
> .../libcpu/powerpc/mpc55xx/misc/flash_support.c    |   85 +++++++++-----------
> 1 files changed, 39 insertions(+), 46 deletions(-)
>
> diff --git a/c/src/lib/libcpu/powerpc/mpc55xx/misc/flash_support.c b/c/src/lib/libcpu/powerpc/mpc55xx/misc/flash_support.c
> index 17c4e3f..b286b51 100644
> --- a/c/src/lib/libcpu/powerpc/mpc55xx/misc/flash_support.c
> +++ b/c/src/lib/libcpu/powerpc/mpc55xx/misc/flash_support.c
> @@ -135,8 +135,6 @@ range_set(
>     *p_bits = bits;
> }
>
> -#define N(ARG) (sizeof(ARG)/sizeof(ARG[0]))
> -
> /** Return the size of the on-chip flash
>  *  verifying that this is a device that we know about.
>  * @return 0 for OK, non-zero for error:
> @@ -207,7 +205,6 @@ unlock_once(int lsel, int msel, int hbsel, int *p_locked)
>     union LMLR_tag lmlr;
>     union SLMLR_tag slmlr;
>     union HLR_tag hlr;
> -    rtems_interrupt_level level;
>
>     /* If we're already locked return.
>      */
> @@ -217,7 +214,6 @@ unlock_once(int lsel, int msel, int hbsel, int *p_locked)
>
>     /* Do we have to lock something in the low or mid block?
>      */
> -    rtems_interrupt_disable(level);
>     lmlr = FLASH.LMLR;
>     if ((lsel || msel) && (lmlr.B.LME == 0)) {
>         union LMLR_tag lmlr_unlock;
> @@ -228,7 +224,6 @@ unlock_once(int lsel, int msel, int hbsel, int *p_locked)
>         if (lmlr.B.LLOCK != lmlr_unlock.B.LLOCK ||
>         lmlr.B.MLOCK != lmlr_unlock.B.MLOCK) {
>             if (p_locked == 0) {
> -                rtems_interrupt_enable(level);
>                 return MPC55XX_FLASH_LOCK_ERR;
>             } else {
>                 *p_locked = 1;
> @@ -237,9 +232,7 @@ unlock_once(int lsel, int msel, int hbsel, int *p_locked)
>             FLASH.LMLR = lmlr_unlock;
>         }
>     }
> -    rtems_interrupt_enable(level);
>
> -    rtems_interrupt_disable(level);
>     slmlr = FLASH.SLMLR;
>     if ((lsel || msel) && (slmlr.B.SLE == 0)) {
>         union SLMLR_tag slmlr_unlock;
> @@ -250,7 +243,6 @@ unlock_once(int lsel, int msel, int hbsel, int *p_locked)
>         if (slmlr.B.SLLOCK != slmlr_unlock.B.SLLOCK ||
>         slmlr.B.SMLOCK != slmlr_unlock.B.SMLOCK) {
>             if (p_locked == 0) {
> -                rtems_interrupt_enable(level);
>                 return MPC55XX_FLASH_LOCK_ERR;
>             } else {
>                 *p_locked = 1;
> @@ -259,11 +251,9 @@ unlock_once(int lsel, int msel, int hbsel, int *p_locked)
>             FLASH.SLMLR = slmlr_unlock;
>         }
>     }
> -    rtems_interrupt_enable(level);
>
>     /* Do we have to unlock something in the high block?
>      */
> -    rtems_interrupt_disable(level);
>     hlr = FLASH.HLR;
>     if (hbsel && (hlr.B.HBE == 0)) {
>         union HLR_tag hlr_unlock;
> @@ -272,7 +262,6 @@ unlock_once(int lsel, int msel, int hbsel, int *p_locked)
>         if (hlr.B.HBLOCK != hlr_unlock.B.HBLOCK) {
>             if (p_locked == 0) {
>                 return MPC55XX_FLASH_LOCK_ERR;
> -                rtems_interrupt_enable(level);
>             } else {
>                 *p_locked = 1;
>             }
> @@ -280,7 +269,6 @@ unlock_once(int lsel, int msel, int hbsel, int *p_locked)
>             FLASH.HLR = hlr_unlock;
>         }
>     }
> -    rtems_interrupt_enable(level);
>
>     return 0;
> }
> @@ -398,24 +386,25 @@ mpc55xx_flash_copy_op(
> {
>     uint32_t udest, usrc, flash_size;
>     int r;
> -    int peg;            /* Program or Erase Good - Did it work? */
> +    int peg;                        /* Program or Erase Good - Did it work? */
>
> -    int lsel;           /* Low block select bits. */
> -    int msel;           /* Mid block select bits. */
> -    int hbsel;          /* High block select bits. */
> +    int lsel;                       /* Low block select bits. */
> +    int msel;                       /* Mid block select bits. */
> +    int hbsel;                      /* High block select bits. */
>
> -    int s_lsel;           /* Source Low block select bits. */
> -    int s_msel;           /* Source Mid block select bits. */
> -    int s_hbsel;          /* Source High block select bits. */
> +    int s_lsel;                     /* Source Low block select bits. */
> +    int s_msel;                     /* Source Mid block select bits. */
> +    int s_hbsel;                    /* Source High block select bits. */
>
>     int unlocked = 0;
>     int *p_unlocked;
>     int i;
> -    int nwords;         /* The number of 32 bit words to write. */
> -    volatile uint32_t *flash;    /* Where the flash is mapped in. */
> -    volatile uint32_t *memory;   /* What to copy into flash. */
> -    uint32_t offset;    /* Where the FLASH is mapped into memory. */
> -    rtems_interrupt_level level;
> +    int nwords;                     /* The number of 32 bit words to write. */
> +    volatile uint32_t *flash;       /* Where the flash is mapped in. */
> +    volatile uint32_t *memory;      /* What to copy into flash. */
> +    const void *flashing_from;      /* Where we are flahsing from.
> +                                     * "const" is to match invalidate cache function signature. */
> +    uint32_t offset;                /* Where the FLASH is mapped into memory. */
>
>     if ( (r = mpc55xx_flash_size(&flash_size))) {
>         return r;
> @@ -461,13 +450,13 @@ mpc55xx_flash_copy_op(
>
>     /* Set up the bit masks for the blocks to program or erase.
>      */
> -    range_set(udest, udest + nbytes, &lsel,   lsel_ranges, N( lsel_ranges));
> -    range_set(udest, udest + nbytes, &msel,   msel_ranges, N( msel_ranges));
> -    range_set(udest, udest + nbytes, &hbsel, hbsel_ranges, N(hbsel_ranges));
> +    range_set(udest, udest + nbytes, &lsel,   lsel_ranges, RTEMS_ARRAY_SIZE( lsel_ranges));
> +    range_set(udest, udest + nbytes, &msel,   msel_ranges, RTEMS_ARRAY_SIZE( msel_ranges));
> +    range_set(udest, udest + nbytes, &hbsel, hbsel_ranges, RTEMS_ARRAY_SIZE(hbsel_ranges));
>
> -    range_set(usrc, usrc + nbytes, &s_lsel,   lsel_ranges, N( lsel_ranges));
> -    range_set(usrc, usrc + nbytes, &s_msel,   msel_ranges, N( msel_ranges));
> -    range_set(usrc, usrc + nbytes, &s_hbsel, hbsel_ranges, N(hbsel_ranges));
> +    range_set(usrc, usrc + nbytes, &s_lsel,   lsel_ranges, RTEMS_ARRAY_SIZE( lsel_ranges));
> +    range_set(usrc, usrc + nbytes, &s_msel,   msel_ranges, RTEMS_ARRAY_SIZE( msel_ranges));
> +    range_set(usrc, usrc + nbytes, &s_hbsel, hbsel_ranges, RTEMS_ARRAY_SIZE(hbsel_ranges));
>
>     /* Are we attempting overlapping flash?
>      */
> @@ -481,33 +470,39 @@ mpc55xx_flash_copy_op(
>
>   /* In the following sections any "Step N" notes refer to
>    * the steps in "13.4.2.3 Flash Programming" in the reference manual.
> -   * XXX Do parts of this neeed to be protected by interrupt locks?
>    */
>
>     if (opmask & MPC55XX_FLASH_ERASE) {   /* Erase. */
> +        uint32_t flash_biucr_r;
>         if ( (r = unlock_once(lsel, msel, hbsel, p_unlocked)) ) {
>             return r;
>         }
>
> -        rtems_interrupt_disable(level);
> +        /* Per errata "e989: FLASH: Disable Prefetch during programming and erase" */
> +        flash_biucr_r = FLASH.BIUCR.R;
> +        FLASH.BIUCR.B.PFLIM = 0;
> +
> +        FLASH.MCR.B.ESUS = 0;       /* Be sure ESUS is clear. */
> +
>         FLASH.MCR.B.ERS = 1;        /* Step 1: Select erase. */
>
>         FLASH.LMSR.B.LSEL = lsel;   /* Step 2: Select blocks to be erased. */
>         FLASH.LMSR.B.MSEL = msel;
>         FLASH.HSR.B.HBSEL = hbsel;
>
> -        flash[0] = 1;               /* Step 3: Write to any address in the flash
> +        flash[0] = 0xffffffff;      /* Step 3: Write to any address in the flash
>                                      * (the "erase interlock write)".
>                                      */
> +        rtems_cache_flush_multiple_data_lines(flash, sizeof(flash[0]));
> +
>         FLASH.MCR.B.EHV = 1;         /* Step 4: Enable high V to start erase. */
> -        rtems_interrupt_enable(level);
>         while (FLASH.MCR.B.DONE == 0) { /* Step 5: Wait until done. */
>         }
> -        rtems_interrupt_disable(level);
>         peg = FLASH.MCR.B.PEG;       /* Save result. */
>         FLASH.MCR.B.EHV = 0;         /* Disable high voltage. */
>         FLASH.MCR.B.ERS = 0;         /* De-select erase. */
> -        rtems_interrupt_enable(level);
> +        FLASH.BIUCR.R = flash_biucr_r;
> +
>         if (peg == 0) {
>             return MPC55XX_FLASH_ERASE_ERR; /* Flash erase failed. */
>         }
> @@ -534,9 +529,7 @@ mpc55xx_flash_copy_op(
>         }
>         FLASH.MCR.B.PGM = 1;                /* Step 1 */
>
> -       rtems_interrupt_disable(level);
> -
> -        for (i = 0; i < nwords; i += 2) {
> +        for (flashing_from = (const void *)flash, i = 0; i < nwords; i += 2) {
>            flash[i] = memory[i];            /* Step 2 */
>            flash[i + 1] = memory[i + 1];    /* Always program in min 64 bits. */
>
> @@ -548,45 +541,45 @@ mpc55xx_flash_copy_op(
>            chunk++;
>            if (chunk == 4) {
>                 /* Collected 4 64-bits for a 256 bit chunk. */
> +
> +                rtems_cache_flush_multiple_data_lines(flashing_from, 32);    /* Flush cache. */
> +
>                 FLASH.MCR.B.EHV = 1;            /* Step 4: Enable high V. */
>
> -                rtems_interrupt_enable(level);
>                 while (FLASH.MCR.B.DONE == 0) { /* Step 5: Wait until done. */
>                 }
> -                rtems_interrupt_disable(level);
>
>                 peg = FLASH.MCR.B.PEG;          /* Step 6: Save result. */
>                 FLASH.MCR.B.EHV = 0;            /* Step 7: Disable high V. */
>                 if (peg == 0) {
>                     FLASH.MCR.B.PGM = 0;
> -                    rtems_interrupt_enable(level);
>                     if (p_fail) {
>                         *p_fail = (uint32_t)(flash + i);
>                     }
>                     return MPC55XX_FLASH_PROGRAM_ERR; /* Programming failed. */
>                 }
>                 chunk = 0;                       /* Reset chunk counter. */
> +                flashing_from = (const void *)(flash + i);
>             }
>                                                  /* Step 8: Back to step 2. */
>         }
>
>        if (!chunk) {
>             FLASH.MCR.B.PGM = 0;
> -            rtems_interrupt_enable(level);
>        } else {
>            /* If there is anything left in that last chunk flush it out:
>             */
> +
> +            rtems_cache_flush_multiple_data_lines(flashing_from, chunk * 8);
> +
>             FLASH.MCR.B.EHV = 1;
>
> -            rtems_interrupt_enable(level);
>             while (FLASH.MCR.B.DONE == 0) {     /* Wait until done. */
>             }
> -            rtems_interrupt_disable(level);
>
>             peg = FLASH.MCR.B.PEG;              /* Save result. */
>             FLASH.MCR.B.EHV = 0;                /* Disable high voltage. */
>             FLASH.MCR.B.PGM = 0;
> -            rtems_interrupt_enable(level);
>
>             if (peg == 0) {
>                 if (p_fail) {
> --
> 1.7.1
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel

-- 
Joel Sherrill, Ph.D.             Director of Research & Development
joel.sherrill at OARcorp.com        On-Line Applications Research
Ask me about RTEMS: a free RTOS  Huntsville AL 35805
Support Available                (256) 722-9985



More information about the devel mailing list