Write protection on STM32F779ii - c

I'm trying to erase flash for STM32F779II.
The start up file starts with that section:
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1664K
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
SRAM1 (xrw) : ORIGIN = 0x20020000, LENGTH = 368K
SRAM2 (xrw) : ORIGIN = 0x2007C000, LENGTH = 16K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
}
So I'm leaving that three sections.
I'm trying to clear sector number 22. but I get Write Protection Error.
Here is how I'm earsing it.
Sectors is an array with one element, which is 22 sector number which has address
0x081C0000
secbool flash_erase_sectors(const uint8_t *sectors, int len,
void (*progress)(int pos, int len)) {
ensure(flash_unlock_write(), NULL);
HAL_FLASH_OB_Unlock();
FLASH_EraseInitTypeDef EraseInitStruct;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.NbSectors = 1;
if (progress) {
progress(0, len);
}
for (int i = 0; i < len; i++) {
EraseInitStruct.Sector = sectors[i];
uint32_t SectorError;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
ensure(flash_lock_write(), NULL);
return secfalse;
}
// check whether the sector was really deleted (contains only 0xFF)
const uint32_t addr_start = FLASH_SECTOR_TABLE[sectors[i]],
addr_end = FLASH_SECTOR_TABLE[sectors[i] + 1];
for (uint32_t addr = addr_start; addr < addr_end; addr += 4) {
if (*((const uint32_t *)addr) != 0xFFFFFFFF) {
ensure(flash_lock_write(), NULL);
return secfalse;
}
}
if (progress) {
progress(i + 1, len);
}
}
ensure(flash_lock_write(), NULL);
return sectrue;
}

Related

Writing array to flash which is uint16_t. I am using a STM32L053 nucleo., get a hard fault error. How to convert uint16_t array to write to flash?

This is the how I'm trying to write to flash
Basically I pass my uint16_t array to a function called FLASH_WriteA which accepts the array, the destination array or the location and the length
void FLASH_WriteA(uint16_t * src, uint16_t * dest, uint16_t length_16)
{
uint32_t firstAddress= FLASH_GetFirstAddress((uint32_t)dest, PAGE_SIZE_BYTES); // gets the first address of that page
uint32_t offset = ((uint32_t)dest - seg) / 2; // offset is in words
HAL_FLASH_Unlock();
Flash_Erase_Page((uint16_t*)seg); // calls the page erase function
FLASH_Write_HAL((uint32_t *)&flashBuffer, (uint16_t*)seg, FLASH_TABLE_SIZE_BYTES); //FLASH_TABLE_SIZE_BYTES = 256 = size of array
HAL_FLASH_Lock();
}
HAL_StatusTypeDef Flash_Erase_Page(uint16_t* seg){//, uint16_t length){
//uint16_t pages = (length/page_size) + (int)((length % page_size) != 0);
uint32_t pages = 2; // page size for STM32L053 = 128 bytes
FLASH_EraseInitTypeDef EraseInitStruct;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = seg;
EraseInitStruct.NbPages = pages;
uint32_t PageError;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK) //Erase the Page Before a Write Operation
{
return HAL_ERROR;
}
}
void FLASH_Write_HAL(uint32_t *p_source, uint16_t* seg, uint16_t length)
{
uint32_t varToPass;
uint16_t wordcount=0;
int i;
for (i=0; i<length; i++){
varToPass = p_source[i] ;
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,seg+wordcount,varToPass);
wordcount += 4;
// if (wordcount>=256){
// break;
// }
}
}

Lenght of neighboring regions in MEMORY command (linker)

I want to declare few regions in linker script, one after another. Do I need to reduce the length by one to avoid overlapping ?
MEMORY
{
region_1 : org = 0x100, len = 0x100 /* or len = 0xFF ? */
region_2 : org = 0x200, len = 0x100 /* or len = 0xFF ? */
region_3 : org = 0x300, len = 0x100 /* or len = 0xFF ? */
[...]
}
Do I need to reduce the length by one to avoid overlapping ?
No. What you are doing is correct.
From GNU Linker manual Memory Layout section:
len is the size in bytes of the region
Example:
MEMORY
{
region_1 : org = 0x10000000, len = 1 /* 1 byte */
region_2 : org = 0x20000000, len = 256K /* 256 kilobytes */
region_3 : org = 0x30000000, len = 4M /* 4 megabytes ? */
[...]
}

Virtual address to physical address translation in Linux proc module

