Is it safe to attempt (and fail) to write to a const on an STM32?











up vote
0
down vote

favorite












So, we are experimenting with an approach to perform some matrix math. This is embedded, so memory is limited, and we will have large matrices so it helps us to keep some of them stored in flash rather than RAM.



I've written a matrix structure, two arrays (one const/flash and the other RAM), and a "modify" and "get" function. One matrix, I initialize to the RAM data, and the other matrix I initialize to the flash data, using a cast from const *f32 to *f32.



What I find is that when I run this code on my STM32 embedded processor, the RAM matrix is modifiable, and the matrix pointing to the flash data simply doesn't change (the set to 12.0 doesn't "take", the value remains 2.0).



(before change) a=2, b=2, (after change) c=2, d=12



This is acceptable behavior, by design we will not attempt to modify matrices of flash data, but if we make a mistake we don't want it to crash.



If I run the same code on my windows machine with Visual C++, however, I get an "access violation" when I attempt to run the code below, when I try to modify the const array to 12.0.



This is not surprising that Windows would object, but I'd like to understand the difference in behavior better. This seems related to CPU architecture. Is it safe, on our STM32, to let the code attempt to write to a const array and let it have no effect? Or are there side effects, or reasons to avoid this?



static const f32 constarray[9] = {1,2,3,1,2,3,1,2,3};
static f32 ramarray[9] = {1,2,3,1,2,3,1,2,3};

typedef struct {
u16 rows;
u16 cols;
f32 * mat;
} matrix_versatile;

void modify_versatile_matrix(matrix_versatile * m, uint16_t r, uint16_t c, double new_value)
{
m->mat[r * m->cols + c] = new_value;
}

double get_versatile_matrix_value(matrix_versatile * m, uint16_t r, uint16_t c)
{
return m->mat[r * m->cols + c];
}

double a;
double b;
double c;
double d;

