Skip to content

Commit 34403f8

Browse files
committed
added flashrom API implementation for cc2538
1 parent 6cfc4fe commit 34403f8

3 files changed

Lines changed: 174 additions & 0 deletions

File tree

cpu/cc2538/include/cc2538.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ typedef volatile uint32_t cc2538_reg_t; /**< Least-significant 32 bits of the IE
133133

134134
#define SRAM_BB_BASE 0x22000000 /**< SRAM base address in the bit-band region */
135135

136+
#define FLASH_SIZE 0x00080000 /* 512 KiB */
137+
#define FLASH_PAGE_NUM 256
138+
136139
/** @} */
137140

138141
/** @name CC2538 Special Function Registers
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* cc2538_flashrom.h
3+
*
4+
* Created on: 30.09.2016
5+
* Author: geith
6+
*/
7+
8+
#ifndef CPU_CC2538_INCLUDE_CC2538_FLASHROM_H_
9+
#define CPU_CC2538_INCLUDE_CC2538_FLASHROM_H_
10+
11+
#include "cc2538.h"
12+
#include "flashrom.h"
13+
14+
#ifdef __cplusplus
15+
extern "C" {
16+
#endif
17+
18+
/**
19+
* @brief Flash control register
20+
*/
21+
typedef union {
22+
cc2538_reg_t FCTL; /**< Flash Control Register */
23+
struct {
24+
cc2538_reg_t ERASE : 1; /**< Flash erase */
25+
cc2538_reg_t WRITE : 1; /**< Flash write */
26+
cc2538_reg_t CM : 2; /**< Flash cache mode */
27+
cc2538_reg_t RESERVED_4 : 1; /**< reserved */
28+
cc2538_reg_t ABORT : 1; /**< Flash abort status */
29+
cc2538_reg_t FULL : 1; /**< Flash write buffer full */
30+
cc2538_reg_t BUSY : 1; /**< Flash busy */
31+
cc2538_reg_t SEL_INFO_PAGE : 1; /**< */
32+
cc2538_reg_t UPPER_PAGE_ACCESS : 1; /**< */
33+
cc2538_reg_t RESERVED : 22; /**< Reserved bits */
34+
} FCTLbits;
35+
} cc2538_flash_fctl_t;
36+
37+
38+
/**
39+
* @brief Flash address register
40+
*/
41+
typedef union {
42+
cc2538_reg_t FADDR; /**< Flash Address Register */
43+
struct {
44+
//cc2538_reg_t FADDR : 17; /**< Flash address */
45+
46+
cc2538_reg_t LOC : 7; /**< Flash location within row */
47+
cc2538_reg_t ROW : 2; /**< Flash row */
48+
cc2538_reg_t PAGE : 8; /**< Flash page */
49+
cc2538_reg_t RESERVED : 15; /**< Reserved bits */
50+
} FADDRbits;
51+
} cc2538_flash_faddr_t;
52+
53+
extern cc2538_flash_fctl_t* const FCTL;
54+
//extern cc2538_flash_faddr_t* const FADDR;
55+
56+
57+
#ifdef __cplusplus
58+
} /* end extern "C" */
59+
#endif
60+
61+
#endif /* CPU_CC2538_INCLUDE_CC2538_FLASHROM_H_ */

cpu/cc2538/periph/flashrom.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* flashrom.c
3+
*
4+
* Created on: 30.09.2016
5+
* Author: geith
6+
*/
7+
8+
#include "cc2538_flashrom.h"
9+
#include "mutex.h"
10+
#include "irq.h"
11+
#include "stdio.h"
12+
13+
cc2538_flash_fctl_t* const FCTL = (cc2538_flash_fctl_t*)&FLASH_CTRL_FCTL;
14+
cc2538_flash_faddr_t* const FADDR = (cc2538_flash_faddr_t*)&FLASH_CTRL_FADDR;
15+
16+
static mutex_t flash_mutex = MUTEX_INIT;
17+
18+
#define FLASHROM_SECTION_DATA_INIT 1
19+
20+
#if FLASHROM_SECTION_DATA_INIT
21+
/*
22+
* don't know why, but writing flash works only if the address of
23+
* _flashrom_do_write has been read once (function is places in
24+
* .data section in RAM instead of flash)
25+
*/
26+
static volatile char init_done = 0;
27+
void* _flashrom_write_addr;
28+
#endif
29+
30+
31+
static uint
32+
flashrom_addr_to_page(uint8_t* addr){
33+
uint page_num = 0;
34+
uint flash_page_size = FLASH_SIZE / FLASH_PAGE_NUM;
35+
36+
uint8_t* rel_addr = addr - FLASH_BASE;
37+
38+
page_num = (uint)rel_addr / (uint)flash_page_size;
39+
40+
return page_num;
41+
}
42+
43+
uint8_t
44+
flashrom_erase(uint8_t *addr)
45+
{
46+
mutex_lock(&flash_mutex);
47+
irq_disable();
48+
49+
while(FCTL->FCTLbits.BUSY);
50+
FLASH_CTRL_FADDR = (cc2538_reg_t) addr;
51+
FCTL->FCTLbits.ERASE = 1;
52+
while(FCTL->FCTLbits.BUSY);
53+
54+
irq_enable();
55+
mutex_unlock(&flash_mutex);
56+
57+
return 1;
58+
}
59+
60+
static
61+
__attribute__((section(".data")))
62+
void
63+
_flashrom_do_write(uint8_t *dst, const uint8_t *src, size_t size){
64+
65+
while(FCTL->FCTLbits.BUSY);
66+
67+
68+
uint32_t tmp_data;
69+
uint32_t *tmp_data_ptr;
70+
71+
FLASH_CTRL_FADDR = (cc2538_reg_t) dst;
72+
FCTL->FCTLbits.WRITE = 1;
73+
74+
for(size_t s = 0; s < size; s+=sizeof(tmp_data)){
75+
tmp_data_ptr = (uint32_t*) (src + s);
76+
tmp_data = *tmp_data_ptr;
77+
78+
FLASH_CTRL_FWDATA = tmp_data;
79+
while(FCTL->FCTLbits.FULL);
80+
}
81+
FCTL->FCTLbits.WRITE = 0;
82+
return;
83+
}
84+
85+
uint8_t flashrom_write(uint8_t *dst, const uint8_t *src, size_t size)
86+
{
87+
88+
#if FLASHROM_SECTION_DATA_INIT
89+
if(!init_done){
90+
_flashrom_write_addr = &_flashrom_do_write;
91+
init_done = 1;
92+
}
93+
#endif
94+
95+
uint page_num = flashrom_addr_to_page(dst);
96+
97+
if(page_num == 0xff){
98+
return 0;
99+
}
100+
101+
mutex_lock(&flash_mutex);
102+
irq_disable();
103+
104+
_flashrom_do_write(dst, src, size);
105+
106+
irq_enable();
107+
mutex_unlock(&flash_mutex);
108+
109+
return 1;
110+
}

0 commit comments

Comments
 (0)