I'm trying to create my own proc node "os_pagemap" on Linux(using odroid)
This node's goal is to print all physical memory page's information.
(sudo cat /proc/os_pagemap)
Like this :
[PHY] Virt 483252 Phy 266908 VMA 0 PID 5773 PNAME com.sec.android.app.keyboard
[PHY] Virt 483253 Phy 266909 VMA 0 PID 5773 PNAME com.sec.android.app.keyboard
[PHY] Virt 483254 Phy 266910 VMA 0 PID 5773 PNAME com.sec.android.app.keyboard
[PHY] Virt 398391 Phy 266920 VMA /dev/ashmem/dalvik-bitmap-1 PID 5773 PNAME com.sec.android.app.keyboard
where VMA refers VMA name
To acheive the goal, my design is like this :
1. read_lock(&tasklock)
2. for_each_process(p) => get pids
3. read_unlock(&tasklock)
4. Loop for each pid
1)task = get_pid_task(pid)
2)if task==NULL => skip
3)mm=task->mm
4)down_read(&mm->mmap_sem)
5)Loop for each vma in mm
1>store vma information into os_pagemap_struct
6)up_read(&mm->mmap_sem)
5. Print os_pagemap_struct
However, I can't find out how to
"get vma information" and "Print os_pagemap_struct"
This is the code that I've done:
I only get "vm_start" and "vm_end" and I can't print it well.
struct os_pagemap{
unsigned long vm_start;
unsigned long vm_end;
//more on...
};
static ssize_t ospagemap_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
struct task_struct * p = NULL;
char * pagemap_buf = kmalloc(500, GFP_KERNEL);
int i = 0, j;
int cur = 0, bytes=0;
struct pid *pid_struct;
int pid[100];
struct mm_struct* mm;
struct os_pagemap pagemap;
struct vm_area_struct * vma;
int count = 0;
int buf_size = 0;
read_lock(&tasklist_lock);
for_each_process(p){ //get all process' pids
pid[i] = p->pid;
i++;
}
read_unlock(&tasklist_lock);
for (j = 0; j < i; j++){ //loop for each process
pid_struct = find_get_pid(pid[j]);
p = get_pid_task(pid_struct, PIDTYPE_PID);
put_pid(pid_struct);
if (p == NULL){ //skip this task
printk("[%d]p is NULL", pid[j]);
continue;
}
mm = p->mm;
if (mm == NULL){
printk("\n[%d]mm is NULL!\n",pid[j]);
continue;
}
down_read(&mm->mmap_sem);
vma = mm->mmap;
count = 0;
while (1){ //loop for each vma
if (vma == NULL){
printk("\n[%d]vma is NULL!\n", pid[j]);
break;
}
if (buf_size >= 450){
printk("Realloc size : %d\n", cur + 500);
krealloc(pagemap_buf, cur + 500, GFP_KERNEL);
buf_size = 0;
}
pagemap.vm_start = vma->vm_start;
pagemap.vm_end = vma->vm_end;
bytes = snprintf((cur > 0) ? cur + pagemap_buf : pagemap_buf,
500 - cur,
"Task : [%d]%s start : %lu end : %lu\n", p->pid, p->comm,
pagemap.vm_start, pagemap.vm_end);
printk("Task : [%d]%s start : %lu end : %lu\n", p->pid, p->comm,
pagemap.vm_start, pagemap.vm_end);
cur += bytes;
buf_size += bytes;
vma = vma->vm_next;
count++;
}
up_read(&mm->mmap_sem);
}
printk("cur : %d\n", cur);
copy_to_user(buf, pagemap_buf, (size<cur) ? size : cur);
return (size<cur) ? size : cur;
}
static int ospagemap_open(struct inode *inode, struct file *file)
{
printk("ospagemap opened");
return 0;
}
const struct file_operations proc_ospagemap_operations = {
.llseek = mem_lseek, /* borrow this */
.read = ospagemap_read,
.open = ospagemap_open,
};
static int __init proc_ospagemap_init(void)
{
proc_create("os_pagemap", 0, NULL, &proc_ospagemap_operations);
return 0;
}
fs_initcall(proc_ospagemap_init);

Loosing some bytes on USART transmission with STM32L1XX