int main(void)
{
matrix_versatile matrix_with_const_data;
matrix_versatile matrix_with_ram_data;

matrix_with_const_data.cols = 3;
matrix_with_const_data.rows = 3;
matrix_with_const_data.mat = (f32 *) constarray;

matrix_with_ram_data.cols = 3;
matrix_with_ram_data.rows = 3;
matrix_with_ram_data.mat = ramarray;

a = get_versatile_matrix_value(&matrix_with_const_data, 1, 1);
b = get_versatile_matrix_value(&matrix_with_ram_data, 1, 1);
modify_versatile_matrix(&matrix_with_const_data, 1, 1, 12.0);
modify_versatile_matrix(&matrix_with_ram_data, 1, 1, 12.0);
c = get_versatile_matrix_value(&matrix_with_const_data, 1, 1);
d = get_versatile_matrix_value(&matrix_with_ram_data, 1, 1);









share|improve this question




























    up vote
    0
    down vote

    favorite












    So, we are experimenting with an approach to perform some matrix math. This is embedded, so memory is limited, and we will have large matrices so it helps us to keep some of them stored in flash rather than RAM.



    I've written a matrix structure, two arrays (one const/flash and the other RAM), and a "modify" and "get" function. One matrix, I initialize to the RAM data, and the other matrix I initialize to the flash data, using a cast from const *f32 to *f32.



    What I find is that when I run this code on my STM32 embedded processor, the RAM matrix is modifiable, and the matrix pointing to the flash data simply doesn't change (the set to 12.0 doesn't "take", the value remains 2.0).



    (before change) a=2, b=2, (after change) c=2, d=12



    This is acceptable behavior, by design we will not attempt to modify matrices of flash data, but if we make a mistake we don't want it to crash.



    If I run the same code on my windows machine with Visual C++, however, I get an "access violation" when I attempt to run the code below, when I try to modify the const array to 12.0.



    This is not surprising that Windows would object, but I'd like to understand the difference in behavior better. This seems related to CPU architecture. Is it safe, on our STM32, to let the code attempt to write to a const array and let it have no effect? Or are there side effects, or reasons to avoid this?



    static const f32 constarray[9] = {1,2,3,1,2,3,1,2,3};
    static f32 ramarray[9] = {1,2,3,1,2,3,1,2,3};

    typedef struct {
    u16 rows;
    u16 cols;
    f32 * mat;
    } matrix_versatile;

    void modify_versatile_matrix(matrix_versatile * m, uint16_t r, uint16_t c, double new_value)
    {
    m->mat[r * m->cols + c] = new_value;
    }

    double get_versatile_matrix_value(matrix_versatile * m, uint16_t r, uint16_t c)
    {
    return m->mat[r * m->cols + c];
    }

    double a;
    double b;
    double c;
    double d;

    int main(void)
    {
    matrix_versatile matrix_with_const_data;
    matrix_versatile matrix_with_ram_data;

    matrix_with_const_data.cols = 3;
    matrix_with_const_data.rows = 3;
    matrix_with_const_data.mat = (f32 *) constarray;

    matrix_with_ram_data.cols = 3;
    matrix_with_ram_data.rows = 3;
    matrix_with_ram_data.mat = ramarray;

    a = get_versatile_matrix_value(&matrix_with_const_data, 1, 1);
    b = get_versatile_matrix_value(&matrix_with_ram_data, 1, 1);
    modify_versatile_matrix(&matrix_with_const_data, 1, 1, 12.0);
    modify_versatile_matrix(&matrix_with_ram_data, 1, 1, 12.0);
    c = get_versatile_matrix_value(&matrix_with_const_data, 1, 1);
    d = get_versatile_matrix_value(&matrix_with_ram_data, 1, 1);









    share|improve this question


























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      So, we are experimenting with an approach to perform some matrix math. This is embedded, so memory is limited, and we will have large matrices so it helps us to keep some of them stored in flash rather than RAM.



      I've written a matrix structure, two arrays (one const/flash and the other RAM), and a "modify" and "get" function. One matrix, I initialize to the RAM data, and the other matrix I initialize to the flash data, using a cast from const *f32 to *f32.



      What I find is that when I run this code on my STM32 embedded processor, the RAM matrix is modifiable, and the matrix pointing to the flash data simply doesn't change (the set to 12.0 doesn't "take", the value remains 2.0).



      (before change) a=2, b=2, (after change) c=2, d=12



      This is acceptable behavior, by design we will not attempt to modify matrices of flash data, but if we make a mistake we don't want it to crash.



      If I run the same code on my windows machine with Visual C++, however, I get an "access violation" when I attempt to run the code below, when I try to modify the const array to 12.0.



      This is not surprising that Windows would object, but I'd like to understand the difference in behavior better. This seems related to CPU architecture. Is it safe, on our STM32, to let the code attempt to write to a const array and let it have no effect? Or are there side effects, or reasons to avoid this?



      static const f32 constarray[9] = {1,2,3,1,2,3,1,2,3};
      static f32 ramarray[9] = {1,2,3,1,2,3,1,2,3};

      typedef struct {
      u16 rows;
      u16 cols;
      f32 * mat;
      } matrix_versatile;

      void modify_versatile_matrix(matrix_versatile * m, uint16_t r, uint16_t c, double new_value)
      {
      m->mat[r * m->cols + c] = new_value;
      }

      double get_versatile_matrix_value(matrix_versatile * m, uint16_t r, uint16_t c)
      {
      return m->mat[r * m->cols + c];
      }

      double a;
      double b;
      double c;
      double d;

      int main(void)
      {
      matrix_versatile matrix_with_const_data;
      matrix_versatile matrix_with_ram_data;

      matrix_with_const_data.cols = 3;
      matrix_with_const_data.rows = 3;
      matrix_with_const_data.mat = (f32 *) constarray;

      matrix_with_ram_data.cols = 3;
      matrix_with_ram_data.rows = 3;
      matrix_with_ram_data.mat = ramarray;

      a = get_versatile_matrix_value(&matrix_with_const_data, 1, 1);
      b = get_versatile_matrix_value(&matrix_with_ram_data, 1, 1);
      modify_versatile_matrix(&matrix_with_const_data, 1, 1, 12.0);
      modify_versatile_matrix(&matrix_with_ram_data, 1, 1, 12.0);
      c = get_versatile_matrix_value(&matrix_with_const_data, 1, 1);
      d = get_versatile_matrix_value(&matrix_with_ram_data, 1, 1);









      share|improve this question















      So, we are experimenting with an approach to perform some matrix math. This is embedded, so memory is limited, and we will have large matrices so it helps us to keep some of them stored in flash rather than RAM.



      I've written a matrix structure, two arrays (one const/flash and the other RAM), and a "modify" and "get" function. One matrix, I initialize to the RAM data, and the other matrix I initialize to the flash data, using a cast from const *f32 to *f32.



      What I find is that when I run this code on my STM32 embedded processor, the RAM matrix is modifiable, and the matrix pointing to the flash data simply doesn't change (the set to 12.0 doesn't "take", the value remains 2.0).



      (before change) a=2, b=2, (after change) c=2, d=12



      This is acceptable behavior, by design we will not attempt to modify matrices of flash data, but if we make a mistake we don't want it to crash.



      If I run the same code on my windows machine with Visual C++, however, I get an "access violation" when I attempt to run the code below, when I try to modify the const array to 12.0.



      This is not surprising that Windows would object, but I'd like to understand the difference in behavior better. This seems related to CPU architecture. Is it safe, on our STM32, to let the code attempt to write to a const array and let it have no effect? Or are there side effects, or reasons to avoid this?



      static const f32 constarray[9] = {1,2,3,1,2,3,1,2,3};
      static f32 ramarray[9] = {1,2,3,1,2,3,1,2,3};

      typedef struct {
      u16 rows;
      u16 cols;
      f32 * mat;
      } matrix_versatile;

      void modify_versatile_matrix(matrix_versatile * m, uint16_t r, uint16_t c, double new_value)
      {
      m->mat[r * m->cols + c] = new_value;
      }

      double get_versatile_matrix_value(matrix_versatile * m, uint16_t r, uint16_t c)
      {
      return m->mat[r * m->cols + c];
      }

      double a;
      double b;
      double c;
      double d;

      int main(void)
      {
      matrix_versatile matrix_with_const_data;
      matrix_versatile matrix_with_ram_data;

      matrix_with_const_data.cols = 3;
      matrix_with_const_data.rows = 3;
      matrix_with_const_data.mat = (f32 *) constarray;

      matrix_with_ram_data.cols = 3;
      matrix_with_ram_data.rows = 3;
      matrix_with_ram_data.mat = ramarray;

      a = get_versatile_matrix_value(&matrix_with_const_data, 1, 1);
      b = get_versatile_matrix_value(&matrix_with_ram_data, 1, 1);
      modify_versatile_matrix(&matrix_with_const_data, 1, 1, 12.0);
      modify_versatile_matrix(&matrix_with_ram_data, 1, 1, 12.0);
      c = get_versatile_matrix_value(&matrix_with_const_data, 1, 1);
      d = get_versatile_matrix_value(&matrix_with_ram_data, 1, 1);






      visual-c++ embedded stm32






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 8 at 20:21









      Clifford

      58k858124




      58k858124










      asked Nov 8 at 20:00









      Chris

      111222




      111222
























          2 Answers
          2






          active

          oldest

          votes

















          up vote
          5
          down vote














          but if we make a mistake we don't want it to crash.




          Attempting to write to ROM will not in itself cause a crash, but the code attempting to write it is by definition buggy and may crash in any case, and will certainly not behave as intended.



          It is almost entirely wrong thinking; if you have a bug, you really want it to crash during development, and not after deployment. If it silently does the wrong thing, you may never notice the bug, or the crash might occur somewhere other than in proximity of the bug, so be very hard to find.



          Architectures an MMU or MPU may issue an exception if you attempt to write to memory marked as read-only. That is what is happening in Windows. In that case it can be a useful debug aid given an exception handler that reports such errors by some means. In this case the error is reported exactly when it occurs, rather than crashing some time later when some invalid data is accessed or incorrect result acted upon.



          Some, but mot all STM32 parts include the MPU (application note)






          share|improve this answer























          • Got it. Yes, at development time we will check and double check that we are never attempting to modify a FLASH-based matrix. But I'm curious, you say our STM32 "may crash in any case"... can you expand on that, what might happen?
            – Chris
            Nov 8 at 20:37












          • In short, I guess I assumed that this was a feature, that the CPU was smart enough to realize that it was modifying FLASH and it would noop instead. But this is speculation. What is really happening, and how would it fail?
            – Chris
            Nov 8 at 20:43










          • Oh, and further on the development philosophy I think we will add a boolean to our matrix structure to indicate RW or RO, for further protection, so that even in the event of a mixup we do not attempt to write to FLASH and rely on this "noop" behavior. So mostly at this point I'm just curious: why does it have no effect, is this a feature, can we count on it, or is this behavior undefined, indeterminate, and could bite us? And if it bites us, how?
            – Chris
            Nov 8 at 20:48








          • 1




            @Chris The behaviour is determinate, documented, so you can count on it as a feature. The effect of writing a known value to a known address is completely predictable. RAM: value changes, FLASH: no change and status bit is set, memory mapped register: see the Reference Manual, unmapped area: Bus Fault. Problems start to happen when the address or the value is not predictable.
            – berendi
            Nov 8 at 22:04






          • 1




            @chris Defensive code is one thing, but your approach makes no sense - you are writing _more_software to check for software errors. What makes you think that if you expect to write broken software, writing yet more software will detect it!? A system of asserts on results or reconditions and unit testing is a more robust approach. You are proposing writing code to detect one specific type of code error; what about all the more likely errors. Moreover the error you have exemplified is down to poor coding practice - casting away a const. If you don't do that the compiler will catch it.
            – Clifford
            Nov 9 at 7:15


















          up vote
          1
          down vote













          The answer may depend on the series (STM32F1, STM32F4, STM32L1 etc), as they have somewhat different flash controllers.



          I've once made the same mistake on an STM32F429, and investigated a bit, so I can tell what would happen on an STM32F4.



          Probably nothing.



          The flash is by default protected, in order to be somewhat resilient to those kind of programming errors. In order to modify the flash, one has to write certain values to the FLASH->KEYR register. If the wrong value is written, then the flash will be locked until reset, so nothing really bad can happen unless the program writes 64 bits of correct values. No unexpected interrupts can happen, because the interrupt enable bit is protected by this key too. The attempt will set some error bits in FLASH->SR, so a program can check it and warn the user (preferably the tester).



          However if there is some code there (e.g. a bootloader, or logging something into flash) that is supposed to write something in the flash, i.e. it unlocks the flash with the correct keys, then bad things can happen.



          If the flash is left unlocked after a preceding write operation, then writing to a previously programmed area will change bits from 1 to 0, but not from 0 to 1. It means that the flash will contain the bitwise AND of the old and the newly written value.



          If the failed write attempt occurs first, and unlocked afterwards, then no legitimate write or erase operation would succeed unless the status bits are properly cleared first.



          If the intended and unintended accesses occur interleaved, e.g. in interrupt handlers, then all bets are off.





          Even if the values are in immutable flash memory, there can still be unexpected result. Consider this code



          int foo(int *array) {
          array[0] = 1;
          array[1] = 3;
          array[2] = 5;
          return array[0];
          }


          An optimizing compiler might recognize that the return value should always be 1, and emit code to that effect. Or it might not, and reload array[0] from wherever it is stored, possibly a different value from flash. It may behave differently in debug and release builds, or when the function is called from different places, as it might be inlined differently.





          If the pointer points to an unmapped area, neither RAM nor FLASH nor some memory mapped register, then a a fault will occur, and as the default fault handlers contain just an infinite loop, the program will hang unless it has a fault handler installed that can deal with the situation. Needless to say, overwriting random RAM areas or registers can result in barely predictable behaviour.





          UPDATE



          I've tried your code on actual hardware. When I ran it verbatim, the compiler (gcc-arm-none-eabi-7-2018-q2-update -O3 -lto) optimized away everything, since the variables were not used afterwards. Marking a, b, c, d as volatile resulted in c=2 and d=12, it was still considering the first array const, and no accesses to the arrays were generated. constarray did not show up in the map file at all, the linker had eliminated it completely.



          So I've tried a few things one at a time to force the optimizer to generate code that would actually access the arrays.




          • Disablig optimization (-O0)

          • Making all variables volatile

          • Inserting a couple of compile-time memory barriers (asm volatile("":::"memory");

          • Doing some complex calculations in the middle


          Any of these has produced varying effects on different MCUs, but they were always consistent on a single platform.





          • STM32F103: Hard Fault. Only halfword (16 bit) write accesses are allowed to the flash, 8 or 32 bits always result in a fault. When I've changed the data types to short, the code ran, of course without any effect on the flash.


          • STM32F417: Code runs, with no effects on the flash contents, but bits 6 and 7, PGPERR and PGSERR in FLASH->SR were set a few cycles after the first write attempt to constarray.


          • STM32L151: Code runs, with no effects on the flash controller status.






          share|improve this answer























          • The question appears to be about write access to a read-only address rather then more specifically about failure to write to flash memory because it is explicitly write-protected. Write protection is only relevant when programming flash; when not in programming mode, the access has no effect at all, unless the part has an MPU and the region is marked read-only. The title and code example refer to const rather then specifically flash memory an flash programming.
            – Clifford
            Nov 9 at 7:35












          • @Clifford const arrays are placed in the flash by the linker, unless one uses some really weird linker script or startup code. If the const qualifier is lost when passing the array address to a function that expects a non-const pointer parameter, and attempts to write to an array element, then it will try to write a value to an address in flash. Of course the flash contents would be left unchanged, but the flash controller sees it as a failed programming attempt, and sets the error flag in its status register.
            – berendi
            Nov 9 at 7:55










          • @Clifford It has once got me wondering why my code that deliberately writes the flash stops working when a certain unrelated function is invoked. Turned out the unrelated function had the same kind of bug as the code example in the question. Flash programming started to work when I've cleared FLASH->SR, and monitoring the status register has helped me to find the real bug.
            – berendi
            Nov 9 at 8:22












          • I disagree, there is no attempt to program the flash memory at runtime in the question. It is an important consideration if you are programming flash at runtime (a practice that has particular issues in STM32 in any case), but it clearly does not relate to this question.
            – Clifford
            Nov 9 at 9:02










          • @Clifford I've tried it on actual hardware, see my updated answer. The flash controller does not really care what the programmer was attempting to do, it sets the flags on write accesses. Or raises a fault.
            – berendi
            Nov 11 at 13:35











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53215281%2fis-it-safe-to-attempt-and-fail-to-write-to-a-const-on-an-stm32%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          5
          down vote














          but if we make a mistake we don't want it to crash.




          Attempting to write to ROM will not in itself cause a crash, but the code attempting to write it is by definition buggy and may crash in any case, and will certainly not behave as intended.



          It is almost entirely wrong thinking; if you have a bug, you really want it to crash during development, and not after deployment. If it silently does the wrong thing, you may never notice the bug, or the crash might occur somewhere other than in proximity of the bug, so be very hard to find.



          Architectures an MMU or MPU may issue an exception if you attempt to write to memory marked as read-only. That is what is happening in Windows. In that case it can be a useful debug aid given an exception handler that reports such errors by some means. In this case the error is reported exactly when it occurs, rather than crashing some time later when some invalid data is accessed or incorrect result acted upon.



          Some, but mot all STM32 parts include the MPU (application note)






          share|improve this answer























          • Got it. Yes, at development time we will check and double check that we are never attempting to modify a FLASH-based matrix. But I'm curious, you say our STM32 "may crash in any case"... can you expand on that, what might happen?
            – Chris
            Nov 8 at 20:37












          • In short, I guess I assumed that this was a feature, that the CPU was smart enough to realize that it was modifying FLASH and it would noop instead. But this is speculation. What is really happening, and how would it fail?
            – Chris
            Nov 8 at 20:43










          • Oh, and further on the development philosophy I think we will add a boolean to our matrix structure to indicate RW or RO, for further protection, so that even in the event of a mixup we do not attempt to write to FLASH and rely on this "noop" behavior. So mostly at this point I'm just curious: why does it have no effect, is this a feature, can we count on it, or is this behavior undefined, indeterminate, and could bite us? And if it bites us, how?
            – Chris
            Nov 8 at 20:48








          • 1




            @Chris The behaviour is determinate, documented, so you can count on it as a feature. The effect of writing a known value to a known address is completely predictable. RAM: value changes, FLASH: no change and status bit is set, memory mapped register: see the Reference Manual, unmapped area: Bus Fault. Problems start to happen when the address or the value is not predictable.
            – berendi
            Nov 8 at 22:04






          • 1




            @chris Defensive code is one thing, but your approach makes no sense - you are writing _more_software to check for software errors. What makes you think that if you expect to write broken software, writing yet more software will detect it!? A system of asserts on results or reconditions and unit testing is a more robust approach. You are proposing writing code to detect one specific type of code error; what about all the more likely errors. Moreover the error you have exemplified is down to poor coding practice - casting away a const. If you don't do that the compiler will catch it.
            – Clifford
            Nov 9 at 7:15















          up vote
          5
          down vote














          but if we make a mistake we don't want it to crash.




          Attempting to write to ROM will not in itself cause a crash, but the code attempting to write it is by definition buggy and may crash in any case, and will certainly not behave as intended.



          It is almost entirely wrong thinking; if you have a bug, you really want it to crash during development, and not after deployment. If it silently does the wrong thing, you may never notice the bug, or the crash might occur somewhere other than in proximity of the bug, so be very hard to find.



          Architectures an MMU or MPU may issue an exception if you attempt to write to memory marked as read-only. That is what is happening in Windows. In that case it can be a useful debug aid given an exception handler that reports such errors by some means. In this case the error is reported exactly when it occurs, rather than crashing some time later when some invalid data is accessed or incorrect result acted upon.



          Some, but mot all STM32 parts include the MPU (application note)






          share|improve this answer























          • Got it. Yes, at development time we will check and double check that we are never attempting to modify a FLASH-based matrix. But I'm curious, you say our STM32 "may crash in any case"... can you expand on that, what might happen?
            – Chris
            Nov 8 at 20:37












          • In short, I guess I assumed that this was a feature, that the CPU was smart enough to realize that it was modifying FLASH and it would noop instead. But this is speculation. What is really happening, and how would it fail?
            – Chris
            Nov 8 at 20:43










          • Oh, and further on the development philosophy I think we will add a boolean to our matrix structure to indicate RW or RO, for further protection, so that even in the event of a mixup we do not attempt to write to FLASH and rely on this "noop" behavior. So mostly at this point I'm just curious: why does it have no effect, is this a feature, can we count on it, or is this behavior undefined, indeterminate, and could bite us? And if it bites us, how?
            – Chris
            Nov 8 at 20:48








          • 1




            @Chris The behaviour is determinate, documented, so you can count on it as a feature. The effect of writing a known value to a known address is completely predictable. RAM: value changes, FLASH: no change and status bit is set, memory mapped register: see the Reference Manual, unmapped area: Bus Fault. Problems start to happen when the address or the value is not predictable.
            – berendi
            Nov 8 at 22:04






          • 1




            @chris Defensive code is one thing, but your approach makes no sense - you are writing _more_software to check for software errors. What makes you think that if you expect to write broken software, writing yet more software will detect it!? A system of asserts on results or reconditions and unit testing is a more robust approach. You are proposing writing code to detect one specific type of code error; what about all the more likely errors. Moreover the error you have exemplified is down to poor coding practice - casting away a const. If you don't do that the compiler will catch it.
            – Clifford
            Nov 9 at 7:15













          up vote
          5
          down vote










          up vote
          5
          down vote










          but if we make a mistake we don't want it to crash.




          Attempting to write to ROM will not in itself cause a crash, but the code attempting to write it is by definition buggy and may crash in any case, and will certainly not behave as intended.



          It is almost entirely wrong thinking; if you have a bug, you really want it to crash during development, and not after deployment. If it silently does the wrong thing, you may never notice the bug, or the crash might occur somewhere other than in proximity of the bug, so be very hard to find.



          Architectures an MMU or MPU may issue an exception if you attempt to write to memory marked as read-only. That is what is happening in Windows. In that case it can be a useful debug aid given an exception handler that reports such errors by some means. In this case the error is reported exactly when it occurs, rather than crashing some time later when some invalid data is accessed or incorrect result acted upon.



          Some, but mot all STM32 parts include the MPU (application note)






          share|improve this answer















          but if we make a mistake we don't want it to crash.




          Attempting to write to ROM will not in itself cause a crash, but the code attempting to write it is by definition buggy and may crash in any case, and will certainly not behave as intended.



          It is almost entirely wrong thinking; if you have a bug, you really want it to crash during development, and not after deployment. If it silently does the wrong thing, you may never notice the bug, or the crash might occur somewhere other than in proximity of the bug, so be very hard to find.



          Architectures an MMU or MPU may issue an exception if you attempt to write to memory marked as read-only. That is what is happening in Windows. In that case it can be a useful debug aid given an exception handler that reports such errors by some means. In this case the error is reported exactly when it occurs, rather than crashing some time later when some invalid data is accessed or incorrect result acted upon.



          Some, but mot all STM32 parts include the MPU (application note)







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 9 at 7:23

























          answered Nov 8 at 20:21









          Clifford

          58k858124




          58k858124












          • Got it. Yes, at development time we will check and double check that we are never attempting to modify a FLASH-based matrix. But I'm curious, you say our STM32 "may crash in any case"... can you expand on that, what might happen?
            – Chris
            Nov 8 at 20:37












          • In short, I guess I assumed that this was a feature, that the CPU was smart enough to realize that it was modifying FLASH and it would noop instead. But this is speculation. What is really happening, and how would it fail?
            – Chris
            Nov 8 at 20:43










          • Oh, and further on the development philosophy I think we will add a boolean to our matrix structure to indicate RW or RO, for further protection, so that even in the event of a mixup we do not attempt to write to FLASH and rely on this "noop" behavior. So mostly at this point I'm just curious: why does it have no effect, is this a feature, can we count on it, or is this behavior undefined, indeterminate, and could bite us? And if it bites us, how?
            – Chris
            Nov 8 at 20:48








          • 1




            @Chris The behaviour is determinate, documented, so you can count on it as a feature. The effect of writing a known value to a known address is completely predictable. RAM: value changes, FLASH: no change and status bit is set, memory mapped register: see the Reference Manual, unmapped area: Bus Fault. Problems start to happen when the address or the value is not predictable.
            – berendi
            Nov 8 at 22:04






          • 1




            @chris Defensive code is one thing, but your approach makes no sense - you are writing _more_software to check for software errors. What makes you think that if you expect to write broken software, writing yet more software will detect it!? A system of asserts on results or reconditions and unit testing is a more robust approach. You are proposing writing code to detect one specific type of code error; what about all the more likely errors. Moreover the error you have exemplified is down to poor coding practice - casting away a const. If you don't do that the compiler will catch it.
            – Clifford
            Nov 9 at 7:15


















          • Got it. Yes, at development time we will check and double check that we are never attempting to modify a FLASH-based matrix. But I'm curious, you say our STM32 "may crash in any case"... can you expand on that, what might happen?
            – Chris
            Nov 8 at 20:37












          • In short, I guess I assumed that this was a feature, that the CPU was smart enough to realize that it was modifying FLASH and it would noop instead. But this is speculation. What is really happening, and how would it fail?
            – Chris
            Nov 8 at 20:43










          • Oh, and further on the development philosophy I think we will add a boolean to our matrix structure to indicate RW or RO, for further protection, so that even in the event of a mixup we do not attempt to write to FLASH and rely on this "noop" behavior. So mostly at this point I'm just curious: why does it have no effect, is this a feature, can we count on it, or is this behavior undefined, indeterminate, and could bite us? And if it bites us, how?
            – Chris
            Nov 8 at 20:48








          • 1




            @Chris The behaviour is determinate, documented, so you can count on it as a feature. The effect of writing a known value to a known address is completely predictable. RAM: value changes, FLASH: no change and status bit is set, memory mapped register: see the Reference Manual, unmapped area: Bus Fault. Problems start to happen when the address or the value is not predictable.
            – berendi
            Nov 8 at 22:04






          • 1




            @chris Defensive code is one thing, but your approach makes no sense - you are writing _more_software to check for software errors. What makes you think that if you expect to write broken software, writing yet more software will detect it!? A system of asserts on results or reconditions and unit testing is a more robust approach. You are proposing writing code to detect one specific type of code error; what about all the more likely errors. Moreover the error you have exemplified is down to poor coding practice - casting away a const. If you don't do that the compiler will catch it.
            – Clifford
            Nov 9 at 7:15
















          Got it. Yes, at development time we will check and double check that we are never attempting to modify a FLASH-based matrix. But I'm curious, you say our STM32 "may crash in any case"... can you expand on that, what might happen?
          – Chris
          Nov 8 at 20:37






          Got it. Yes, at development time we will check and double check that we are never attempting to modify a FLASH-based matrix. But I'm curious, you say our STM32 "may crash in any case"... can you expand on that, what might happen?
          – Chris
          Nov 8 at 20:37














          In short, I guess I assumed that this was a feature, that the CPU was smart enough to realize that it was modifying FLASH and it would noop instead. But this is speculation. What is really happening, and how would it fail?
          – Chris
          Nov 8 at 20:43




          In short, I guess I assumed that this was a feature, that the CPU was smart enough to realize that it was modifying FLASH and it would noop instead. But this is speculation. What is really happening, and how would it fail?
          – Chris
          Nov 8 at 20:43












          Oh, and further on the development philosophy I think we will add a boolean to our matrix structure to indicate RW or RO, for further protection, so that even in the event of a mixup we do not attempt to write to FLASH and rely on this "noop" behavior. So mostly at this point I'm just curious: why does it have no effect, is this a feature, can we count on it, or is this behavior undefined, indeterminate, and could bite us? And if it bites us, how?
          – Chris
          Nov 8 at 20:48






          Oh, and further on the development philosophy I think we will add a boolean to our matrix structure to indicate RW or RO, for further protection, so that even in the event of a mixup we do not attempt to write to FLASH and rely on this "noop" behavior. So mostly at this point I'm just curious: why does it have no effect, is this a feature, can we count on it, or is this behavior undefined, indeterminate, and could bite us? And if it bites us, how?
          – Chris
          Nov 8 at 20:48






          1




          1




          @Chris The behaviour is determinate, documented, so you can count on it as a feature. The effect of writing a known value to a known address is completely predictable. RAM: value changes, FLASH: no change and status bit is set, memory mapped register: see the Reference Manual, unmapped area: Bus Fault. Problems start to happen when the address or the value is not predictable.
          – berendi
          Nov 8 at 22:04




          @Chris The behaviour is determinate, documented, so you can count on it as a feature. The effect of writing a known value to a known address is completely predictable. RAM: value changes, FLASH: no change and status bit is set, memory mapped register: see the Reference Manual, unmapped area: Bus Fault. Problems start to happen when the address or the value is not predictable.
          – berendi
          Nov 8 at 22:04




          1




          1




          @chris Defensive code is one thing, but your approach makes no sense - you are writing _more_software to check for software errors. What makes you think that if you expect to write broken software, writing yet more software will detect it!? A system of asserts on results or reconditions and unit testing is a more robust approach. You are proposing writing code to detect one specific type of code error; what about all the more likely errors. Moreover the error you have exemplified is down to poor coding practice - casting away a const. If you don't do that the compiler will catch it.
          – Clifford
          Nov 9 at 7:15




          @chris Defensive code is one thing, but your approach makes no sense - you are writing _more_software to check for software errors. What makes you think that if you expect to write broken software, writing yet more software will detect it!? A system of asserts on results or reconditions and unit testing is a more robust approach. You are proposing writing code to detect one specific type of code error; what about all the more likely errors. Moreover the error you have exemplified is down to poor coding practice - casting away a const. If you don't do that the compiler will catch it.
          – Clifford
          Nov 9 at 7:15












          up vote
          1
          down vote













          The answer may depend on the series (STM32F1, STM32F4, STM32L1 etc), as they have somewhat different flash controllers.



          I've once made the same mistake on an STM32F429, and investigated a bit, so I can tell what would happen on an STM32F4.



          Probably nothing.



          The flash is by default protected, in order to be somewhat resilient to those kind of programming errors. In order to modify the flash, one has to write certain values to the FLASH->KEYR register. If the wrong value is written, then the flash will be locked until reset, so nothing really bad can happen unless the program writes 64 bits of correct values. No unexpected interrupts can happen, because the interrupt enable bit is protected by this key too. The attempt will set some error bits in FLASH->SR, so a program can check it and warn the user (preferably the tester).



          However if there is some code there (e.g. a bootloader, or logging something into flash) that is supposed to write something in the flash, i.e. it unlocks the flash with the correct keys, then bad things can happen.



          If the flash is left unlocked after a preceding write operation, then writing to a previously programmed area will change bits from 1 to 0, but not from 0 to 1. It means that the flash will contain the bitwise AND of the old and the newly written value.



          If the failed write attempt occurs first, and unlocked afterwards, then no legitimate write or erase operation would succeed unless the status bits are properly cleared first.



          If the intended and unintended accesses occur interleaved, e.g. in interrupt handlers, then all bets are off.





          Even if the values are in immutable flash memory, there can still be unexpected result. Consider this code



          int foo(int *array) {
          array[0] = 1;
          array[1] = 3;
          array[2] = 5;
          return array[0];
          }


          An optimizing compiler might recognize that the return value should always be 1, and emit code to that effect. Or it might not, and reload array[0] from wherever it is stored, possibly a different value from flash. It may behave differently in debug and release builds, or when the function is called from different places, as it might be inlined differently.





          If the pointer points to an unmapped area, neither RAM nor FLASH nor some memory mapped register, then a a fault will occur, and as the default fault handlers contain just an infinite loop, the program will hang unless it has a fault handler installed that can deal with the situation. Needless to say, overwriting random RAM areas or registers can result in barely predictable behaviour.





          UPDATE



          I've tried your code on actual hardware. When I ran it verbatim, the compiler (gcc-arm-none-eabi-7-2018-q2-update -O3 -lto) optimized away everything, since the variables were not used afterwards. Marking a, b, c, d as volatile resulted in c=2 and d=12, it was still considering the first array const, and no accesses to the arrays were generated. constarray did not show up in the map file at all, the linker had eliminated it completely.



          So I've tried a few things one at a time to force the optimizer to generate code that would actually access the arrays.




          • Disablig optimization (-O0)

          • Making all variables volatile

          • Inserting a couple of compile-time memory barriers (asm volatile("":::"memory");

          • Doing some complex calculations in the middle


          Any of these has produced varying effects on different MCUs, but they were always consistent on a single platform.





          • STM32F103: Hard Fault. Only halfword (16 bit) write accesses are allowed to the flash, 8 or 32 bits always result in a fault. When I've changed the data types to short, the code ran, of course without any effect on the flash.


          • STM32F417: Code runs, with no effects on the flash contents, but bits 6 and 7, PGPERR and PGSERR in FLASH->SR were set a few cycles after the first write attempt to constarray.


          • STM32L151: Code runs, with no effects on the flash controller status.






          share|improve this answer























          • The question appears to be about write access to a read-only address rather then more specifically about failure to write to flash memory because it is explicitly write-protected. Write protection is only relevant when programming flash; when not in programming mode, the access has no effect at all, unless the part has an MPU and the region is marked read-only. The title and code example refer to const rather then specifically flash memory an flash programming.
            – Clifford
            Nov 9 at 7:35












          • @Clifford const arrays are placed in the flash by the linker, unless one uses some really weird linker script or startup code. If the const qualifier is lost when passing the array address to a function that expects a non-const pointer parameter, and attempts to write to an array element, then it will try to write a value to an address in flash. Of course the flash contents would be left unchanged, but the flash controller sees it as a failed programming attempt, and sets the error flag in its status register.
            – berendi
            Nov 9 at 7:55










          • @Clifford It has once got me wondering why my code that deliberately writes the flash stops working when a certain unrelated function is invoked. Turned out the unrelated function had the same kind of bug as the code example in the question. Flash programming started to work when I've cleared FLASH->SR, and monitoring the status register has helped me to find the real bug.
            – berendi
            Nov 9 at 8:22












          • I disagree, there is no attempt to program the flash memory at runtime in the question. It is an important consideration if you are programming flash at runtime (a practice that has particular issues in STM32 in any case), but it clearly does not relate to this question.
            – Clifford
            Nov 9 at 9:02










          • @Clifford I've tried it on actual hardware, see my updated answer. The flash controller does not really care what the programmer was attempting to do, it sets the flags on write accesses. Or raises a fault.
            – berendi
            Nov 11 at 13:35















          up vote
          1
          down vote













          The answer may depend on the series (STM32F1, STM32F4, STM32L1 etc), as they have somewhat different flash controllers.



          I've once made the same mistake on an STM32F429, and investigated a bit, so I can tell what would happen on an STM32F4.



          Probably nothing.



          The flash is by default protected, in order to be somewhat resilient to those kind of programming errors. In order to modify the flash, one has to write certain values to the FLASH->KEYR register. If the wrong value is written, then the flash will be locked until reset, so nothing really bad can happen unless the program writes 64 bits of correct values. No unexpected interrupts can happen, because the interrupt enable bit is protected by this key too. The attempt will set some error bits in FLASH->SR, so a program can check it and warn the user (preferably the tester).



          However if there is some code there (e.g. a bootloader, or logging something into flash) that is supposed to write something in the flash, i.e. it unlocks the flash with the correct keys, then bad things can happen.



          If the flash is left unlocked after a preceding write operation, then writing to a previously programmed area will change bits from 1 to 0, but not from 0 to 1. It means that the flash will contain the bitwise AND of the old and the newly written value.



          If the failed write attempt occurs first, and unlocked afterwards, then no legitimate write or erase operation would succeed unless the status bits are properly cleared first.



          If the intended and unintended accesses occur interleaved, e.g. in interrupt handlers, then all bets are off.





          Even if the values are in immutable flash memory, there can still be unexpected result. Consider this code



          int foo(int *array) {
          array[0] = 1;
          array[1] = 3;
          array[2] = 5;
          return array[0];
          }


          An optimizing compiler might recognize that the return value should always be 1, and emit code to that effect. Or it might not, and reload array[0] from wherever it is stored, possibly a different value from flash. It may behave differently in debug and release builds, or when the function is called from different places, as it might be inlined differently.





          If the pointer points to an unmapped area, neither RAM nor FLASH nor some memory mapped register, then a a fault will occur, and as the default fault handlers contain just an infinite loop, the program will hang unless it has a fault handler installed that can deal with the situation. Needless to say, overwriting random RAM areas or registers can result in barely predictable behaviour.





          UPDATE



          I've tried your code on actual hardware. When I ran it verbatim, the compiler (gcc-arm-none-eabi-7-2018-q2-update -O3 -lto) optimized away everything, since the variables were not used afterwards. Marking a, b, c, d as volatile resulted in c=2 and d=12, it was still considering the first array const, and no accesses to the arrays were generated. constarray did not show up in the map file at all, the linker had eliminated it completely.



          So I've tried a few things one at a time to force the optimizer to generate code that would actually access the arrays.




          • Disablig optimization (-O0)

          • Making all variables volatile

          • Inserting a couple of compile-time memory barriers (asm volatile("":::"memory");

          • Doing some complex calculations in the middle


          Any of these has produced varying effects on different MCUs, but they were always consistent on a single platform.





          • STM32F103: Hard Fault. Only halfword (16 bit) write accesses are allowed to the flash, 8 or 32 bits always result in a fault. When I've changed the data types to short, the code ran, of course without any effect on the flash.


          • STM32F417: Code runs, with no effects on the flash contents, but bits 6 and 7, PGPERR and PGSERR in FLASH->SR were set a few cycles after the first write attempt to constarray.


          • STM32L151: Code runs, with no effects on the flash controller status.






          share|improve this answer























          • The question appears to be about write access to a read-only address rather then more specifically about failure to write to flash memory because it is explicitly write-protected. Write protection is only relevant when programming flash; when not in programming mode, the access has no effect at all, unless the part has an MPU and the region is marked read-only. The title and code example refer to const rather then specifically flash memory an flash programming.
            – Clifford
            Nov 9 at 7:35












          • @Clifford const arrays are placed in the flash by the linker, unless one uses some really weird linker script or startup code. If the const qualifier is lost when passing the array address to a function that expects a non-const pointer parameter, and attempts to write to an array element, then it will try to write a value to an address in flash. Of course the flash contents would be left unchanged, but the flash controller sees it as a failed programming attempt, and sets the error flag in its status register.
            – berendi
            Nov 9 at 7:55










          • @Clifford It has once got me wondering why my code that deliberately writes the flash stops working when a certain unrelated function is invoked. Turned out the unrelated function had the same kind of bug as the code example in the question. Flash programming started to work when I've cleared FLASH->SR, and monitoring the status register has helped me to find the real bug.
            – berendi
            Nov 9 at 8:22












          • I disagree, there is no attempt to program the flash memory at runtime in the question. It is an important consideration if you are programming flash at runtime (a practice that has particular issues in STM32 in any case), but it clearly does not relate to this question.
            – Clifford
            Nov 9 at 9:02










          • @Clifford I've tried it on actual hardware, see my updated answer. The flash controller does not really care what the programmer was attempting to do, it sets the flags on write accesses. Or raises a fault.
            – berendi
            Nov 11 at 13:35













          up vote
          1
          down vote










          up vote
          1
          down vote









          The answer may depend on the series (STM32F1, STM32F4, STM32L1 etc), as they have somewhat different flash controllers.



          I've once made the same mistake on an STM32F429, and investigated a bit, so I can tell what would happen on an STM32F4.



          Probably nothing.



          The flash is by default protected, in order to be somewhat resilient to those kind of programming errors. In order to modify the flash, one has to write certain values to the FLASH->KEYR register. If the wrong value is written, then the flash will be locked until reset, so nothing really bad can happen unless the program writes 64 bits of correct values. No unexpected interrupts can happen, because the interrupt enable bit is protected by this key too. The attempt will set some error bits in FLASH->SR, so a program can check it and warn the user (preferably the tester).



          However if there is some code there (e.g. a bootloader, or logging something into flash) that is supposed to write something in the flash, i.e. it unlocks the flash with the correct keys, then bad things can happen.



          If the flash is left unlocked after a preceding write operation, then writing to a previously programmed area will change bits from 1 to 0, but not from 0 to 1. It means that the flash will contain the bitwise AND of the old and the newly written value.



          If the failed write attempt occurs first, and unlocked afterwards, then no legitimate write or erase operation would succeed unless the status bits are properly cleared first.



          If the intended and unintended accesses occur interleaved, e.g. in interrupt handlers, then all bets are off.





          Even if the values are in immutable flash memory, there can still be unexpected result. Consider this code



          int foo(int *array) {
          array[0] = 1;
          array[1] = 3;
          array[2] = 5;
          return array[0];
          }


          An optimizing compiler might recognize that the return value should always be 1, and emit code to that effect. Or it might not, and reload array[0] from wherever it is stored, possibly a different value from flash. It may behave differently in debug and release builds, or when the function is called from different places, as it might be inlined differently.





          If the pointer points to an unmapped area, neither RAM nor FLASH nor some memory mapped register, then a a fault will occur, and as the default fault handlers contain just an infinite loop, the program will hang unless it has a fault handler installed that can deal with the situation. Needless to say, overwriting random RAM areas or registers can result in barely predictable behaviour.





          UPDATE



          I've tried your code on actual hardware. When I ran it verbatim, the compiler (gcc-arm-none-eabi-7-2018-q2-update -O3 -lto) optimized away everything, since the variables were not used afterwards. Marking a, b, c, d as volatile resulted in c=2 and d=12, it was still considering the first array const, and no accesses to the arrays were generated. constarray did not show up in the map file at all, the linker had eliminated it completely.



          So I've tried a few things one at a time to force the optimizer to generate code that would actually access the arrays.




          • Disablig optimization (-O0)

          • Making all variables volatile

          • Inserting a couple of compile-time memory barriers (asm volatile("":::"memory");

          • Doing some complex calculations in the middle


          Any of these has produced varying effects on different MCUs, but they were always consistent on a single platform.





          • STM32F103: Hard Fault. Only halfword (16 bit) write accesses are allowed to the flash, 8 or 32 bits always result in a fault. When I've changed the data types to short, the code ran, of course without any effect on the flash.


          • STM32F417: Code runs, with no effects on the flash contents, but bits 6 and 7, PGPERR and PGSERR in FLASH->SR were set a few cycles after the first write attempt to constarray.


          • STM32L151: Code runs, with no effects on the flash controller status.






          share|improve this answer














          The answer may depend on the series (STM32F1, STM32F4, STM32L1 etc), as they have somewhat different flash controllers.



          I've once made the same mistake on an STM32F429, and investigated a bit, so I can tell what would happen on an STM32F4.



          Probably nothing.



          The flash is by default protected, in order to be somewhat resilient to those kind of programming errors. In order to modify the flash, one has to write certain values to the FLASH->KEYR register. If the wrong value is written, then the flash will be locked until reset, so nothing really bad can happen unless the program writes 64 bits of correct values. No unexpected interrupts can happen, because the interrupt enable bit is protected by this key too. The attempt will set some error bits in FLASH->SR, so a program can check it and warn the user (preferably the tester).



          However if there is some code there (e.g. a bootloader, or logging something into flash) that is supposed to write something in the flash, i.e. it unlocks the flash with the correct keys, then bad things can happen.



          If the flash is left unlocked after a preceding write operation, then writing to a previously programmed area will change bits from 1 to 0, but not from 0 to 1. It means that the flash will contain the bitwise AND of the old and the newly written value.



          If the failed write attempt occurs first, and unlocked afterwards, then no legitimate write or erase operation would succeed unless the status bits are properly cleared first.



          If the intended and unintended accesses occur interleaved, e.g. in interrupt handlers, then all bets are off.





          Even if the values are in immutable flash memory, there can still be unexpected result. Consider this code



          int foo(int *array) {
          array[0] = 1;
          array[1] = 3;
          array[2] = 5;
          return array[0];
          }


          An optimizing compiler might recognize that the return value should always be 1, and emit code to that effect. Or it might not, and reload array[0] from wherever it is stored, possibly a different value from flash. It may behave differently in debug and release builds, or when the function is called from different places, as it might be inlined differently.





          If the pointer points to an unmapped area, neither RAM nor FLASH nor some memory mapped register, then a a fault will occur, and as the default fault handlers contain just an infinite loop, the program will hang unless it has a fault handler installed that can deal with the situation. Needless to say, overwriting random RAM areas or registers can result in barely predictable behaviour.





          UPDATE



          I've tried your code on actual hardware. When I ran it verbatim, the compiler (gcc-arm-none-eabi-7-2018-q2-update -O3 -lto) optimized away everything, since the variables were not used afterwards. Marking a, b, c, d as volatile resulted in c=2 and d=12, it was still considering the first array const, and no accesses to the arrays were generated. constarray did not show up in the map file at all, the linker had eliminated it completely.



          So I've tried a few things one at a time to force the optimizer to generate code that would actually access the arrays.




          • Disablig optimization (-O0)

          • Making all variables volatile

          • Inserting a couple of compile-time memory barriers (asm volatile("":::"memory");

          • Doing some complex calculations in the middle


          Any of these has produced varying effects on different MCUs, but they were always consistent on a single platform.





          • STM32F103: Hard Fault. Only halfword (16 bit) write accesses are allowed to the flash, 8 or 32 bits always result in a fault. When I've changed the data types to short, the code ran, of course without any effect on the flash.


          • STM32F417: Code runs, with no effects on the flash contents, but bits 6 and 7, PGPERR and PGSERR in FLASH->SR were set a few cycles after the first write attempt to constarray.


          • STM32L151: Code runs, with no effects on the flash controller status.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 11 at 13:30

























          answered Nov 8 at 21:34









          berendi

          3,8911624




          3,8911624












          • The question appears to be about write access to a read-only address rather then more specifically about failure to write to flash memory because it is explicitly write-protected. Write protection is only relevant when programming flash; when not in programming mode, the access has no effect at all, unless the part has an MPU and the region is marked read-only. The title and code example refer to const rather then specifically flash memory an flash programming.
            – Clifford
            Nov 9 at 7:35












          • @Clifford const arrays are placed in the flash by the linker, unless one uses some really weird linker script or startup code. If the const qualifier is lost when passing the array address to a function that expects a non-const pointer parameter, and attempts to write to an array element, then it will try to write a value to an address in flash. Of course the flash contents would be left unchanged, but the flash controller sees it as a failed programming attempt, and sets the error flag in its status register.
            – berendi
            Nov 9 at 7:55










          • @Clifford It has once got me wondering why my code that deliberately writes the flash stops working when a certain unrelated function is invoked. Turned out the unrelated function had the same kind of bug as the code example in the question. Flash programming started to work when I've cleared FLASH->SR, and monitoring the status register has helped me to find the real bug.
            – berendi
            Nov 9 at 8:22












          • I disagree, there is no attempt to program the flash memory at runtime in the question. It is an important consideration if you are programming flash at runtime (a practice that has particular issues in STM32 in any case), but it clearly does not relate to this question.
            – Clifford
            Nov 9 at 9:02










          • @Clifford I've tried it on actual hardware, see my updated answer. The flash controller does not really care what the programmer was attempting to do, it sets the flags on write accesses. Or raises a fault.
            – berendi
            Nov 11 at 13:35


















          • The question appears to be about write access to a read-only address rather then more specifically about failure to write to flash memory because it is explicitly write-protected. Write protection is only relevant when programming flash; when not in programming mode, the access has no effect at all, unless the part has an MPU and the region is marked read-only. The title and code example refer to const rather then specifically flash memory an flash programming.
            – Clifford
            Nov 9 at 7:35












          • @Clifford const arrays are placed in the flash by the linker, unless one uses some really weird linker script or startup code. If the const qualifier is lost when passing the array address to a function that expects a non-const pointer parameter, and attempts to write to an array element, then it will try to write a value to an address in flash. Of course the flash contents would be left unchanged, but the flash controller sees it as a failed programming attempt, and sets the error flag in its status register.
            – berendi
            Nov 9 at 7:55










          • @Clifford It has once got me wondering why my code that deliberately writes the flash stops working when a certain unrelated function is invoked. Turned out the unrelated function had the same kind of bug as the code example in the question. Flash programming started to work when I've cleared FLASH->SR, and monitoring the status register has helped me to find the real bug.
            – berendi
            Nov 9 at 8:22












          • I disagree, there is no attempt to program the flash memory at runtime in the question. It is an important consideration if you are programming flash at runtime (a practice that has particular issues in STM32 in any case), but it clearly does not relate to this question.
            – Clifford
            Nov 9 at 9:02










          • @Clifford I've tried it on actual hardware, see my updated answer. The flash controller does not really care what the programmer was attempting to do, it sets the flags on write accesses. Or raises a fault.
            – berendi
            Nov 11 at 13:35
















          The question appears to be about write access to a read-only address rather then more specifically about failure to write to flash memory because it is explicitly write-protected. Write protection is only relevant when programming flash; when not in programming mode, the access has no effect at all, unless the part has an MPU and the region is marked read-only. The title and code example refer to const rather then specifically flash memory an flash programming.
          – Clifford
          Nov 9 at 7:35






          The question appears to be about write access to a read-only address rather then more specifically about failure to write to flash memory because it is explicitly write-protected. Write protection is only relevant when programming flash; when not in programming mode, the access has no effect at all, unless the part has an MPU and the region is marked read-only. The title and code example refer to const rather then specifically flash memory an flash programming.
          – Clifford
          Nov 9 at 7:35














          @Clifford const arrays are placed in the flash by the linker, unless one uses some really weird linker script or startup code. If the const qualifier is lost when passing the array address to a function that expects a non-const pointer parameter, and attempts to write to an array element, then it will try to write a value to an address in flash. Of course the flash contents would be left unchanged, but the flash controller sees it as a failed programming attempt, and sets the error flag in its status register.
          – berendi
          Nov 9 at 7:55




          @Clifford const arrays are placed in the flash by the linker, unless one uses some really weird linker script or startup code. If the const qualifier is lost when passing the array address to a function that expects a non-const pointer parameter, and attempts to write to an array element, then it will try to write a value to an address in flash. Of course the flash contents would be left unchanged, but the flash controller sees it as a failed programming attempt, and sets the error flag in its status register.
          – berendi
          Nov 9 at 7:55












          @Clifford It has once got me wondering why my code that deliberately writes the flash stops working when a certain unrelated function is invoked. Turned out the unrelated function had the same kind of bug as the code example in the question. Flash programming started to work when I've cleared FLASH->SR, and monitoring the status register has helped me to find the real bug.
          – berendi
          Nov 9 at 8:22






          @Clifford It has once got me wondering why my code that deliberately writes the flash stops working when a certain unrelated function is invoked. Turned out the unrelated function had the same kind of bug as the code example in the question. Flash programming started to work when I've cleared FLASH->SR, and monitoring the status register has helped me to find the real bug.
          – berendi
          Nov 9 at 8:22














          I disagree, there is no attempt to program the flash memory at runtime in the question. It is an important consideration if you are programming flash at runtime (a practice that has particular issues in STM32 in any case), but it clearly does not relate to this question.
          – Clifford
          Nov 9 at 9:02




          I disagree, there is no attempt to program the flash memory at runtime in the question. It is an important consideration if you are programming flash at runtime (a practice that has particular issues in STM32 in any case), but it clearly does not relate to this question.
          – Clifford
          Nov 9 at 9:02












          @Clifford I've tried it on actual hardware, see my updated answer. The flash controller does not really care what the programmer was attempting to do, it sets the flags on write accesses. Or raises a fault.
          – berendi
          Nov 11 at 13:35




          @Clifford I've tried it on actual hardware, see my updated answer. The flash controller does not really care what the programmer was attempting to do, it sets the flags on write accesses. Or raises a fault.
          – berendi
          Nov 11 at 13:35


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53215281%2fis-it-safe-to-attempt-and-fail-to-write-to-a-const-on-an-stm32%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Florida Star v. B. J. F.

          Error while running script in elastic search , gateway timeout

          Adding quotations to stringified JSON object values