Bayley Wang
/
dc_motor_control
bad dc motor controller with current mode
Revision 0:2b1edabdd26b, committed 2019-02-03
- Comitter:
- bwang
- Date:
- Sun Feb 03 03:38:05 2019 +0000
- Commit message:
- first commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CommandProcessor/CommandProcessor.cpp Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,37 @@ +#include "mbed.h" +#include "CommandProcessor.h" +#include "globals.h" + +void processCmd(Serial *pc,char *buf) { + char *tokens[10]; + int len = tokenize(buf, tokens, 10); + + switch (len) { + case 1: + if (strcmp(tokens[0], "clear") == 0) cmd_clear(pc); + else if (strcmp(tokens[0], "help") == 0) cmd_help(pc); + else if (strcmp(tokens[0], "reload") == 0) cmd_reload(pc, pref); + else if (strcmp(tokens[0], "load") == 0) cmd_reload(pc, pref); + else if (strcmp(tokens[0], "flush") == 0) cmd_flush(pc, pref); + else if (strcmp(tokens[0], "src") == 0) cmd_ls2(pc, tokens[0]); + else if (strcmp(tokens[0], "op") == 0) cmd_ls2(pc, tokens[0]); + else if (strcmp(tokens[0], "ls") == 0) cmd_ls(pc); + else pc->printf("%s\n", "Bad command"); + break; + case 2: + if (strcmp(tokens[0], "setp") == 0) cmd_setp(pc, tokens[1]); + else if (strcmp(tokens[0], "freq") == 0) cmd_freq(pc, tokens[1]); + else if (strcmp(tokens[0], "ls") == 0) cmd_ls2(pc, tokens[1]); + else if (strcmp(tokens[0], "src") == 0) cmd_src(pc, tokens[1]); + else if (strcmp(tokens[0], "op") == 0) cmd_op(pc, tokens[1]); + else if (strcmp(tokens[0], "query") == 0) cmd_query(pc, tokens[1]); + else pc->printf("%s\n", "Bad command"); + break; + case 3: + if (strcmp(tokens[0], "set") == 0) cmd_set(pc, tokens[1], tokens[2]); + break; + default: + pc->printf("%s\n", "Bad command"); + break; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CommandProcessor/CommandProcessor.h Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,36 @@ +#ifndef __COMMAND_PROCESSOR_H +#define __COMMAND_PROCESSOR_H + +#include "mbed.h" +#include "PreferenceWriter.h" + +void processCmd(Serial *pc, char *buf); + +/*---mode switching---*/ +void cmd_setp(Serial *pc, char *buf); +void cmd_freq(Serial *pc, char *buf); +void cmd_src(Serial *pc, char *buf); +void cmd_op(Serial *pc, char *buf); +void cmd_ls(Serial *pc); + +/*---setting/getting parameters---*/ +void cmd_ls2(Serial *pc, char *buf); +void cmd_set(Serial *pc, char *buf, char *val); +void cmd_flush(Serial *pc, PreferenceWriter *pref); +void cmd_reload(Serial *pc, PreferenceWriter *pref); +void cmd_query(Serial *pc, char *buf); + +/*---system commands---*/ +void cmd_clear(Serial *pc); +void cmd_help(Serial *pc); + +/*---internal functions---*/ +int tokenize(char *buf, char **out, int max); +int str_to_src(char *buf); +char* src_to_str(int n); +float* checkf(char *s); +int* checkn(char *s); +char* op_to_str(int n); +int str_to_op(char *buf); + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CommandProcessor/cmd_helpers.cpp Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,88 @@ +#include "mbed.h" +#include "CommandProcessor.h" + +#include "globals.h" + +int tokenize(char *buf, char **out, int max) { + char* tok; + int k = 0; + + tok = strtok(buf, " "); + + while(tok != NULL && k < max) { + out[k] = tok; + k++; + tok = strtok(NULL, " "); + } + return k; +} + +#define __check(x) if(strcmp(s, #x) == 0) return &x + +float* checkf(char *s) { + __check(KP); + __check(KI); + __check(I_LIMIT); + __check(F_SW); + __check(THROTTLE_DEADBAND); + __check(ANALOG_THROTTLE_LOW); + __check(ANALOG_THROTTLE_HI); + return NULL; +} + +int* checkn(char *s) { + return NULL; +} + +#define __strcase(in, out) case in:strcpy(result, out);break +#define __intcase(in, out) if (strcmp(buf, in) == 0) return out + +char* src_to_str(int n) { + static char result[12]; + switch (n) { + __strcase(CMD_SRC_RC, "RC"); + __strcase(CMD_SRC_ANALOG, "Analog"); + __strcase(CMD_SRC_TERMINAL, "Terminal"); + __strcase(CMD_SRC_SERIAL, "Serial"); + __strcase(CMD_SRC_CAN, "CAN"); + __strcase(CMD_SRC_INTERNAL, "Internal"); + default: + strcpy(result, "Invalid"); + break; + } + return result; +} + +int str_to_src(char *buf) { + __intcase("rc", CMD_SRC_RC); + __intcase("analog", CMD_SRC_ANALOG); + __intcase("terminal", CMD_SRC_TERMINAL); + __intcase("serial", CMD_SRC_SERIAL); + __intcase("can", CMD_SRC_CAN); + __intcase("internal", CMD_SRC_INTERNAL); + return -1; +} + + +char* op_to_str(int n) { + static char result[24]; + switch(n) { + __strcase(OP_TORQUE, "Torque loop"); + __strcase(OP_DRIVING, "Driving map"); + __strcase(OP_SPEED, "Open-loop speed"); + __strcase(OP_POSITION, "Position loop"); + default: + strcpy(result, "Invalid"); + break; + } + return result; +} + +int str_to_op(char *buf) { + __intcase("torque", OP_TORQUE); + __intcase("driving", OP_DRIVING); + __intcase("speed", OP_SPEED); + __intcase("pos", OP_POSITION); + __intcase("position", OP_POSITION); + return -1; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CommandProcessor/cmd_mode.cpp Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,39 @@ +#include "mbed.h" +#include "CommandProcessor.h" + +#include "globals.h" + +void cmd_setp(Serial *pc, char *buf) { + float dtc = atof(buf); + if (dtc < 0.0f) dtc = 0.0f; + if (dtc > 1.0f) dtc = 1.0f; + user_cmd = dtc; +} + +void cmd_freq(Serial *pc, char *buf) { + float freq = atof(buf); + if (freq < 500.0f) freq = 500.0f; + if (freq > 10000.0f) freq = 10000.0f; + TIM1->ARR = (int) ((float) 9e7 / freq); +} + +void cmd_src(Serial *pc, char *buf) { + int n = str_to_src(buf); + if (n < 0) { + pc->printf("%s\n", "Invalid Source"); + return; + } + BREMS_src = n; + pc->printf("Set source to %s\n", src_to_str(n)); +} + +void cmd_op(Serial *pc, char *buf) { + int n = str_to_op(buf); + if (n < 0) { + pc->printf("%s\n", "Invalid operation"); + return; + } + BREMS_op = n; + pc->printf("Set operation to %s\n", op_to_str(n)); +} + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CommandProcessor/cmd_set_get.cpp Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,63 @@ +#include "mbed.h" +#include "CommandProcessor.h" +#include "globals.h" + +#define FPRINT(a) pc->printf("%s: %f\n", #a, a) +#define DPRINT(a) pc->printf("%s: %d\n", #a, a) + +void cmd_ls(Serial *pc) { + DPRINT(PREFS_VALID); + FPRINT(I_LIMIT); + FPRINT(KP); + FPRINT(KI); + FPRINT(F_SW); + FPRINT(THROTTLE_DEADBAND); + FPRINT(ANALOG_THROTTLE_LOW); + FPRINT(ANALOG_THROTTLE_HI); +} + +void cmd_ls2(Serial *pc, char *buf) { + if (strcmp(buf, "src") == 0) { + pc->printf("%s\n", src_to_str(BREMS_src)); + return; + } + if (strcmp(buf, "op") == 0) { + pc->printf("%s\n", op_to_str(BREMS_op)); + return; + } + + float *fptr = checkf(buf); + if (fptr != NULL) pc->printf("%s: %f\n", buf, *fptr); + int *nptr = NULL; + if (fptr == NULL) nptr = checkn(buf); + if (nptr != NULL) pc->printf("%s: %d\n", buf, *nptr); + if (nptr == NULL && fptr == NULL) pc->printf("%s\n", "No Such Parameter"); +} + +void cmd_set(Serial *pc, char *buf, char *val) { + float *fptr = checkf(buf); + if (fptr != NULL) *fptr = (float) (atof(val)); + int *nptr = NULL; + if (fptr == NULL) nptr = checkn(buf); + if (nptr != NULL) *nptr = (int) (atoi(val)); + if (nptr != NULL || fptr != NULL) cmd_ls2(pc, buf); + if (nptr == NULL && fptr == NULL) pc->printf("%s\n", "No Such Parameter"); +} + +void cmd_flush(Serial *pc, PreferenceWriter *pref) { + if (!pref->ready()) pref->open(); + PREFS_VALID = 1; + pref->flush(); +} + +void cmd_reload(Serial *pc, PreferenceWriter *pref) { + pref->load(); + if (PREFS_VALID) pc->printf("Flash Values Loaded\n"); +} + +void cmd_query(Serial *pc, char *buf) { + if (strcmp(buf, "i") == 0) pc->printf("%f\n", current); + else if (strcmp(buf, "cmd") == 0) pc->printf("%f\n", throttle); + else if (strcmp(buf, "v") == 0) pc->printf("%f\n", vout); + else pc->printf("%s\n", "No such parameter"); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CommandProcessor/cmd_sys.cpp Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,11 @@ +#include "mbed.h" +#include "CommandProcessor.h" + +void cmd_clear(Serial *pc) { + pc->printf("\e[1;1H\e[2J"); +} + +void cmd_help(Serial *pc) { + pc->printf("%s\n", "setp <float>: set a duty cycle between 0.0 and 1.0"); + pc->printf("%s\n", "freq <float>: set a frequency between 500.0Hz and 10000.0Hz"); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FastPWM.lib Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/benkatz/code/FastPWM3/#51c979bca21e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Filter/Filter.cpp Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,21 @@ +#include "mbed.h" +#include "math.h" +#include "Filter.h" + +MedianFilter::MedianFilter(int length) { + buf = new fCircularBuffer(length, true); +} + +float MedianFilter::update(float x) { + buf->add(x); + return buf->median(); +} + +MovingAverageFilter::MovingAverageFilter(int length) { + buf = new fCircularBuffer(length, false); +} + +float MovingAverageFilter::update(float x) { + buf->add(x); + return buf->mean(); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Filter/Filter.h Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,55 @@ +#ifndef __FILTER_H +#define __FILTER_H + +#include "mbed.h" +#include "math.h" + +class fCircularBuffer { +public: + fCircularBuffer(int length, bool use_median); + float oldest() {if (oldest_index >= 0) return buf[oldest_index]; return 0.0f;} + float newest() {if (newest_index >= 0) return buf[newest_index]; return 0.0f;} + int length() {return _length;} + void add(float x); /*recomputes mean, median - O(length) time*/ + float &at(int index); +public: + float &operator[](int index) {return at(index);} +public: + /*O(1) time*/ + float mean(); + float median(); +private: + int _length; + bool _use_median; + int oldest_index, newest_index, num; + double sum; +private: + float *buf; + float *sorted; +}; + +class Filter { +public: + virtual float update(float x) = 0; + virtual float read() = 0; +}; + +class MedianFilter : public Filter { +public: + MedianFilter(int length); + virtual float update(float x); + virtual float read() {return buf->median();} +private: + fCircularBuffer *buf; +}; + +class MovingAverageFilter : public Filter { +public: + MovingAverageFilter(int length); + virtual float update(float x); + virtual float read() {return buf->mean();} +private: + fCircularBuffer *buf; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Filter/fCircularBuffer.cpp Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,152 @@ +#include "mbed.h" +#include "math.h" +#include "Filter.h" + +fCircularBuffer::fCircularBuffer(int length, bool use_median) { + _length = length; + _use_median = use_median; + + oldest_index = 0; + newest_index = -1; + num = 0; + sum = 0.0f; + + buf = (float*)malloc(_length * sizeof(float)); + sorted = (float*)malloc(_length * sizeof(float)); + for (int i = 0; i < _length; i++) { + buf[i] = 0.0f; + sorted[i] = 0.0f; + } +} + +float &fCircularBuffer::at(int index) { + int actual = oldest_index + index; + if (actual >= _length) actual -= _length; + return buf[actual]; +} + +void fCircularBuffer::add(float x) { + if (num < _length) { + newest_index++; + buf[newest_index] = x; + sum += x; + num++; + + if (!_use_median || _length < 4) return; + + /*insert x into sorted array*/ + int i = num - 1; + while (i > 0 && sorted[i - 1] > x) { + sorted[i] = sorted[i - 1]; + i--; + } + sorted[i] = x; + } else { + /*update circular buffer*/ + float oldest = buf[oldest_index]; + + sum -= buf[oldest_index]; + oldest_index++; + if (oldest_index >= _length) oldest_index -= _length; + + newest_index++; + if (newest_index >= _length) newest_index -= _length; + buf[newest_index] = x; + + sum += x; + + if (!_use_median || _length < 4) return; + + /*find sorted index of oldest element*/ + int removed; + for (removed = 0; removed < _length; removed++) { + if (sorted[removed] == oldest) break; + } + + /*insert x*/ + int i; + if (removed == _length - 1) { + i = _length - 1; + while (i > 0 && sorted[i - 1] > x) { + sorted[i] = sorted[i - 1]; + i--; + } + sorted[i] = x; + } else if (removed == 0) { + i = 0; + while (i < _length - 1 && sorted[i + 1] < x) { + sorted[i] = sorted[i + 1]; + i++; + } + sorted[i] = x; + } else if (sorted[removed - 1] <= x && sorted[removed + 1] >= x) { + sorted[removed] = x; + } else if (sorted[removed - 1] > x) { + i = removed; + while (i > 0 && sorted[i - 1] > x) { + sorted[i] = sorted[i - 1]; + i--; + } + sorted[i] = x; + } else { + i = removed; + while (i < _length - 1 && sorted[i + 1] < x) { + sorted[i] = sorted[i + 1]; + i++; + } + sorted[i] = x; + } + } +} + +float fCircularBuffer::mean() { + return sum / num; +} + +float median3(float *buf) { + if (buf[0] > buf[1]) { + if (buf[1] > buf[2]) { + return buf[1]; + } else if (buf[0] > buf[2]) { + return buf[2]; + } else { + return buf[0]; + } + } else { + if (buf[0] > buf[2]) { + return buf[0]; + } else if (buf[1] > buf[2]) { + return buf[2]; + } else { + return buf[1]; + } + } +} +float fCircularBuffer::median() { + if (_length == 1) { + return buf[0]; + } + if (_length == 2) { + if (num < 2) return buf[0]; + return (buf[0] + buf[1]) / 2.0f; + } + if (_length == 3) { + if (num < 2) return buf[0]; + if (num == 2) return (buf[0] + buf[1]) / 2.0f; + return median3(buf); + } + if (num < _length) { + if (num % 2 == 1) { + return sorted[(num - 1) / 2]; + } else { + return (sorted[num / 2] + sorted[num / 2 - 1]) / 2.0f; + } + } + else { + if (_length % 2 == 1) { + return sorted[(_length - 1) / 2]; + } else { + return (sorted[_length / 2] + sorted[_length / 2 - 1]) / 2.0f; + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PreferenceWriter/FlashWriter.cpp Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,53 @@ +#include "stm32f4xx_flash.h" +#include "FlashWriter.h" + +FlashWriter::FlashWriter(int sector) { + if (sector > 7) sector = 7; + __sector = sector; + __base = __SECTOR_ADDRS[sector]; + __ready = false; +} + +bool FlashWriter::ready() { + return __ready; +} + +void FlashWriter::open() { + FLASH_Unlock(); + FLASH_ClearFlag( FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); + FLASH_EraseSector(__SECTORS[__sector], VoltageRange_3); + __ready = true; +} + +void FlashWriter::write(uint32_t index, int x) { + union {int a; uint32_t b;}; + a = x; + FLASH_ProgramWord(__base + 4 * index, b); +} + +void FlashWriter::write(uint32_t index, unsigned int x) { + FLASH_ProgramWord(__base + 4 * index, x); +} + +void FlashWriter::write(uint32_t index, float x) { + union {float a; uint32_t b;}; + a = x; + FLASH_ProgramWord(__base + 4 * index, b); +} + +void FlashWriter::close() { + FLASH_Lock(); + __ready = false; +} + +int flashReadInt(uint32_t sector, uint32_t index) { + return *(int*) (__SECTOR_ADDRS[sector] + 4 * index); +} + +uint32_t flashReadUint(uint32_t sector, uint32_t index) { + return *(uint32_t*) (__SECTOR_ADDRS[sector] + 4 * index); +} + +float flashReadFloat(uint32_t sector, uint32_t index) { + return *(float*) (__SECTOR_ADDRS[sector] + 4 * index); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PreferenceWriter/FlashWriter.h Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,39 @@ +#ifndef __FLASHWRITER_H +#define __FLASHWRITER_H + +#include "stm32f4xx_flash.h" + +/* Base address of the Flash sectors */ +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */ + +static uint32_t __SECTOR_ADDRS[] = {ADDR_FLASH_SECTOR_0, ADDR_FLASH_SECTOR_1, ADDR_FLASH_SECTOR_2, ADDR_FLASH_SECTOR_3, + ADDR_FLASH_SECTOR_4, ADDR_FLASH_SECTOR_5, ADDR_FLASH_SECTOR_6, ADDR_FLASH_SECTOR_7}; +static uint32_t __SECTORS[] = {FLASH_Sector_0, FLASH_Sector_1, FLASH_Sector_2, FLASH_Sector_3, + FLASH_Sector_4, FLASH_Sector_6, FLASH_Sector_6, FLASH_Sector_7}; +class FlashWriter { +public: + FlashWriter(int sector); + void open(); + bool ready(); + void write(uint32_t index, int x); + void write(uint32_t index, unsigned int x); + void write(uint32_t index, float x); + void close(); +private: + uint32_t __base; + uint32_t __sector; + bool __ready; +}; + +int flashReadInt(uint32_t sector, uint32_t index); +uint32_t flashReadUint(uint32_t sector, uint32_t index); +float flashReadFloat(uint32_t sector, uint32_t index); + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PreferenceWriter/PreferenceWriter.cpp Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,56 @@ +#include "PreferenceWriter.h" +#include "FlashWriter.h" + +#include "globals.h" + +float __float_reg[64]; +int __int_reg[64]; + +PreferenceWriter::PreferenceWriter(uint32_t sector) { + writer = new FlashWriter(sector); + __sector = sector; + __ready = false; +} + +void PreferenceWriter::open() { + writer->open(); + __ready = true; +} + +bool PreferenceWriter::ready() { + return __ready; +} + +void PreferenceWriter::write(int x, int index) { + __int_reg[index] = x; +} + +void PreferenceWriter::write(float x, int index) { + __float_reg[index] = x; +} + +void PreferenceWriter::flush() { + int offs; + for (offs = 0; offs < 64; offs++) { + writer->write(offs, __int_reg[offs]); + } + for (; offs < 128; offs++) { + writer->write(offs, __float_reg[offs - 64]); + } + __ready = false; +} + +void PreferenceWriter::load() { + int offs; + for (offs = 0; offs < 64; offs++) { + __int_reg[offs] = flashReadInt(__sector, offs); + } + for(; offs < 128; offs++) { + __float_reg[offs - 64] = flashReadFloat(__sector, offs); + } +} + +void PreferenceWriter::close() { + __ready = false; + writer->close(); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PreferenceWriter/PreferenceWriter.h Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,23 @@ +#ifndef __PREFERENCE_WRITER_H +#define __PREFERENCE_WRITER_H + +#include "mbed.h" +#include "FlashWriter.h" + +class PreferenceWriter { +public: + PreferenceWriter(uint32_t sector); + void open(); + bool ready(); + void write(int x, int index); + void write(float x, int index); + void flush(); + void load(); + void close(); +private: + FlashWriter *writer; + uint32_t __sector; + bool __ready; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PreferenceWriter/stm32f4xx_flash.c Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,1616 @@ +/** + ****************************************************************************** + * @file stm32f4xx_flash.c + * @author MCD Application Team + * @version V1.7.1 + * @date 20-May-2016 + * @brief This file provides firmware functions to manage the following + * functionalities of the FLASH peripheral: + * + FLASH Interface configuration + * + FLASH Memory Programming + * + Option Bytes Programming + * + Interrupts and flags management + * + @verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] + This driver provides functions to configure and program the FLASH memory + of all STM32F4xx devices. These functions are split in 4 groups: + + (#) FLASH Interface configuration functions: this group includes the + management of the following features: + (++) Set the latency + (++) Enable/Disable the prefetch buffer + (++) Enable/Disable the Instruction cache and the Data cache + (++) Reset the Instruction cache and the Data cache + + (#) FLASH Memory Programming functions: this group includes all needed + functions to erase and program the main memory: + (++) Lock and Unlock the FLASH interface + (++) Erase function: Erase sector, erase all sectors + (++) Program functions: byte, half word, word and double word + + (#) Option Bytes Programming functions: this group includes all needed + functions to manage the Option Bytes: + (++) Set/Reset the write protection + (++) Set the Read protection Level + (++) Set the BOR level + (++) Program the user Option Bytes + (++) Launch the Option Bytes loader + + (#) Interrupts and flags management functions: this group + includes all needed functions to: + (++) Enable/Disable the FLASH interrupt sources + (++) Get flags status + (++) Clear flags + (++) Get FLASH operation status + (++) Wait for last FLASH operation + @endverbatim + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_flash.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup FLASH + * @brief FLASH driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define SECTOR_MASK ((uint32_t)0xFFFFFF07) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup FLASH_Private_Functions + * @{ + */ + +/** @defgroup FLASH_Group1 FLASH Interface configuration functions + * @brief FLASH Interface configuration functions + * + +@verbatim + =============================================================================== + ##### FLASH Interface configuration functions ##### + =============================================================================== + [..] + This group includes the following functions: + (+) void FLASH_SetLatency(uint32_t FLASH_Latency) + To correctly read data from FLASH memory, the number of wait states (LATENCY) + must be correctly programmed according to the frequency of the CPU clock + (HCLK) and the supply voltage of the device. + [..] + For STM32F405xx/07xx and STM32F415xx/17xx devices + +-------------------------------------------------------------------------------------+ + | Latency | HCLK clock frequency (MHz) | + | |---------------------------------------------------------------------| + | | voltage range | voltage range | voltage range | voltage range | + | | 2.7 V - 3.6 V | 2.4 V - 2.7 V | 2.1 V - 2.4 V | 1.8 V - 2.1 V | + |---------------|----------------|----------------|-----------------|-----------------| + |0WS(1CPU cycle)|0 < HCLK <= 30 |0 < HCLK <= 24 |0 < HCLK <= 22 |0 < HCLK <= 20 | + |---------------|----------------|----------------|-----------------|-----------------| + |1WS(2CPU cycle)|30 < HCLK <= 60 |24 < HCLK <= 48 |22 < HCLK <= 44 |20 < HCLK <= 40 | + |---------------|----------------|----------------|-----------------|-----------------| + |2WS(3CPU cycle)|60 < HCLK <= 90 |48 < HCLK <= 72 |44 < HCLK <= 66 |40 < HCLK <= 60 | + |---------------|----------------|----------------|-----------------|-----------------| + |3WS(4CPU cycle)|90 < HCLK <= 120|72 < HCLK <= 96 |66 < HCLK <= 88 |60 < HCLK <= 80 | + |---------------|----------------|----------------|-----------------|-----------------| + |4WS(5CPU cycle)|120< HCLK <= 150|96 < HCLK <= 120|88 < HCLK <= 110 |80 < HCLK <= 100 | + |---------------|----------------|----------------|-----------------|-----------------| + |5WS(6CPU cycle)|150< HCLK <= 168|120< HCLK <= 144|110 < HCLK <= 132|100 < HCLK <= 120| + |---------------|----------------|----------------|-----------------|-----------------| + |6WS(7CPU cycle)| NA |144< HCLK <= 168|132 < HCLK <= 154|120 < HCLK <= 140| + |---------------|----------------|----------------|-----------------|-----------------| + |7WS(8CPU cycle)| NA | NA |154 < HCLK <= 168|140 < HCLK <= 160| + +---------------|----------------|----------------|-----------------|-----------------+ + + [..] + For STM32F42xxx/43xxx devices + +-------------------------------------------------------------------------------------+ + | Latency | HCLK clock frequency (MHz) | + | |---------------------------------------------------------------------| + | | voltage range | voltage range | voltage range | voltage range | + | | 2.7 V - 3.6 V | 2.4 V - 2.7 V | 2.1 V - 2.4 V | 1.8 V - 2.1 V | + |---------------|----------------|----------------|-----------------|-----------------| + |0WS(1CPU cycle)|0 < HCLK <= 30 |0 < HCLK <= 24 |0 < HCLK <= 22 |0 < HCLK <= 20 | + |---------------|----------------|----------------|-----------------|-----------------| + |1WS(2CPU cycle)|30 < HCLK <= 60 |24 < HCLK <= 48 |22 < HCLK <= 44 |20 < HCLK <= 40 | + |---------------|----------------|----------------|-----------------|-----------------| + |2WS(3CPU cycle)|60 < HCLK <= 90 |48 < HCLK <= 72 |44 < HCLK <= 66 |40 < HCLK <= 60 | + |---------------|----------------|----------------|-----------------|-----------------| + |3WS(4CPU cycle)|90 < HCLK <= 120|72 < HCLK <= 96 |66 < HCLK <= 88 |60 < HCLK <= 80 | + |---------------|----------------|----------------|-----------------|-----------------| + |4WS(5CPU cycle)|120< HCLK <= 150|96 < HCLK <= 120|88 < HCLK <= 110 |80 < HCLK <= 100 | + |---------------|----------------|----------------|-----------------|-----------------| + |5WS(6CPU cycle)|120< HCLK <= 180|120< HCLK <= 144|110 < HCLK <= 132|100 < HCLK <= 120| + |---------------|----------------|----------------|-----------------|-----------------| + |6WS(7CPU cycle)| NA |144< HCLK <= 168|132 < HCLK <= 154|120 < HCLK <= 140| + |---------------|----------------|----------------|-----------------|-----------------| + |7WS(8CPU cycle)| NA |168< HCLK <= 180|154 < HCLK <= 176|140 < HCLK <= 160| + |---------------|----------------|----------------|-----------------|-----------------| + |8WS(9CPU cycle)| NA | NA |176 < HCLK <= 180|160 < HCLK <= 168| + +-------------------------------------------------------------------------------------+ + + [..] + For STM32F401x devices + +-------------------------------------------------------------------------------------+ + | Latency | HCLK clock frequency (MHz) | + | |---------------------------------------------------------------------| + | | voltage range | voltage range | voltage range | voltage range | + | | 2.7 V - 3.6 V | 2.4 V - 2.7 V | 2.1 V - 2.4 V | 1.8 V - 2.1 V | + |---------------|----------------|----------------|-----------------|-----------------| + |0WS(1CPU cycle)|0 < HCLK <= 30 |0 < HCLK <= 24 |0 < HCLK <= 22 |0 < HCLK <= 20 | + |---------------|----------------|----------------|-----------------|-----------------| + |1WS(2CPU cycle)|30 < HCLK <= 60 |24 < HCLK <= 48 |22 < HCLK <= 44 |20 < HCLK <= 40 | + |---------------|----------------|----------------|-----------------|-----------------| + |2WS(3CPU cycle)|60 < HCLK <= 84 |48 < HCLK <= 72 |44 < HCLK <= 66 |40 < HCLK <= 60 | + |---------------|----------------|----------------|-----------------|-----------------| + |3WS(4CPU cycle)| NA |72 < HCLK <= 84 |66 < HCLK <= 84 |60 < HCLK <= 80 | + |---------------|----------------|----------------|-----------------|-----------------| + |4WS(5CPU cycle)| NA | NA | NA |80 < HCLK <= 84 | + +-------------------------------------------------------------------------------------+ + + [..] + For STM32F410xx/STM32F411xE devices + +-------------------------------------------------------------------------------------+ + | Latency | HCLK clock frequency (MHz) | + | |---------------------------------------------------------------------| + | | voltage range | voltage range | voltage range | voltage range | + | | 2.7 V - 3.6 V | 2.4 V - 2.7 V | 2.1 V - 2.4 V | 1.8 V - 2.1 V | + |---------------|----------------|----------------|-----------------|-----------------| + |0WS(1CPU cycle)|0 < HCLK <= 30 |0 < HCLK <= 24 |0 < HCLK <= 18 |0 < HCLK <= 16 | + |---------------|----------------|----------------|-----------------|-----------------| + |1WS(2CPU cycle)|30 < HCLK <= 64 |24 < HCLK <= 48 |18 < HCLK <= 36 |16 < HCLK <= 32 | + |---------------|----------------|----------------|-----------------|-----------------| + |2WS(3CPU cycle)|64 < HCLK <= 90 |48 < HCLK <= 72 |36 < HCLK <= 54 |32 < HCLK <= 48 | + |---------------|----------------|----------------|-----------------|-----------------| + |3WS(4CPU cycle)|90 < HCLK <= 100|72 < HCLK <= 96 |54 < HCLK <= 72 |48 < HCLK <= 64 | + |---------------|----------------|----------------|-----------------|-----------------| + |4WS(5CPU cycle)| NA |96 < HCLK <= 100|72 < HCLK <= 90 |64 < HCLK <= 80 | + |---------------|----------------|----------------|-----------------|-----------------| + |5WS(6CPU cycle)| NA | NA |90 < HCLK <= 100 |80 < HCLK <= 96 | + |---------------|----------------|----------------|-----------------|-----------------| + |6WS(7CPU cycle)| NA | NA | NA |96 < HCLK <= 100 | + +-------------------------------------------------------------------------------------+ + + [..] + +-------------------------------------------------------------------------------------------------------------------+ + | | voltage range | voltage range | voltage range | voltage range | voltage range 2.7 V - 3.6 V | + | | 2.7 V - 3.6 V | 2.4 V - 2.7 V | 2.1 V - 2.4 V | 1.8 V - 2.1 V | with External Vpp = 9V | + |---------------|----------------|----------------|-----------------|-----------------|-----------------------------| + |Max Parallelism| x32 | x16 | x8 | x64 | + |---------------|----------------|----------------|-----------------|-----------------|-----------------------------| + |PSIZE[1:0] | 10 | 01 | 00 | 11 | + +-------------------------------------------------------------------------------------------------------------------+ + + -@- On STM32F405xx/407xx and STM32F415xx/417xx devices: + (++) when VOS = '0' Scale 2 mode, the maximum value of fHCLK = 144MHz. + (++) when VOS = '1' Scale 1 mode, the maximum value of fHCLK = 168MHz. + [..] + On STM32F42xxx/43xxx devices: + (++) when VOS[1:0] = '0x01' Scale 3 mode, the maximum value of fHCLK is 120MHz. + (++) when VOS[1:0] = '0x10' Scale 2 mode, the maximum value of fHCLK is 144MHz if OverDrive OFF and 168MHz if OverDrive ON. + (++) when VOS[1:0] = '0x11' Scale 1 mode, the maximum value of fHCLK is 168MHz if OverDrive OFF and 180MHz if OverDrive ON. + [..] + On STM32F401x devices: + (++) when VOS[1:0] = '0x01' Scale 3 mode, the maximum value of fHCLK is 60MHz. + (++) when VOS[1:0] = '0x10' Scale 2 mode, the maximum value of fHCLK is 84MHz. + [..] + On STM32F410xx/STM32F411xE devices: + (++) when VOS[1:0] = '0x01' Scale 3 mode, the maximum value of fHCLK is 64MHz. + (++) when VOS[1:0] = '0x10' Scale 2 mode, the maximum value of fHCLK is 84MHz. + (++) when VOS[1:0] = '0x11' Scale 1 mode, the maximum value of fHCLK is 100MHz. + + For more details please refer product DataSheet + You can use PWR_MainRegulatorModeConfig() function to control VOS bits. + + (+) void FLASH_PrefetchBufferCmd(FunctionalState NewState) + (+) void FLASH_InstructionCacheCmd(FunctionalState NewState) + (+) void FLASH_DataCacheCmd(FunctionalState NewState) + (+) void FLASH_InstructionCacheReset(void) + (+) void FLASH_DataCacheReset(void) + + [..] + The unlock sequence is not needed for these functions. + +@endverbatim + * @{ + */ + +/** + * @brief Sets the code latency value. + * @param FLASH_Latency: specifies the FLASH Latency value. + * This parameter can be one of the following values: + * @arg FLASH_Latency_0: FLASH Zero Latency cycle + * @arg FLASH_Latency_1: FLASH One Latency cycle + * @arg FLASH_Latency_2: FLASH Two Latency cycles + * @arg FLASH_Latency_3: FLASH Three Latency cycles + * @arg FLASH_Latency_4: FLASH Four Latency cycles + * @arg FLASH_Latency_5: FLASH Five Latency cycles + * @arg FLASH_Latency_6: FLASH Six Latency cycles + * @arg FLASH_Latency_7: FLASH Seven Latency cycles + * @arg FLASH_Latency_8: FLASH Eight Latency cycles + * @arg FLASH_Latency_9: FLASH Nine Latency cycles + * @arg FLASH_Latency_10: FLASH Teen Latency cycles + * @arg FLASH_Latency_11: FLASH Eleven Latency cycles + * @arg FLASH_Latency_12: FLASH Twelve Latency cycles + * @arg FLASH_Latency_13: FLASH Thirteen Latency cycles + * @arg FLASH_Latency_14: FLASH Fourteen Latency cycles + * @arg FLASH_Latency_15: FLASH Fifteen Latency cycles + * + * @note For STM32F405xx/407xx, STM32F415xx/417xx, STM32F401xx/411xE and STM32F412xG devices + * this parameter can be a value between FLASH_Latency_0 and FLASH_Latency_7. + * + * @note For STM32F42xxx/43xxx devices this parameter can be a value between + * FLASH_Latency_0 and FLASH_Latency_15. + * + * @retval None + */ +void FLASH_SetLatency(uint32_t FLASH_Latency) +{ + /* Check the parameters */ + assert_param(IS_FLASH_LATENCY(FLASH_Latency)); + + /* Perform Byte access to FLASH_ACR[8:0] to set the Latency value */ + *(__IO uint8_t *)ACR_BYTE0_ADDRESS = (uint8_t)FLASH_Latency; +} + +/** + * @brief Enables or disables the Prefetch Buffer. + * @param NewState: new state of the Prefetch Buffer. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_PrefetchBufferCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + /* Enable or disable the Prefetch Buffer */ + if(NewState != DISABLE) + { + FLASH->ACR |= FLASH_ACR_PRFTEN; + } + else + { + FLASH->ACR &= (~FLASH_ACR_PRFTEN); + } +} + +/** + * @brief Enables or disables the Instruction Cache feature. + * @param NewState: new state of the Instruction Cache. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_InstructionCacheCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if(NewState != DISABLE) + { + FLASH->ACR |= FLASH_ACR_ICEN; + } + else + { + FLASH->ACR &= (~FLASH_ACR_ICEN); + } +} + +/** + * @brief Enables or disables the Data Cache feature. + * @param NewState: new state of the Data Cache. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_DataCacheCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if(NewState != DISABLE) + { + FLASH->ACR |= FLASH_ACR_DCEN; + } + else + { + FLASH->ACR &= (~FLASH_ACR_DCEN); + } +} + +/** + * @brief Resets the Instruction Cache. + * @note This function must be used only when the Instruction Cache is disabled. + * @param None + * @retval None + */ +void FLASH_InstructionCacheReset(void) +{ + FLASH->ACR |= FLASH_ACR_ICRST; +} + +/** + * @brief Resets the Data Cache. + * @note This function must be used only when the Data Cache is disabled. + * @param None + * @retval None + */ +void FLASH_DataCacheReset(void) +{ + FLASH->ACR |= FLASH_ACR_DCRST; +} + +/** + * @} + */ + +/** @defgroup FLASH_Group2 FLASH Memory Programming functions + * @brief FLASH Memory Programming functions + * +@verbatim + =============================================================================== + ##### FLASH Memory Programming functions ##### + =============================================================================== + [..] + This group includes the following functions: + (+) void FLASH_Unlock(void) + (+) void FLASH_Lock(void) + (+) FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange) + (+) FLASH_Status FLASH_EraseAllSectors(uint8_t VoltageRange) + (+) FLASH_Status FLASH_ProgramDoubleWord(uint32_t Address, uint64_t Data) + (+) FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data) + (+) FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) + (+) FLASH_Status FLASH_ProgramByte(uint32_t Address, uint8_t Data) + The following functions can be used only for STM32F42xxx/43xxx devices. + (+) FLASH_Status FLASH_EraseAllBank1Sectors(uint8_t VoltageRange) + (+) FLASH_Status FLASH_EraseAllBank2Sectors(uint8_t VoltageRange) + [..] + Any operation of erase or program should follow these steps: + (#) Call the FLASH_Unlock() function to enable the FLASH control register access + + (#) Call the desired function to erase sector(s) or program data + + (#) Call the FLASH_Lock() function to disable the FLASH control register access + (recommended to protect the FLASH memory against possible unwanted operation) + +@endverbatim + * @{ + */ + +/** + * @brief Unlocks the FLASH control register access + * @param None + * @retval None + */ +void FLASH_Unlock(void) +{ + if((FLASH->CR & FLASH_CR_LOCK) != RESET) + { + /* Authorize the FLASH Registers access */ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + } +} + +/** + * @brief Locks the FLASH control register access + * @param None + * @retval None + */ +void FLASH_Lock(void) +{ + /* Set the LOCK Bit to lock the FLASH Registers access */ + FLASH->CR |= FLASH_CR_LOCK; +} + +/** + * @brief Erases a specified FLASH Sector. + * + * @note If an erase and a program operations are requested simultaneously, + * the erase operation is performed before the program one. + * + * @param FLASH_Sector: The Sector number to be erased. + * + * @note For STM32F405xx/407xx and STM32F415xx/417xx devices this parameter can + * be a value between FLASH_Sector_0 and FLASH_Sector_11. + * + * For STM32F42xxx/43xxx devices this parameter can be a value between + * FLASH_Sector_0 and FLASH_Sector_23. + * + * For STM32F401xx devices this parameter can be a value between + * FLASH_Sector_0 and FLASH_Sector_5. + * + * For STM32F411xE and STM32F412xG devices this parameter can be a value between + * FLASH_Sector_0 and FLASH_Sector_7. + * + * For STM32F410xx devices this parameter can be a value between + * FLASH_Sector_0 and FLASH_Sector_4. + * + * @param VoltageRange: The device voltage range which defines the erase parallelism. + * This parameter can be one of the following values: + * @arg VoltageRange_1: when the device voltage range is 1.8V to 2.1V, + * the operation will be done by byte (8-bit) + * @arg VoltageRange_2: when the device voltage range is 2.1V to 2.7V, + * the operation will be done by half word (16-bit) + * @arg VoltageRange_3: when the device voltage range is 2.7V to 3.6V, + * the operation will be done by word (32-bit) + * @arg VoltageRange_4: when the device voltage range is 2.7V to 3.6V + External Vpp, + * the operation will be done by double word (64-bit) + * + * @retval FLASH Status: The returned value can be: FLASH_BUSY2, FLASH_ERROR_PROGRAM2, + * FLASH_ERROR_WRP2, FLASH_ERROR_OPERATION2 or FLASH_COMPLETE2. + */ +FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange) +{ + uint32_t tmp_psize = 0x0; + FLASH_Status status = FLASH_COMPLETE2; + + /* Check the parameters */ + assert_param(IS_FLASH_SECTOR(FLASH_Sector)); + assert_param(IS_VOLTAGERANGE(VoltageRange)); + + if(VoltageRange == VoltageRange_1) + { + tmp_psize = FLASH_PSIZE_BYTE; + } + else if(VoltageRange == VoltageRange_2) + { + tmp_psize = FLASH_PSIZE_HALF_WORD; + } + else if(VoltageRange == VoltageRange_3) + { + tmp_psize = FLASH_PSIZE_WORD; + } + else + { + tmp_psize = FLASH_PSIZE_DOUBLE_WORD; + } + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + if(status == FLASH_COMPLETE2) + { + /* if the previous operation is completed, proceed to erase the sector */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= tmp_psize; + FLASH->CR &= SECTOR_MASK; + FLASH->CR |= FLASH_CR_SER | FLASH_Sector; + FLASH->CR |= FLASH_CR_STRT; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + /* if the erase operation is completed, disable the SER Bit */ + FLASH->CR &= (~FLASH_CR_SER); + FLASH->CR &= SECTOR_MASK; + } + /* Return the Erase Status */ + return status; +} + +/** + * @brief Erases all FLASH Sectors. + * + * @note If an erase and a program operations are requested simultaneously, + * the erase operation is performed before the program one. + * + * @param VoltageRange: The device voltage range which defines the erase parallelism. + * This parameter can be one of the following values: + * @arg VoltageRange_1: when the device voltage range is 1.8V to 2.1V, + * the operation will be done by byte (8-bit) + * @arg VoltageRange_2: when the device voltage range is 2.1V to 2.7V, + * the operation will be done by half word (16-bit) + * @arg VoltageRange_3: when the device voltage range is 2.7V to 3.6V, + * the operation will be done by word (32-bit) + * @arg VoltageRange_4: when the device voltage range is 2.7V to 3.6V + External Vpp, + * the operation will be done by double word (64-bit) + * + * @retval FLASH Status: The returned value can be: FLASH_BUSY2, FLASH_ERROR_PROGRAM2, + * FLASH_ERROR_WRP2, FLASH_ERROR_OPERATION2 or FLASH_COMPLETE2. + */ +FLASH_Status FLASH_EraseAllSectors(uint8_t VoltageRange) +{ + uint32_t tmp_psize = 0x0; + FLASH_Status status = FLASH_COMPLETE2; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + assert_param(IS_VOLTAGERANGE(VoltageRange)); + + if(VoltageRange == VoltageRange_1) + { + tmp_psize = FLASH_PSIZE_BYTE; + } + else if(VoltageRange == VoltageRange_2) + { + tmp_psize = FLASH_PSIZE_HALF_WORD; + } + else if(VoltageRange == VoltageRange_3) + { + tmp_psize = FLASH_PSIZE_WORD; + } + else + { + tmp_psize = FLASH_PSIZE_DOUBLE_WORD; + } + if(status == FLASH_COMPLETE2) + { + /* if the previous operation is completed, proceed to erase all sectors */ +#if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F469_479xx) + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= tmp_psize; + FLASH->CR |= (FLASH_CR_MER1 | FLASH_CR_MER2); + FLASH->CR |= FLASH_CR_STRT; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + /* if the erase operation is completed, disable the MER Bit */ + FLASH->CR &= ~(FLASH_CR_MER1 | FLASH_CR_MER2); +#endif /* STM32F427_437xx || STM32F429_439xx || STM32F469_479xx */ + +#if defined(STM32F40_41xxx) || defined(STM32F401xx) || defined(STM32F410xx) || defined(STM32F411xE) || defined(STM32F412xG) || defined(STM32F446xx) + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= tmp_psize; + FLASH->CR |= FLASH_CR_MER; + FLASH->CR |= FLASH_CR_STRT; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + /* if the erase operation is completed, disable the MER Bit */ + FLASH->CR &= (~FLASH_CR_MER); +#endif /* STM32F40_41xxx || STM32F401xx || STM32F410xx || STM32F411xE || STM32F412xG || STM32F446xx */ + + } + /* Return the Erase Status */ + return status; +} + +/** + * @brief Erases all FLASH Sectors in Bank 1. + * + * @note This function can be used only for STM32F42xxx/43xxx devices. + * + * @note If an erase and a program operations are requested simultaneously, + * the erase operation is performed before the program one. + * + * @param VoltageRange: The device voltage range which defines the erase parallelism. + * This parameter can be one of the following values: + * @arg VoltageRange_1: when the device voltage range is 1.8V to 2.1V, + * the operation will be done by byte (8-bit) + * @arg VoltageRange_2: when the device voltage range is 2.1V to 2.7V, + * the operation will be done by half word (16-bit) + * @arg VoltageRange_3: when the device voltage range is 2.7V to 3.6V, + * the operation will be done by word (32-bit) + * @arg VoltageRange_4: when the device voltage range is 2.7V to 3.6V + External Vpp, + * the operation will be done by double word (64-bit) + * + * @retval FLASH Status: The returned value can be: FLASH_BUSY2, FLASH_ERROR_PROGRAM2, + * FLASH_ERROR_WRP2, FLASH_ERROR_OPERATION2 or FLASH_COMPLETE2. + */ +FLASH_Status FLASH_EraseAllBank1Sectors(uint8_t VoltageRange) +{ + uint32_t tmp_psize = 0x0; + FLASH_Status status = FLASH_COMPLETE2; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + assert_param(IS_VOLTAGERANGE(VoltageRange)); + + if(VoltageRange == VoltageRange_1) + { + tmp_psize = FLASH_PSIZE_BYTE; + } + else if(VoltageRange == VoltageRange_2) + { + tmp_psize = FLASH_PSIZE_HALF_WORD; + } + else if(VoltageRange == VoltageRange_3) + { + tmp_psize = FLASH_PSIZE_WORD; + } + else + { + tmp_psize = FLASH_PSIZE_DOUBLE_WORD; + } + if(status == FLASH_COMPLETE2) + { + /* if the previous operation is completed, proceed to erase all sectors */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= tmp_psize; + FLASH->CR |= FLASH_CR_MER1; + FLASH->CR |= FLASH_CR_STRT; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + /* if the erase operation is completed, disable the MER Bit */ + FLASH->CR &= (~FLASH_CR_MER1); + + } + /* Return the Erase Status */ + return status; +} + + +/** + * @brief Erases all FLASH Sectors in Bank 2. + * + * @note This function can be used only for STM32F42xxx/43xxx devices. + * + * @note If an erase and a program operations are requested simultaneously, + * the erase operation is performed before the program one. + * + * @param VoltageRange: The device voltage range which defines the erase parallelism. + * This parameter can be one of the following values: + * @arg VoltageRange_1: when the device voltage range is 1.8V to 2.1V, + * the operation will be done by byte (8-bit) + * @arg VoltageRange_2: when the device voltage range is 2.1V to 2.7V, + * the operation will be done by half word (16-bit) + * @arg VoltageRange_3: when the device voltage range is 2.7V to 3.6V, + * the operation will be done by word (32-bit) + * @arg VoltageRange_4: when the device voltage range is 2.7V to 3.6V + External Vpp, + * the operation will be done by double word (64-bit) + * + * @retval FLASH Status: The returned value can be: FLASH_BUSY2, FLASH_ERROR_PROGRAM2, + * FLASH_ERROR_WRP2, FLASH_ERROR_OPERATION2 or FLASH_COMPLETE2. + */ +FLASH_Status FLASH_EraseAllBank2Sectors(uint8_t VoltageRange) +{ + uint32_t tmp_psize = 0x0; + FLASH_Status status = FLASH_COMPLETE2; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + assert_param(IS_VOLTAGERANGE(VoltageRange)); + + if(VoltageRange == VoltageRange_1) + { + tmp_psize = FLASH_PSIZE_BYTE; + } + else if(VoltageRange == VoltageRange_2) + { + tmp_psize = FLASH_PSIZE_HALF_WORD; + } + else if(VoltageRange == VoltageRange_3) + { + tmp_psize = FLASH_PSIZE_WORD; + } + else + { + tmp_psize = FLASH_PSIZE_DOUBLE_WORD; + } + if(status == FLASH_COMPLETE2) + { + /* if the previous operation is completed, proceed to erase all sectors */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= tmp_psize; + FLASH->CR |= FLASH_CR_MER2; + FLASH->CR |= FLASH_CR_STRT; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + /* if the erase operation is completed, disable the MER Bit */ + FLASH->CR &= (~FLASH_CR_MER2); + + } + /* Return the Erase Status */ + return status; +} + +/** + * @brief Programs a double word (64-bit) at a specified address. + * @note This function must be used when the device voltage range is from + * 2.7V to 3.6V and an External Vpp is present. + * + * @note If an erase and a program operations are requested simultaneously, + * the erase operation is performed before the program one. + * + * @param Address: specifies the address to be programmed. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_BUSY2, FLASH_ERROR_PROGRAM2, + * FLASH_ERROR_WRP2, FLASH_ERROR_OPERATION2 or FLASH_COMPLETE2. + */ +FLASH_Status FLASH_ProgramDoubleWord(uint32_t Address, uint64_t Data) +{ + FLASH_Status status = FLASH_COMPLETE2; + + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + if(status == FLASH_COMPLETE2) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= FLASH_PSIZE_DOUBLE_WORD; + FLASH->CR |= FLASH_CR_PG; + + *(__IO uint64_t*)Address = Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + /* if the program operation is completed, disable the PG Bit */ + FLASH->CR &= (~FLASH_CR_PG); + } + /* Return the Program Status */ + return status; +} + +/** + * @brief Programs a word (32-bit) at a specified address. + * + * @note This function must be used when the device voltage range is from 2.7V to 3.6V. + * + * @note If an erase and a program operations are requested simultaneously, + * the erase operation is performed before the program one. + * + * @param Address: specifies the address to be programmed. + * This parameter can be any address in Program memory zone or in OTP zone. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_BUSY2, FLASH_ERROR_PROGRAM2, + * FLASH_ERROR_WRP2, FLASH_ERROR_OPERATION2 or FLASH_COMPLETE2. + */ +FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data) +{ + FLASH_Status status = FLASH_COMPLETE2; + + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + if(status == FLASH_COMPLETE2) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= FLASH_PSIZE_WORD; + FLASH->CR |= FLASH_CR_PG; + + *(__IO uint32_t*)Address = Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + /* if the program operation is completed, disable the PG Bit */ + FLASH->CR &= (~FLASH_CR_PG); + } + /* Return the Program Status */ + return status; +} + +/** + * @brief Programs a half word (16-bit) at a specified address. + * @note This function must be used when the device voltage range is from 2.1V to 3.6V. + * + * @note If an erase and a program operations are requested simultaneously, + * the erase operation is performed before the program one. + * + * @param Address: specifies the address to be programmed. + * This parameter can be any address in Program memory zone or in OTP zone. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_BUSY2, FLASH_ERROR_PROGRAM2, + * FLASH_ERROR_WRP2, FLASH_ERROR_OPERATION2 or FLASH_COMPLETE2. + */ +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) +{ + FLASH_Status status = FLASH_COMPLETE2; + + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + if(status == FLASH_COMPLETE2) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= FLASH_PSIZE_HALF_WORD; + FLASH->CR |= FLASH_CR_PG; + + *(__IO uint16_t*)Address = Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + /* if the program operation is completed, disable the PG Bit */ + FLASH->CR &= (~FLASH_CR_PG); + } + /* Return the Program Status */ + return status; +} + +/** + * @brief Programs a byte (8-bit) at a specified address. + * @note This function can be used within all the device supply voltage ranges. + * + * @note If an erase and a program operations are requested simultaneously, + * the erase operation is performed before the program one. + * + * @param Address: specifies the address to be programmed. + * This parameter can be any address in Program memory zone or in OTP zone. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_BUSY2, FLASH_ERROR_PROGRAM2, + * FLASH_ERROR_WRP2, FLASH_ERROR_OPERATION2 or FLASH_COMPLETE2. + */ +FLASH_Status FLASH_ProgramByte(uint32_t Address, uint8_t Data) +{ + FLASH_Status status = FLASH_COMPLETE2; + + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + if(status == FLASH_COMPLETE2) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= FLASH_PSIZE_BYTE; + FLASH->CR |= FLASH_CR_PG; + + *(__IO uint8_t*)Address = Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + /* if the program operation is completed, disable the PG Bit */ + FLASH->CR &= (~FLASH_CR_PG); + } + + /* Return the Program Status */ + return status; +} + +/** + * @} + */ + +/** @defgroup FLASH_Group3 Option Bytes Programming functions + * @brief Option Bytes Programming functions + * +@verbatim + =============================================================================== + ##### Option Bytes Programming functions ##### + =============================================================================== + [..] + This group includes the following functions: + (+) void FLASH_OB_Unlock(void) + (+) void FLASH_OB_Lock(void) + (+) void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState) + (+) void FLASH_OB_WRP1Config(uint32_t OB_WRP, FunctionalState NewState) + (+) void FLASH_OB_PCROPSelectionConfig(uint8_t OB_PCROPSelect) + (+) void FLASH_OB_PCROPConfig(uint32_t OB_PCROP, FunctionalState NewState) + (+) void FLASH_OB_PCROP1Config(uint32_t OB_PCROP, FunctionalState NewState) + (+) void FLASH_OB_RDPConfig(uint8_t OB_RDP) + (+) void FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY) + (+) void FLASH_OB_BORConfig(uint8_t OB_BOR) + (+) FLASH_Status FLASH_ProgramOTP(uint32_t Address, uint32_t Data) + (+) FLASH_Status FLASH_OB_Launch(void) + (+) uint32_t FLASH_OB_GetUser(void) + (+) uint8_t FLASH_OB_GetWRP(void) + (+) uint8_t FLASH_OB_GetWRP1(void) + (+) uint8_t FLASH_OB_GetPCROP(void) + (+) uint8_t FLASH_OB_GetPCROP1(void) + (+) uint8_t FLASH_OB_GetRDP(void) + (+) uint8_t FLASH_OB_GetBOR(void) + [..] + The following function can be used only for STM32F42xxx/43xxx devices. + (+) void FLASH_OB_BootConfig(uint8_t OB_BOOT) + [..] + Any operation of erase or program should follow these steps: + (#) Call the FLASH_OB_Unlock() function to enable the FLASH option control + register access + + (#) Call one or several functions to program the desired Option Bytes: + (++) void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState) + => to Enable/Disable the desired sector write protection + (++) void FLASH_OB_RDPConfig(uint8_t OB_RDP) => to set the desired read + Protection Level + (++) void FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY) + => to configure the user Option Bytes. + (++) void FLASH_OB_BORConfig(uint8_t OB_BOR) => to set the BOR Level + + (#) Once all needed Option Bytes to be programmed are correctly written, + call the FLASH_OB_Launch() function to launch the Option Bytes + programming process. + + -@- When changing the IWDG mode from HW to SW or from SW to HW, a system + reset is needed to make the change effective. + + (#) Call the FLASH_OB_Lock() function to disable the FLASH option control + register access (recommended to protect the Option Bytes against + possible unwanted operations) + +@endverbatim + * @{ + */ + +/** + * @brief Unlocks the FLASH Option Control Registers access. + * @param None + * @retval None + */ +void FLASH_OB_Unlock(void) +{ + if((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) != RESET) + { + /* Authorizes the Option Byte register programming */ + FLASH->OPTKEYR = FLASH_OPT_KEY1; + FLASH->OPTKEYR = FLASH_OPT_KEY2; + } +} + +/** + * @brief Locks the FLASH Option Control Registers access. + * @param None + * @retval None + */ +void FLASH_OB_Lock(void) +{ + /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */ + FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK; +} + +/** + * @brief Enables or disables the write protection of the desired sectors, for the first + * 1 Mb of the Flash + * + * @note When the memory read protection level is selected (RDP level = 1), + * it is not possible to program or erase the flash sector i if CortexM4 + * debug features are connected or boot code is executed in RAM, even if nWRPi = 1 + * @note Active value of nWRPi bits is inverted when PCROP mode is active (SPRMOD =1). + * + * @param OB_WRP: specifies the sector(s) to be write protected or unprotected. + * This parameter can be one of the following values: + * @arg OB_WRP: A value between OB_WRP_Sector0 and OB_WRP_Sector11 + * @arg OB_WRP_Sector_All + * @param Newstate: new state of the Write Protection. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState) +{ + FLASH_Status status = FLASH_COMPLETE2; + + /* Check the parameters */ + assert_param(IS_OB_WRP(OB_WRP)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + status = FLASH_WaitForLastOperation2(); + + if(status == FLASH_COMPLETE2) + { + if(NewState != DISABLE) + { + *(__IO uint16_t*)OPTCR_BYTE2_ADDRESS &= (~OB_WRP); + } + else + { + *(__IO uint16_t*)OPTCR_BYTE2_ADDRESS |= (uint16_t)OB_WRP; + } + } +} + +/** + * @brief Enables or disables the write protection of the desired sectors, for the second + * 1 Mb of the Flash + * + * @note This function can be used only for STM32F42xxx/43xxx devices. + * + * @note When the memory read out protection is selected (RDP level = 1), + * it is not possible to program or erase the flash sector i if CortexM4 + * debug features are connected or boot code is executed in RAM, even if nWRPi = 1 + * @note Active value of nWRPi bits is inverted when PCROP mode is active (SPRMOD =1). + * + * @param OB_WRP: specifies the sector(s) to be write protected or unprotected. + * This parameter can be one of the following values: + * @arg OB_WRP: A value between OB_WRP_Sector12 and OB_WRP_Sector23 + * @arg OB_WRP_Sector_All + * @param Newstate: new state of the Write Protection. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_OB_WRP1Config(uint32_t OB_WRP, FunctionalState NewState) +{ + FLASH_Status status = FLASH_COMPLETE2; + + /* Check the parameters */ + assert_param(IS_OB_WRP(OB_WRP)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + status = FLASH_WaitForLastOperation2(); + + if(status == FLASH_COMPLETE2) + { + if(NewState != DISABLE) + { + *(__IO uint16_t*)OPTCR1_BYTE2_ADDRESS &= (~OB_WRP); + } + else + { + *(__IO uint16_t*)OPTCR1_BYTE2_ADDRESS |= (uint16_t)OB_WRP; + } + } +} + +/** + * @brief Select the Protection Mode (SPRMOD). + * + * @note This function can be used only for STM32F42xxx/43xxx and STM32F401xx/411xE devices. + * + * @note After PCROP activation, Option Byte modification is not possible. + * Exception made for the global Read Out Protection modification level (level1 to level0) + * @note Once SPRMOD bit is active unprotection of a protected sector is not possible + * + * @note Read a protected sector will set RDERR Flag and write a protected sector will set WRPERR Flag + * + * @note Some Precautions should be taken when activating the PCROP feature : + * The active value of nWRPi bits is inverted when PCROP mode is active, this means if SPRMOD = 1 + * and WRPi = 1 (default value), then the user sector i is read/write protected. + * In order to avoid activation of PCROP Mode for undesired sectors, please follow the + * below safety sequence : + * - Disable PCROP for all Sectors using FLASH_OB_PCROPConfig(OB_PCROP_Sector_All, DISABLE) function + * for Bank1 or FLASH_OB_PCROP1Config(OB_PCROP_Sector_All, DISABLE) function for Bank2 + * - Enable PCROP for the desired Sector i using FLASH_OB_PCROPConfig(Sector i, ENABLE) function + * - Activate the PCROP Mode FLASH_OB_PCROPSelectionConfig() function. + * + * @param OB_PCROP: Select the Protection Mode of nWPRi bits + * This parameter can be one of the following values: + * @arg OB_PcROP_Disable: nWRPi control the write protection of respective user sectors. + * @arg OB_PcROP_Enable: nWRPi control the read&write protection (PCROP) of respective user sectors. + * @retval None + */ +void FLASH_OB_PCROPSelectionConfig(uint8_t OB_PcROP) +{ + uint8_t optiontmp = 0xFF; + + /* Check the parameters */ + assert_param(IS_OB_PCROP_SELECT(OB_PcROP)); + + /* Mask SPRMOD bit */ + optiontmp = (uint8_t)((*(__IO uint8_t *)OPTCR_BYTE3_ADDRESS) & (uint8_t)0x7F); + /* Update Option Byte */ + *(__IO uint8_t *)OPTCR_BYTE3_ADDRESS = (uint8_t)(OB_PcROP | optiontmp); + +} + +/** + * @brief Enables or disables the read/write protection (PCROP) of the desired + * sectors, for the first 1 MB of the Flash. + * + * @note This function can be used only for STM32F42xxx/43xxx , STM32F401xx/411xE + * and STM32F412xG devices. + * + * @param OB_PCROP: specifies the sector(s) to be read/write protected or unprotected. + * This parameter can be one of the following values: + * @arg OB_PCROP: A value between OB_PCROP_Sector0 and OB_PCROP_Sector11 for + * STM32F42xxx/43xxx devices and between OB_PCROP_Sector0 and + * OB_PCROP_Sector5 for STM32F401xx/411xE devices. + * @arg OB_PCROP_Sector_All + * @param Newstate: new state of the Write Protection. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_OB_PCROPConfig(uint32_t OB_PCROP, FunctionalState NewState) +{ + FLASH_Status status = FLASH_COMPLETE2; + + /* Check the parameters */ + assert_param(IS_OB_PCROP(OB_PCROP)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + status = FLASH_WaitForLastOperation2(); + + if(status == FLASH_COMPLETE2) + { + if(NewState != DISABLE) + { + *(__IO uint16_t*)OPTCR_BYTE2_ADDRESS |= (uint16_t)OB_PCROP; + } + else + { + *(__IO uint16_t*)OPTCR_BYTE2_ADDRESS &= (~OB_PCROP); + } + } +} + +/** + * @brief Enables or disables the read/write protection (PCROP) of the desired + * sectors + * + * @note This function can be used only for STM32F42xxx/43xxx devices. + * + * @param OB_PCROP: specifies the sector(s) to be read/write protected or unprotected. + * This parameter can be one of the following values: + * @arg OB_PCROP: A value between OB_PCROP_Sector12 and OB_PCROP_Sector23 + * @arg OB_PCROP_Sector_All + * @param Newstate: new state of the Write Protection. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_OB_PCROP1Config(uint32_t OB_PCROP, FunctionalState NewState) +{ + FLASH_Status status = FLASH_COMPLETE2; + + /* Check the parameters */ + assert_param(IS_OB_PCROP(OB_PCROP)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + status = FLASH_WaitForLastOperation2(); + + if(status == FLASH_COMPLETE2) + { + if(NewState != DISABLE) + { + *(__IO uint16_t*)OPTCR1_BYTE2_ADDRESS |= (uint16_t)OB_PCROP; + } + else + { + *(__IO uint16_t*)OPTCR1_BYTE2_ADDRESS &= (~OB_PCROP); + } + } +} + + +/** + * @brief Sets the read protection level. + * @param OB_RDP: specifies the read protection level. + * This parameter can be one of the following values: + * @arg OB_RDP_Level_0: No protection + * @arg OB_RDP_Level_1: Read protection of the memory + * @arg OB_RDP_Level_2: Full chip protection + * + * /!\ Warning /!\ When enabling OB_RDP level 2 it's no more possible to go back to level 1 or 0 + * + * @retval None + */ +void FLASH_OB_RDPConfig(uint8_t OB_RDP) +{ + FLASH_Status status = FLASH_COMPLETE2; + + /* Check the parameters */ + assert_param(IS_OB_RDP(OB_RDP)); + + status = FLASH_WaitForLastOperation2(); + + if(status == FLASH_COMPLETE2) + { + *(__IO uint8_t*)OPTCR_BYTE1_ADDRESS = OB_RDP; + + } +} + +/** + * @brief Programs the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY. + * @param OB_IWDG: Selects the IWDG mode + * This parameter can be one of the following values: + * @arg OB_IWDG_SW: Software IWDG selected + * @arg OB_IWDG_HW: Hardware IWDG selected + * @param OB_STOP: Reset event when entering STOP mode. + * This parameter can be one of the following values: + * @arg OB_STOP_NoRST: No reset generated when entering in STOP + * @arg OB_STOP_RST: Reset generated when entering in STOP + * @param OB_STDBY: Reset event when entering Standby mode. + * This parameter can be one of the following values: + * @arg OB_STDBY_NoRST: No reset generated when entering in STANDBY + * @arg OB_STDBY_RST: Reset generated when entering in STANDBY + * @retval None + */ +void FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY) +{ + uint8_t optiontmp = 0xFF; + FLASH_Status status = FLASH_COMPLETE2; + + /* Check the parameters */ + assert_param(IS_OB_IWDG_SOURCE(OB_IWDG)); + assert_param(IS_OB_STOP_SOURCE(OB_STOP)); + assert_param(IS_OB_STDBY_SOURCE(OB_STDBY)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + if(status == FLASH_COMPLETE2) + { +#if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F469_479xx) + /* Mask OPTLOCK, OPTSTRT, BOR_LEV and BFB2 bits */ + optiontmp = (uint8_t)((*(__IO uint8_t *)OPTCR_BYTE0_ADDRESS) & (uint8_t)0x1F); +#endif /* STM32F427_437xx || STM32F429_439xx || STM32F469_479xx */ + +#if defined(STM32F40_41xxx) || defined(STM32F401xx) || defined(STM32F410xx) || defined(STM32F411xE) || defined(STM32F446xx) + /* Mask OPTLOCK, OPTSTRT and BOR_LEV bits */ + optiontmp = (uint8_t)((*(__IO uint8_t *)OPTCR_BYTE0_ADDRESS) & (uint8_t)0x0F); +#endif /* STM32F40_41xxx || STM32F401xx || STM32F410xx || STM32F411xE || STM32F446xx */ + + /* Update User Option Byte */ + *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS = OB_IWDG | (uint8_t)(OB_STDBY | (uint8_t)(OB_STOP | ((uint8_t)optiontmp))); + } +} + +/** + * @brief Configure the Dual Bank Boot. + * + * @note This function can be used only for STM32F42xxx/43xxx devices. + * + * @param OB_BOOT: specifies the Dual Bank Boot Option byte. + * This parameter can be one of the following values: + * @arg OB_Dual_BootEnabled: Dual Bank Boot Enable + * @arg OB_Dual_BootDisabled: Dual Bank Boot Disabled + * @retval None + */ +void FLASH_OB_BootConfig(uint8_t OB_BOOT) +{ + /* Check the parameters */ + assert_param(IS_OB_BOOT(OB_BOOT)); + + /* Set Dual Bank Boot */ + *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS &= (~FLASH_OPTCR_BFB2); + *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS |= OB_BOOT; + +} + +/** + * @brief Sets the BOR Level. + * @param OB_BOR: specifies the Option Bytes BOR Reset Level. + * This parameter can be one of the following values: + * @arg OB_BOR_LEVEL3: Supply voltage ranges from 2.7 to 3.6 V + * @arg OB_BOR_LEVEL2: Supply voltage ranges from 2.4 to 2.7 V + * @arg OB_BOR_LEVEL1: Supply voltage ranges from 2.1 to 2.4 V + * @arg OB_BOR_OFF: Supply voltage ranges from 1.62 to 2.1 V + * @retval None + */ +void FLASH_OB_BORConfig(uint8_t OB_BOR) +{ + /* Check the parameters */ + assert_param(IS_OB_BOR(OB_BOR)); + + /* Set the BOR Level */ + *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS &= (~FLASH_OPTCR_BOR_LEV); + *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS |= OB_BOR; + +} + +/** + * @brief Launch the option byte loading. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_BUSY2, FLASH_ERROR_PROGRAM2, + * FLASH_ERROR_WRP2, FLASH_ERROR_OPERATION2 or FLASH_COMPLETE2. + */ +FLASH_Status FLASH_OB_Launch(void) +{ + FLASH_Status status = FLASH_COMPLETE2; + + /* Set the OPTSTRT bit in OPTCR register */ + *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS |= FLASH_OPTCR_OPTSTRT; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation2(); + + return status; +} + +/** + * @brief Returns the FLASH User Option Bytes values. + * @param None + * @retval The FLASH User Option Bytes values: IWDG_SW(Bit0), RST_STOP(Bit1) + * and RST_STDBY(Bit2). + */ +uint8_t FLASH_OB_GetUser(void) +{ + /* Return the User Option Byte */ + return (uint8_t)(FLASH->OPTCR >> 5); +} + +/** + * @brief Returns the FLASH Write Protection Option Bytes value. + * @param None + * @retval The FLASH Write Protection Option Bytes value + */ +uint16_t FLASH_OB_GetWRP(void) +{ + /* Return the FLASH write protection Register value */ + return (*(__IO uint16_t *)(OPTCR_BYTE2_ADDRESS)); +} + +/** + * @brief Returns the FLASH Write Protection Option Bytes value. + * + * @note This function can be used only for STM32F42xxx/43xxx devices. + * + * @param None + * @retval The FLASH Write Protection Option Bytes value + */ +uint16_t FLASH_OB_GetWRP1(void) +{ + /* Return the FLASH write protection Register value */ + return (*(__IO uint16_t *)(OPTCR1_BYTE2_ADDRESS)); +} + +/** + * @brief Returns the FLASH PC Read/Write Protection Option Bytes value. + * + * @note This function can be used only for STM32F42xxx/43xxx devices and STM32F401xx/411xE devices. + * + * @param None + * @retval The FLASH PC Read/Write Protection Option Bytes value + */ +uint16_t FLASH_OB_GetPCROP(void) +{ + /* Return the FLASH PC Read/write protection Register value */ + return (*(__IO uint16_t *)(OPTCR_BYTE2_ADDRESS)); +} + +/** + * @brief Returns the FLASH PC Read/Write Protection Option Bytes value. + * + * @note This function can be used only for STM32F42xxx/43xxx devices. + * + * @param None + * @retval The FLASH PC Read/Write Protection Option Bytes value + */ +uint16_t FLASH_OB_GetPCROP1(void) +{ + /* Return the FLASH write protection Register value */ + return (*(__IO uint16_t *)(OPTCR1_BYTE2_ADDRESS)); +} + +/** + * @brief Returns the FLASH Read Protection level. + * @param None + * @retval FLASH ReadOut Protection Status: + * - SET, when OB_RDP_Level_1 or OB_RDP_Level_2 is set + * - RESET, when OB_RDP_Level_0 is set + */ +FlagStatus FLASH_OB_GetRDP(void) +{ + FlagStatus readstatus = RESET; + + if ((*(__IO uint8_t*)(OPTCR_BYTE1_ADDRESS) != (uint8_t)OB_RDP_Level_0)) + { + readstatus = SET; + } + else + { + readstatus = RESET; + } + return readstatus; +} + +/** + * @brief Returns the FLASH BOR level. + * @param None + * @retval The FLASH BOR level: + * - OB_BOR_LEVEL3: Supply voltage ranges from 2.7 to 3.6 V + * - OB_BOR_LEVEL2: Supply voltage ranges from 2.4 to 2.7 V + * - OB_BOR_LEVEL1: Supply voltage ranges from 2.1 to 2.4 V + * - OB_BOR_OFF : Supply voltage ranges from 1.62 to 2.1 V + */ +uint8_t FLASH_OB_GetBOR(void) +{ + /* Return the FLASH BOR level */ + return (uint8_t)(*(__IO uint8_t *)(OPTCR_BYTE0_ADDRESS) & (uint8_t)0x0C); +} + +/** + * @} + */ + +/** @defgroup FLASH_Group4 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified FLASH interrupts. + * @param FLASH_IT: specifies the FLASH interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg FLASH_IT_ERR: FLASH Error Interrupt + * @arg FLASH_IT_EOP: FLASH end of operation Interrupt + * @retval None + */ +void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FLASH_IT(FLASH_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if(NewState != DISABLE) + { + /* Enable the interrupt sources */ + FLASH->CR |= FLASH_IT; + } + else + { + /* Disable the interrupt sources */ + FLASH->CR &= ~(uint32_t)FLASH_IT; + } +} + +/** + * @brief Checks whether the specified FLASH flag is set or not. + * @param FLASH_FLAG: specifies the FLASH flag to check. + * This parameter can be one of the following values: + * @arg FLASH_FLAG_EOP: FLASH End of Operation flag + * @arg FLASH_FLAG_OPERR: FLASH operation Error flag + * @arg FLASH_FLAG_WRPERR: FLASH Write protected error flag + * @arg FLASH_FLAG_PGAERR: FLASH Programming Alignment error flag + * @arg FLASH_FLAG_PGPERR: FLASH Programming Parallelism error flag + * @arg FLASH_FLAG_PGSERR: FLASH Programming Sequence error flag + * @arg FLASH_FLAG_RDERR: FLASH (PCROP) Read Protection error flag (STM32F42xx/43xxx and STM32F401xx/411xE devices) + * @arg FLASH_FLAG_BSY: FLASH Busy flag + * @retval The new state of FLASH_FLAG (SET or RESET). + */ +FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_FLASH_GET_FLAG(FLASH_FLAG)); + + if((FLASH->SR & FLASH_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the new state of FLASH_FLAG (SET or RESET) */ + return bitstatus; +} + +/** + * @brief Clears the FLASH's pending flags. + * @param FLASH_FLAG: specifies the FLASH flags to clear. + * This parameter can be any combination of the following values: + * @arg FLASH_FLAG_EOP: FLASH End of Operation flag + * @arg FLASH_FLAG_OPERR: FLASH operation Error flag + * @arg FLASH_FLAG_WRPERR: FLASH Write protected error flag + * @arg FLASH_FLAG_PGAERR: FLASH Programming Alignment error flag + * @arg FLASH_FLAG_PGPERR: FLASH Programming Parallelism error flag + * @arg FLASH_FLAG_PGSERR: FLASH Programming Sequence error flag + * @arg FLASH_FLAG_RDERR: FLASH Read Protection error flag (STM32F42xx/43xxx and STM32F401xx/411xE devices) + * @retval None + */ +void FLASH_ClearFlag(uint32_t FLASH_FLAG) +{ + /* Check the parameters */ + assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)); + + /* Clear the flags */ + FLASH->SR = FLASH_FLAG; +} + +/** + * @brief Returns the FLASH Status. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_BUSY2, FLASH_ERROR_PROGRAM2, + * FLASH_ERROR_WRP2, FLASH_ERROR_RD2, FLASH_ERROR_OPERATION2 or FLASH_COMPLETE2. + */ +FLASH_Status FLASH_GetStatus(void) +{ + FLASH_Status flashstatus = FLASH_COMPLETE2; + + if((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY) + { + flashstatus = FLASH_BUSY2; + } + else + { + if((FLASH->SR & FLASH_FLAG_WRPERR) != (uint32_t)0x00) + { + flashstatus = FLASH_ERROR_WRP2; + } + else + { + if((FLASH->SR & FLASH_FLAG_RDERR) != (uint32_t)0x00) + { + flashstatus = FLASH_ERROR_RD2; + } + else + { + if((FLASH->SR & (uint32_t)0xE0) != (uint32_t)0x00) + { + flashstatus = FLASH_ERROR_PROGRAM2; + } + else + { + if((FLASH->SR & FLASH_FLAG_OPERR) != (uint32_t)0x00) + { + flashstatus = FLASH_ERROR_OPERATION2; + } + else + { + flashstatus = FLASH_COMPLETE2; + } + } + } + } + } + /* Return the FLASH Status */ + return flashstatus; +} + +/** + * @brief Waits for a FLASH operation to complete. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_BUSY2, FLASH_ERROR_PROGRAM2, + * FLASH_ERROR_WRP2, FLASH_ERROR_OPERATION2 or FLASH_COMPLETE2. + */ +FLASH_Status FLASH_WaitForLastOperation2(void) +{ + __IO FLASH_Status status = FLASH_COMPLETE2; + + /* Check for the FLASH Status */ + status = FLASH_GetStatus(); + + /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + Even if the FLASH operation fails, the BUSY flag will be reset and an error + flag will be set */ + while(status == FLASH_BUSY2) + { + status = FLASH_GetStatus(); + } + /* Return the operation status */ + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PreferenceWriter/stm32f4xx_flash.h Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,425 @@ +/** + ****************************************************************************** + * @file stm32f4xx_flash.h + * @author MCD Application Team + * @version V1.7.1 + * @date 20-May-2016 + * @brief This file contains all the functions prototypes for the FLASH + * firmware library. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_FLASH_H +#define __STM32F4xx_FLASH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @addtogroup FLASH + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** + * @brief FLASH Status + */ +typedef enum +{ + FLASH_BUSY2 = 1, + FLASH_ERROR_RD2, + FLASH_ERROR_PGS2, + FLASH_ERROR_PGP2, + FLASH_ERROR_PGA2, + FLASH_ERROR_WRP2, + FLASH_ERROR_PROGRAM2, + FLASH_ERROR_OPERATION2, + FLASH_COMPLETE2 +}FLASH_Status; + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup FLASH_Exported_Constants + * @{ + */ + +/** @defgroup Flash_Latency + * @{ + */ +#define FLASH_Latency_0 ((uint8_t)0x0000) /*!< FLASH Zero Latency cycle */ +#define FLASH_Latency_1 ((uint8_t)0x0001) /*!< FLASH One Latency cycle */ +#define FLASH_Latency_2 ((uint8_t)0x0002) /*!< FLASH Two Latency cycles */ +#define FLASH_Latency_3 ((uint8_t)0x0003) /*!< FLASH Three Latency cycles */ +#define FLASH_Latency_4 ((uint8_t)0x0004) /*!< FLASH Four Latency cycles */ +#define FLASH_Latency_5 ((uint8_t)0x0005) /*!< FLASH Five Latency cycles */ +#define FLASH_Latency_6 ((uint8_t)0x0006) /*!< FLASH Six Latency cycles */ +#define FLASH_Latency_7 ((uint8_t)0x0007) /*!< FLASH Seven Latency cycles */ +#define FLASH_Latency_8 ((uint8_t)0x0008) /*!< FLASH Eight Latency cycles */ +#define FLASH_Latency_9 ((uint8_t)0x0009) /*!< FLASH Nine Latency cycles */ +#define FLASH_Latency_10 ((uint8_t)0x000A) /*!< FLASH Ten Latency cycles */ +#define FLASH_Latency_11 ((uint8_t)0x000B) /*!< FLASH Eleven Latency cycles */ +#define FLASH_Latency_12 ((uint8_t)0x000C) /*!< FLASH Twelve Latency cycles */ +#define FLASH_Latency_13 ((uint8_t)0x000D) /*!< FLASH Thirteen Latency cycles */ +#define FLASH_Latency_14 ((uint8_t)0x000E) /*!< FLASH Fourteen Latency cycles */ +#define FLASH_Latency_15 ((uint8_t)0x000F) /*!< FLASH Fifteen Latency cycles */ + +/** + * @} + */ + +/** @defgroup FLASH_Voltage_Range + * @{ + */ +#define VoltageRange_1 ((uint8_t)0x00) /*!< Device operating range: 1.8V to 2.1V */ +#define VoltageRange_2 ((uint8_t)0x01) /*!<Device operating range: 2.1V to 2.7V */ +#define VoltageRange_3 ((uint8_t)0x02) /*!<Device operating range: 2.7V to 3.6V */ +#define VoltageRange_4 ((uint8_t)0x03) /*!<Device operating range: 2.7V to 3.6V + External Vpp */ + +/* +#define IS_VOLTAGERANGE(RANGE)(((RANGE) == VoltageRange_1) || \ + ((RANGE) == VoltageRange_2) || \ + ((RANGE) == VoltageRange_3) || \ + ((RANGE) == VoltageRange_4)) +*/ + +/** + * @} + */ + +/** @defgroup FLASH_Sectors + * @{ + */ +#define FLASH_Sector_0 ((uint16_t)0x0000) /*!< Sector Number 0 */ +#define FLASH_Sector_1 ((uint16_t)0x0008) /*!< Sector Number 1 */ +#define FLASH_Sector_2 ((uint16_t)0x0010) /*!< Sector Number 2 */ +#define FLASH_Sector_3 ((uint16_t)0x0018) /*!< Sector Number 3 */ +#define FLASH_Sector_4 ((uint16_t)0x0020) /*!< Sector Number 4 */ +#define FLASH_Sector_5 ((uint16_t)0x0028) /*!< Sector Number 5 */ +#define FLASH_Sector_6 ((uint16_t)0x0030) /*!< Sector Number 6 */ +#define FLASH_Sector_7 ((uint16_t)0x0038) /*!< Sector Number 7 */ +#define FLASH_Sector_8 ((uint16_t)0x0040) /*!< Sector Number 8 */ +#define FLASH_Sector_9 ((uint16_t)0x0048) /*!< Sector Number 9 */ +#define FLASH_Sector_10 ((uint16_t)0x0050) /*!< Sector Number 10 */ +#define FLASH_Sector_11 ((uint16_t)0x0058) /*!< Sector Number 11 */ +#define FLASH_Sector_12 ((uint16_t)0x0080) /*!< Sector Number 12 */ +#define FLASH_Sector_13 ((uint16_t)0x0088) /*!< Sector Number 13 */ +#define FLASH_Sector_14 ((uint16_t)0x0090) /*!< Sector Number 14 */ +#define FLASH_Sector_15 ((uint16_t)0x0098) /*!< Sector Number 15 */ +#define FLASH_Sector_16 ((uint16_t)0x00A0) /*!< Sector Number 16 */ +#define FLASH_Sector_17 ((uint16_t)0x00A8) /*!< Sector Number 17 */ +#define FLASH_Sector_18 ((uint16_t)0x00B0) /*!< Sector Number 18 */ +#define FLASH_Sector_19 ((uint16_t)0x00B8) /*!< Sector Number 19 */ +#define FLASH_Sector_20 ((uint16_t)0x00C0) /*!< Sector Number 20 */ +#define FLASH_Sector_21 ((uint16_t)0x00C8) /*!< Sector Number 21 */ +#define FLASH_Sector_22 ((uint16_t)0x00D0) /*!< Sector Number 22 */ +#define FLASH_Sector_23 ((uint16_t)0x00D8) /*!< Sector Number 23 */ + +#if defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F469_479xx) +#define IS_FLASH_ADDRESS(ADDRESS) ((((ADDRESS) >= 0x08000000) && ((ADDRESS) <= 0x081FFFFF)) ||\ + (((ADDRESS) >= 0x1FFF7800) && ((ADDRESS) <= 0x1FFF7A0F))) +#endif /* STM32F427_437xx || STM32F429_439xx || STM32F469_479xx */ + +#if defined (STM32F40_41xxx) || defined(STM32F412xG) +#define IS_FLASH_ADDRESS(ADDRESS) ((((ADDRESS) >= 0x08000000) && ((ADDRESS) <= 0x080FFFFF)) ||\ + (((ADDRESS) >= 0x1FFF7800) && ((ADDRESS) <= 0x1FFF7A0F))) +#endif /* STM32F40_41xxx || STM32F412xG */ + +#if defined (STM32F401xx) +#define IS_FLASH_ADDRESS(ADDRESS) ((((ADDRESS) >= 0x08000000) && ((ADDRESS) <= 0x0803FFFF)) ||\ + (((ADDRESS) >= 0x1FFF7800) && ((ADDRESS) <= 0x1FFF7A0F))) +#endif /* STM32F401xx */ + +#if defined (STM32F411xE) || defined (STM32F446xx) +//#define IS_FLASH_ADDRESS(ADDRESS) ((((ADDRESS) >= 0x08000000) && ((ADDRESS) <= 0x0807FFFF)) ||\ +// (((ADDRESS) >= 0x1FFF7800) && ((ADDRESS) <= 0x1FFF7A0F))) +#endif /* STM32F411xE || STM32F446xx */ + +#if defined (STM32F410xx) +#define IS_FLASH_ADDRESS(ADDRESS) ((((ADDRESS) >= 0x08000000) && ((ADDRESS) <= 0x0801FFFF)) ||\ + (((ADDRESS) >= 0x1FFF7800) && ((ADDRESS) <= 0x1FFF7A0F))) +#endif /* STM32F410xx */ + +/** + * @} + */ + +/** @defgroup Option_Bytes_Write_Protection + * @{ + */ +#define OB_WRP_Sector_0 ((uint32_t)0x00000001) /*!< Write protection of Sector0 */ +#define OB_WRP_Sector_1 ((uint32_t)0x00000002) /*!< Write protection of Sector1 */ +#define OB_WRP_Sector_2 ((uint32_t)0x00000004) /*!< Write protection of Sector2 */ +#define OB_WRP_Sector_3 ((uint32_t)0x00000008) /*!< Write protection of Sector3 */ +#define OB_WRP_Sector_4 ((uint32_t)0x00000010) /*!< Write protection of Sector4 */ +#define OB_WRP_Sector_5 ((uint32_t)0x00000020) /*!< Write protection of Sector5 */ +#define OB_WRP_Sector_6 ((uint32_t)0x00000040) /*!< Write protection of Sector6 */ +#define OB_WRP_Sector_7 ((uint32_t)0x00000080) /*!< Write protection of Sector7 */ +#define OB_WRP_Sector_8 ((uint32_t)0x00000100) /*!< Write protection of Sector8 */ +#define OB_WRP_Sector_9 ((uint32_t)0x00000200) /*!< Write protection of Sector9 */ +#define OB_WRP_Sector_10 ((uint32_t)0x00000400) /*!< Write protection of Sector10 */ +#define OB_WRP_Sector_11 ((uint32_t)0x00000800) /*!< Write protection of Sector11 */ +#define OB_WRP_Sector_12 ((uint32_t)0x00000001) /*!< Write protection of Sector12 */ +#define OB_WRP_Sector_13 ((uint32_t)0x00000002) /*!< Write protection of Sector13 */ +#define OB_WRP_Sector_14 ((uint32_t)0x00000004) /*!< Write protection of Sector14 */ +#define OB_WRP_Sector_15 ((uint32_t)0x00000008) /*!< Write protection of Sector15 */ +#define OB_WRP_Sector_16 ((uint32_t)0x00000010) /*!< Write protection of Sector16 */ +#define OB_WRP_Sector_17 ((uint32_t)0x00000020) /*!< Write protection of Sector17 */ +#define OB_WRP_Sector_18 ((uint32_t)0x00000040) /*!< Write protection of Sector18 */ +#define OB_WRP_Sector_19 ((uint32_t)0x00000080) /*!< Write protection of Sector19 */ +#define OB_WRP_Sector_20 ((uint32_t)0x00000100) /*!< Write protection of Sector20 */ +#define OB_WRP_Sector_21 ((uint32_t)0x00000200) /*!< Write protection of Sector21 */ +#define OB_WRP_Sector_22 ((uint32_t)0x00000400) /*!< Write protection of Sector22 */ +#define OB_WRP_Sector_23 ((uint32_t)0x00000800) /*!< Write protection of Sector23 */ +#define OB_WRP_Sector_All ((uint32_t)0x00000FFF) /*!< Write protection of all Sectors */ + +#define IS_OB_WRP(SECTOR)((((SECTOR) & (uint32_t)0xFFFFF000) == 0x00000000) && ((SECTOR) != 0x00000000)) +/** + * @} + */ + +/** @defgroup Selection_Protection_Mode + * @{ + */ +#define OB_PcROP_Disable ((uint8_t)0x00) /*!< Disabled PcROP, nWPRi bits used for Write Protection on sector i */ +#define OB_PcROP_Enable ((uint8_t)0x80) /*!< Enable PcROP, nWPRi bits used for PCRoP Protection on sector i */ + +/** + * @} + */ + +/** @defgroup Option_Bytes_PC_ReadWrite_Protection + * @{ + */ +#define OB_PCROP_Sector_0 ((uint32_t)0x00000001) /*!< PC Read/Write protection of Sector0 */ +#define OB_PCROP_Sector_1 ((uint32_t)0x00000002) /*!< PC Read/Write protection of Sector1 */ +#define OB_PCROP_Sector_2 ((uint32_t)0x00000004) /*!< PC Read/Write protection of Sector2 */ +#define OB_PCROP_Sector_3 ((uint32_t)0x00000008) /*!< PC Read/Write protection of Sector3 */ +#define OB_PCROP_Sector_4 ((uint32_t)0x00000010) /*!< PC Read/Write protection of Sector4 */ +#define OB_PCROP_Sector_5 ((uint32_t)0x00000020) /*!< PC Read/Write protection of Sector5 */ +#define OB_PCROP_Sector_6 ((uint32_t)0x00000040) /*!< PC Read/Write protection of Sector6 */ +#define OB_PCROP_Sector_7 ((uint32_t)0x00000080) /*!< PC Read/Write protection of Sector7 */ +#define OB_PCROP_Sector_8 ((uint32_t)0x00000100) /*!< PC Read/Write protection of Sector8 */ +#define OB_PCROP_Sector_9 ((uint32_t)0x00000200) /*!< PC Read/Write protection of Sector9 */ +#define OB_PCROP_Sector_10 ((uint32_t)0x00000400) /*!< PC Read/Write protection of Sector10 */ +#define OB_PCROP_Sector_11 ((uint32_t)0x00000800) /*!< PC Read/Write protection of Sector11 */ +#define OB_PCROP_Sector_12 ((uint32_t)0x00000001) /*!< PC Read/Write protection of Sector12 */ +#define OB_PCROP_Sector_13 ((uint32_t)0x00000002) /*!< PC Read/Write protection of Sector13 */ +#define OB_PCROP_Sector_14 ((uint32_t)0x00000004) /*!< PC Read/Write protection of Sector14 */ +#define OB_PCROP_Sector_15 ((uint32_t)0x00000008) /*!< PC Read/Write protection of Sector15 */ +#define OB_PCROP_Sector_16 ((uint32_t)0x00000010) /*!< PC Read/Write protection of Sector16 */ +#define OB_PCROP_Sector_17 ((uint32_t)0x00000020) /*!< PC Read/Write protection of Sector17 */ +#define OB_PCROP_Sector_18 ((uint32_t)0x00000040) /*!< PC Read/Write protection of Sector18 */ +#define OB_PCROP_Sector_19 ((uint32_t)0x00000080) /*!< PC Read/Write protection of Sector19 */ +#define OB_PCROP_Sector_20 ((uint32_t)0x00000100) /*!< PC Read/Write protection of Sector20 */ +#define OB_PCROP_Sector_21 ((uint32_t)0x00000200) /*!< PC Read/Write protection of Sector21 */ +#define OB_PCROP_Sector_22 ((uint32_t)0x00000400) /*!< PC Read/Write protection of Sector22 */ +#define OB_PCROP_Sector_23 ((uint32_t)0x00000800) /*!< PC Read/Write protection of Sector23 */ +#define OB_PCROP_Sector_All ((uint32_t)0x00000FFF) /*!< PC Read/Write protection of all Sectors */ + +/** + * @} + */ + +/** @defgroup FLASH_Option_Bytes_Read_Protection + * @{ + */ +#define OB_RDP_Level_0 ((uint8_t)0xAA) +#define OB_RDP_Level_1 ((uint8_t)0x55) +/*#define OB_RDP_Level_2 ((uint8_t)0xCC)*/ /*!< Warning: When enabling read protection level 2 + it's no more possible to go back to level 1 or 0 */ +#define IS_OB_RDP(LEVEL) (((LEVEL) == OB_RDP_Level_0)||\ + ((LEVEL) == OB_RDP_Level_1))/*||\ + ((LEVEL) == OB_RDP_Level_2))*/ +/** + * @} + */ + +/** @defgroup FLASH_Option_Bytes_IWatchdog + * @{ + */ + +#define IS_OB_IWDG_SOURCE(SOURCE) (((SOURCE) == OB_IWDG_SW) || ((SOURCE) == OB_IWDG_HW)) +/** + * @} + */ + +/** @defgroup FLASH_Option_Bytes_nRST_STOP + * @{ + */ +#define OB_STOP_NoRST ((uint8_t)0x40) /*!< No reset generated when entering in STOP */ + +/** + * @} + */ + + +/** @defgroup FLASH_Option_Bytes_nRST_STDBY + * @{ + */ +#define OB_STDBY_NoRST ((uint8_t)0x80) /*!< No reset generated when entering in STANDBY */ +//#define OB_STDBY_RST ((uint8_t)0x00) /*!< Reset generated when entering in STANDBY */ +//#define IS_OB_STDBY_SOURCE(SOURCE) (((SOURCE) == OB_STDBY_NoRST) || ((SOURCE) == OB_STDBY_RST)) +/** + * @} + */ + +/** @defgroup FLASH_BOR_Reset_Level + * @{ + */ + +#define IS_OB_BOR(LEVEL) (((LEVEL) == OB_BOR_LEVEL1) || ((LEVEL) == OB_BOR_LEVEL2) ||\ + ((LEVEL) == OB_BOR_LEVEL3) || ((LEVEL) == OB_BOR_OFF)) +/** + * @} + */ + +/** @defgroup FLASH_Dual_Boot + * @{ + */ +#define OB_Dual_BootEnabled ((uint8_t)0x10) /*!< Dual Bank Boot Enable */ +#define OB_Dual_BootDisabled ((uint8_t)0x00) /*!< Dual Bank Boot Disable, always boot on User Flash */ +#define IS_OB_BOOT(BOOT) (((BOOT) == OB_Dual_BootEnabled) || ((BOOT) == OB_Dual_BootDisabled)) +/** + * @} + */ + +/** @defgroup FLASH_Interrupts + * @{ + */ + +#define IS_FLASH_IT(IT) ((((IT) & (uint32_t)0xFCFFFFFF) == 0x00000000) && ((IT) != 0x00000000)) +/** + * @} + */ + +/** @defgroup FLASH_Flags + * @{ + */ + +#define IS_FLASH_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFFFE0C) == 0x00000000) && ((FLAG) != 0x00000000)) +#define IS_FLASH_GET_FLAG(FLAG) (((FLAG) == FLASH_FLAG_EOP) || ((FLAG) == FLASH_FLAG_OPERR) || \ + ((FLAG) == FLASH_FLAG_WRPERR) || ((FLAG) == FLASH_FLAG_PGAERR) || \ + ((FLAG) == FLASH_FLAG_PGPERR) || ((FLAG) == FLASH_FLAG_PGSERR) || \ + ((FLAG) == FLASH_FLAG_BSY) || ((FLAG) == FLASH_FLAG_RDERR)) + +/** + * @brief ACR register byte 0 (Bits[7:0]) base address + */ +//#define ACR_BYTE0_ADDRESS ((uint32_t)0x40023C00) +/** + * @brief OPTCR register byte 0 (Bits[7:0]) base address + */ +//#define OPTCR_BYTE0_ADDRESS ((uint32_t)0x40023C14) +/** + * @brief OPTCR register byte 1 (Bits[15:8]) base address + */ +//#define OPTCR_BYTE1_ADDRESS ((uint32_t)0x40023C15) +/** + * @brief OPTCR register byte 2 (Bits[23:16]) base address + */ +//#define OPTCR_BYTE2_ADDRESS ((uint32_t)0x40023C16) +/** + * @brief OPTCR register byte 3 (Bits[31:24]) base address + */ +//#define OPTCR_BYTE3_ADDRESS ((uint32_t)0x40023C17) + +/** + * @brief OPTCR1 register byte 0 (Bits[7:0]) base address + */ +#define OPTCR1_BYTE2_ADDRESS ((uint32_t)0x40023C1A) + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/* FLASH Interface configuration functions ************************************/ +void FLASH_SetLatency(uint32_t FLASH_Latency); +void FLASH_PrefetchBufferCmd(FunctionalState NewState); +void FLASH_InstructionCacheCmd(FunctionalState NewState); +void FLASH_DataCacheCmd(FunctionalState NewState); +void FLASH_InstructionCacheReset(void); +void FLASH_DataCacheReset(void); + +/* FLASH Memory Programming functions *****************************************/ +void FLASH_Unlock(void); +void FLASH_Lock(void); +FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange); +FLASH_Status FLASH_EraseAllSectors(uint8_t VoltageRange); +FLASH_Status FLASH_EraseAllBank1Sectors(uint8_t VoltageRange); +FLASH_Status FLASH_EraseAllBank2Sectors(uint8_t VoltageRange); +FLASH_Status FLASH_ProgramDoubleWord(uint32_t Address, uint64_t Data); +FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data); +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); +FLASH_Status FLASH_ProgramByte(uint32_t Address, uint8_t Data); + +/* Option Bytes Programming functions *****************************************/ +void FLASH_OB_Unlock(void); +void FLASH_OB_Lock(void); +void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState); +void FLASH_OB_WRP1Config(uint32_t OB_WRP, FunctionalState NewState); +void FLASH_OB_PCROPSelectionConfig(uint8_t OB_PcROP); +void FLASH_OB_PCROPConfig(uint32_t OB_PCROP, FunctionalState NewState); +void FLASH_OB_PCROP1Config(uint32_t OB_PCROP, FunctionalState NewState); +void FLASH_OB_RDPConfig(uint8_t OB_RDP); +void FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY); +void FLASH_OB_BORConfig(uint8_t OB_BOR); +void FLASH_OB_BootConfig(uint8_t OB_BOOT); +FLASH_Status FLASH_OB_Launch(void); +uint8_t FLASH_OB_GetUser(void); +uint16_t FLASH_OB_GetWRP(void); +uint16_t FLASH_OB_GetWRP1(void); +uint16_t FLASH_OB_GetPCROP(void); +uint16_t FLASH_OB_GetPCROP1(void); +FlagStatus FLASH_OB_GetRDP(void); +uint8_t FLASH_OB_GetBOR(void); + +/* Interrupts and flags management functions **********************************/ +void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState); +FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG); +void FLASH_ClearFlag(uint32_t FLASH_FLAG); +FLASH_Status FLASH_GetStatus(void); +FLASH_Status FLASH_WaitForLastOperation2(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_FLASH_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/globals.h Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,47 @@ +#ifndef __GLOBALS_H +#define __GLOBALS_H + +#include "FastPWM.h" +#include "PreferenceWriter.h" + +extern FastPWM *out1, *out2, *out3; +extern int adval1, adval2; +extern PreferenceWriter *pref; +extern float current, throttle, vout, user_cmd; + +extern int __int_reg[]; +extern float __float_reg[]; + +#define I_LIMIT __float_reg[0] +#define KP __float_reg[1] +#define KI __float_reg[2] +#define F_SW __float_reg[3] +#define THROTTLE_DEADBAND __float_reg[4] +#define ANALOG_THROTTLE_LOW __float_reg[5] +#define ANALOG_THROTTLE_HI __float_reg[6] + +#define PREFS_VALID __int_reg[0] +#define BREMS_src __int_reg[1] +#define BREMS_op __int_reg[2] + +#define NUM_OPS 4 +enum { + OP_TORQUE, + OP_DRIVING, + OP_SPEED, + OP_POSITION, +}; + +#define NUM_SRCS 6 +enum { + CMD_SRC_RC, + CMD_SRC_ANALOG, + CMD_SRC_TERMINAL, + CMD_SRC_SERIAL, + CMD_SRC_CAN, + CMD_SRC_INTERNAL +}; + +#define set_dtc(a, x) *a = (x) + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,187 @@ +#include "mbed.h" +#include "globals.h" +#include "CommandProcessor.h" +#include "PreferenceWriter.h" +#include "Filter.h" +#include "FastPWM.h" + +#define AVDD 3.3f +#define I_PN 300.0f +#define G_TH (.625f / I_PN) +#define R_UP 12.f +#define R_DN 12.f +#define V_REF 2.5f + +Serial pc(USBTX, USBRX); +FastPWM *out1, *out2, *out3; +int adval1, adval2; +DigitalOut test(PC_6); +PreferenceWriter *pref; +float user_cmd; + +char linebuf[128]; +int index = 0; + +float current, throttle, vout; +float integral, err; + +void rxCallback() { + while (pc.readable()) { + char c = pc.getc(); + if (c != 127 && c != 8 && c != '\r' && c != '\t') { + linebuf[index] = c; + if (index < 127) index++; + pc.putc(c); + } else if (c == 127 || c == 8) { + if (index > 0) { + index--; + //BS (8) should delete previous char + pc.putc(127); + } + } else if (c == '\r') { + linebuf[index] = 0; + pc.putc(c); + processCmd(&pc, linebuf); + index = 0; + pc.putc('>'); + } + } +} + +inline float to_amps(float adval) { + float adv = adval * AVDD; + float adv_unscaled = adv * (R_UP + R_DN) / R_DN; + float adv_unoffs = adv_unscaled - V_REF; + return adv_unoffs / G_TH; +} + +extern "C" void TIM1_UP_TIM10_IRQHandler(void) { + if (TIM1->SR & TIM_SR_UIF ) { + ADC1->CR2 |= 0x40000000; + volatile int delay; + for (delay = 0; delay < 35; delay++); + + adval1 = ADC1->DR; + adval2 = ADC2->DR; + + current = to_amps((float) adval1 / 4095.0f); + + switch (BREMS_src) { + case CMD_SRC_TERMINAL: + throttle = user_cmd; + break; + case CMD_SRC_ANALOG: + throttle = adval2 / 4095.0f; + break; + default: + break; + } + + if (throttle < THROTTLE_DEADBAND) throttle = 0.0f; + + err = throttle * I_LIMIT - current; + integral += err * KI; + if (integral < 0.0f) integral = 0.0f; + if (integral > 1.0f) integral = 1.0f; + + vout = KP * err + integral; + if (vout < 0.0f) vout = 0.0f; + if (vout > 1.0f) vout = 1.0f; + + switch (BREMS_op) { + case OP_TORQUE: + set_dtc(out1, vout); + break; + case OP_SPEED: + set_dtc(out1, user_cmd); + break; + default: + break; + } + } + TIM1->SR = 0x00; +} + +void BREMSConfigRegisters() { + //Load preferences + cmd_clear(&pc); + pref = new PreferenceWriter(6); + cmd_reload(&pc, pref); + if (PREFS_VALID != 1) { + pc.printf("Stored preferences invalid, loading defaults\n"); + KP = 1.0f; + KI = 1.0f; + I_LIMIT = 400.0f; + BREMS_src = CMD_SRC_ANALOG; + } + + //safety first! + user_cmd = 0.0f; + + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; + + RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; //enable TIM1 clock + + out1 = new FastPWM(PA_8); + out2 = new FastPWM(PA_9); + out3 = new FastPWM(PA_10); + + NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn); //Enable TIM1 IRQ + + TIM1->DIER |= TIM_DIER_UIE; //enable update interrupt + TIM1->CR1 = 0x40; //0x40 for CMS = 10, center aligned mode 1, 0x00 for edge aligned + TIM1->CR1 |= TIM_CR1_ARPE; //autoreload on, + TIM1->RCR |= 0x01; //0x01 for center-aligned, 0x00 for edge aligned + TIM1->EGR |= TIM_EGR_UG; + + TIM1->PSC = 0x00; //no prescaler, timer counts up in sync with the peripheral clock + TIM1->ARR = (int) ((float) 9e7 / F_SW); //*2 for edge aligned + TIM1->CCER |= TIM_CCER_CC1P; //rising edge aligned, non-inverting + TIM1->CCER |= TIM_CCER_CC2P; + TIM1->CCER |= TIM_CCER_CC3P; + TIM1->CR1 |= TIM_CR1_CEN; + + //ADC Setup + RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // clock for ADC1 + RCC->APB2ENR |= RCC_APB2ENR_ADC2EN; // clock for ADC2 + + ADC->CCR = 0x00000006; //Regular simultaneous mode, 3 channels + + ADC1->CR2 |= ADC_CR2_ADON; //ADC1 on + ADC1->SQR3 = 0x0000004; //PA_4 as ADC1, sequence 0 + + ADC2->CR2 |= ADC_CR2_ADON; //ADC2 ON + ADC2->SQR3 = 0x00000008; //PB_0 as ADC2, sequence 1 + + //PA_4 as analog + GPIOA->MODER |= (1 << 8); + GPIOA->MODER |= (1 << 9); + + //PB_0 as analog + GPIOB->MODER |= (1 << 0); + GPIOB->MODER |= (1 << 1); + + //Outputs off + set_dtc(out1, 0.0f); + set_dtc(out2, 0.0f); + set_dtc(out3, 0.0f); + current = 0.0f; + throttle = 0.0f; + integral = 0.0f; + + //Wait for sensors to settle + wait(1.0); +} + +int main() { + pc.baud(115200); + pc.attach(rxCallback); + + BREMSConfigRegisters(); + pc.printf(">"); + + for (;;) { + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sun Feb 03 03:38:05 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/e95d10626187 \ No newline at end of file