I'm facing a problem with the communication between my computer and my board stm32L152RE.
I try to send a string of 1024 bytes and write it on my flash board.
For that, i send packets of 32 bytes.
The algorithm is simple :
I erase my memory with enought space to write my string of 1024
I receive 32 bytes in a string buffer
I write them on the flash
I do that until i receive 1024 bytes and the I stop.
The problem is , when i print what i have in memory step by step, I only receive 16 bytes and i don't know why
Here's my code, maybe it will help understand my program
/*
* bootloader.c
*
* Created on: 9 juin 2015
* Author: tgloaguen
*/
#include "usart.h"
#include "stm32l1xx_flash.h"
#define WRITE_START_ADDR 0x08000000
#define WRITE_END_ADDR 0x08000FFF
#define FLASH_PAGE_SIZE ((uint16_t)0x100) //If a page is 256 bits
#define MY_BL_FUNCTIONS __attribute__((section(".bootsection")))
void BootLoader(void) MY_BL_FUNCTIONS;
FLASH_Status Flash_Write ( uint32_t StartAddress, uint8_t *p, uint32_t Size ) MY_BL_FUNCTIONS;
uint8_t Flash_Erase() MY_BL_FUNCTIONS;
void Receive_Data(char * buffer,int size)MY_BL_FUNCTIONS;
void Receive_Size(char * buffer, int *sizeData)MY_BL_FUNCTIONS;
void BootLoader(void) {
//clear all ITs
USART_ITConfig( USART1, USART_IT_RXNE, DISABLE );
//SendString("HELLO",USART2);
uint8_t status,i;
char buffer[33];
//en dur
uint16_t *adr = WRITE_START_ADDR;
uint16_t sizeBin = 1024,k = 0,k_hexa = 0x20;
//Receive size of BIN
// Receive_Size(buffer,&sizeBin);
Flash_Erase();
//if sizeBin ok
//receive frames
do
{
//receive 32 bytes
Receive_Data(buffer,32);
GPIO_ToggleBits(GPIOA, GPIO_Pin_5);
// //write a sector (1024k)
status = Flash_Write(adr , buffer, 0x20);
// on check si on ecrit bien au bon endroit
SendString("\r\n ", USART2);
// //increment cpt
k += 32;
adr = adr + k_hexa;
// //check CRC
// //TODO
//
} while (k < sizeBin);
SendString("nickel ", USART2);
}
void Receive_Size(char * buffer, int *sizeData) {
int i = 0;
do {
buffer[i] = Uart2ReadChar();
i++;
} while (buffer[i] != '\0');
*sizeData = (buffer[1] << 8) + buffer[0];
}
void Receive_Data(char * buffer,int size){
int i=0;
do{
buffer[i] = Uart2ReadChar();
i++;
}
while(i < size);
}
uint8_t Flash_Erase() {
uint32_t EraseCounter = 0x00, Address = 0x00;//Erase count, write address
uint32_t NbrOfPage = 0x00;//Recording to erase the pages
volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;/*FLASH complete erasure marks*/
/*Unlock FLASH*/
FLASH_Unlock();
/*Calculate the number of FLASH pages need to erase */
NbrOfPage = (WRITE_END_ADDR - WRITE_START_ADDR) / FLASH_PAGE_SIZE;
/* Remove all hang flags */
FLASH_ClearFlag ( FLASH_FLAG_EOP |
FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR |
FLASH_FLAG_SIZERR |
FLASH_FLAG_OPTVERR );
/* Erase the FLASH page*/
for(EraseCounter = 0; (EraseCounter <NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
{
FLASHStatus = FLASH_ErasePage(WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));
}
FLASH_Lock ( );
return (uint8_t)FLASHStatus;
}
FLASH_Status Flash_Write ( uint32_t StartAddress, uint8_t *p, uint32_t Size )
{
uint32_t Address;
__IO FLASH_Status status = FLASH_COMPLETE;
Address = StartAddress;
/* Unlock the FLASH Program memory */
FLASH_Unlock ();
/* Clear all pending flags */
FLASH_ClearFlag ( FLASH_FLAG_EOP |
FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR |
FLASH_FLAG_SIZERR |
FLASH_FLAG_OPTVERR );
while ( Address < StartAddress + Size )
{
status = FLASH_FastProgramWord ( Address, *(uint32_t *)p );
//debug
SendChar('|',USART2);
SendChar(*p,USART2);
Address = Address + 4;
p = p + 4;
if ( status != FLASH_COMPLETE ) return status;
}
/* Lock the FLASH Program memory */
FLASH_Lock ( );
return status;
}

Getting IPs from a DNS response

I'm trying to write a program that will scrape one IP address out of a DNS reply without using any DNS functions in c. For some reason this code works but only for google, facebook and imgur.com. As in, if I enter in "www.facebook.com" it gives the right IP address and same with the other two sites but any other site entered gives a wrong IP address. Does anyone know what I'm doing wrong?
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#define PORT 53
#define SITEMAXLEN 40
#define QUERYMAXLEN SITEMAXLEN + 16
#define DNSRESULTMAXLEN 100
#define IPARRAYLEN 20
typedef unsigned char char_type;
void enter_record(char_type* query, char_type* site, int* let_set);
void print_query(char_type* query, int len);
void send_query(char_type* query, char_type* result, int len, int* answer_set);
char_type* parse_result(char_type* result, int query_len, char_type* ip);
void print_ip(int* ip);
int sock;
struct sockaddr_in server_addr;
struct sockaddr_in from_addr;
int main(int argc, char_type** argv) {
char_type* site;
char_type* query;
char_type* dns_result;
char_type* ip;
int query_len;
int answer_len;
site = (char_type*)malloc(SITEMAXLEN * sizeof(char_type));
query = (char_type*)malloc((QUERYMAXLEN) * sizeof(char_type));
dns_result = (char_type*)malloc(DNSRESULTMAXLEN * sizeof(char_type));
ip = (char_type*)malloc(IPARRAYLEN * sizeof(char_type));
if((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
fprintf(stderr, "error creating socket to the name server\n");
return 1;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("208.67.220.220");
server_addr.sin_port = htons(PORT);
printf("enter in website name\n");
scanf("%s", site);
enter_record(query, site, &query_len);
print_query(query, query_len);
send_query(query, dns_result, query_len, &answer_len);
printf("\n\nresult is\n");
print_query(dns_result, answer_len);
parse_result(dns_result, query_len, ip);
printf("\n\nip address is: %s", ip);
return 0;
}
void enter_record(char_type* query, char_type* site, int* len_set) {
char_type* loc;
char_type* len;
char_type* tld;
int query_end;
loc = strchr(site, '.'); //. after www
len = strchr(loc + 1, '.'); //. after the hostname
*loc = (char_type)(len - loc - 1);
*len = (char_type)0x0003;
query[0] = 'B';
query[1] = 'L';
query[2] = (char_type)0x0001;
query[3] = (char_type)0x0000;
query[4] = (char_type)0x0000;
query[5] = (char_type)0x0001;
query[6] = (char_type)0x0000;
query[7] = (char_type)0x0000;
query[8] = (char_type)0x0000;
query[9] = (char_type)0x0000;
query[10] = (char_type)0x0000;
query[11] = (char_type)0x0000;
query[12] = (char_type)0x0003;
strncat(query + 13, site, strlen(site));
query_end = 13 + strlen(site);
query[query_end] = 0x0000;
query[query_end + 1] = 0x0000;
query[query_end + 2] = 0x0001;
query[query_end + 3] = 0x0000;
query[query_end + 4] = 0x0001;
*len_set = query_end + 5;
}
void print_query(char_type* query, int len) {
int i;
printf("in hex\n");
for(i = 0; i < len; i++) {
printf("%02hhX ", query[i]);
if(i % 16 == 0 && i != 0) {
printf("\n");
}
}
printf("\nin ascii\n");
for(i = 0; i < len; i++) {
printf("%c ", query[i] < (char_type)0x21 ? '.' : query[i]);
if(i % 16 == 0 && i != 0) {
printf("\n");
}
}
printf("\n");
}
void send_query(char_type* query, char_type* result, int len, int* set_len) {
int from_size;
int response_len;
if(sendto(sock, query, len, 0,
(struct sockaddr*)&server_addr, sizeof(server_addr)) != len) {
//message couldn't be sent
fprintf(stderr, "couldn't send the query\n");
return;
}
from_size = sizeof(from_addr);
while((response_len = recvfrom(sock, result, DNSRESULTMAXLEN, 0,
(struct sockaddr*)&from_addr, &from_size)) < 0) {
}
//null terminate the buffer
//printf("%d\n", response_len);
//result[response_len] = '\0';
*set_len = response_len;
}
char_type* parse_result(char_type* result, int query_len, char_type* ip) {
/*int offset = -1;
//offset = query_len + 32;
int count = 0;
while(count < 3) {
offset++;
if(result[offset] == 0x00C0) {
count++;
}
}
offset += 32;*/
int offset = -1;
int found = 0;
while(found == 0) {
offset++;
if(result[offset] == 0x00C0) {
if(result[offset + 3] == 0x0001 && result[offset + 2] == 0x0000) {
offset = offset + result[offset + 1];
found = 1;
}
}
}
sprintf(ip, "%d.%d.%d.%d\n",
result[offset], result[offset + 1],
result[offset + 2], result[offset + 3]);
return ip;
}
In parse_result() instead of jumping result[offset + 1] bytes, jump 12 bytes.
if(result[offset + 3] == 0x0001 && result[offset + 2] == 0x0000) {
/* ********
offset = offset + result[offset + 1];
******** */
offset = offset + 12;
found = 1;
}
The value at result[offset + 1] is the offset from the beginning of the message to a name, not an ip address. In the case of yahoo, the offset ultimately points to "any-fp.wa1.b.yahoo.com".
It worked for facebook (and others) because the offset to the name in the answer is 12. The offset is 12 when the name in the question is the same as the name in the answer.
Update
Not all DNS answers start each answer section with a pointer (0xC0 0x??). They may have a label instead and your program will fail miserably. Even the pointer's first byte is not required to be 0xC0: the requirement is to have the first 2 bits set.

Resources