mirror of
https://github.com/nodemcu/nodemcu-firmware.git
synced 2025-01-16 20:52:57 +08:00
c4e8b04fbf
There was only one genuine use of this macro, all other places were using it only as a necessary compensation. While this was fine as long as it was the first meg of flash which was mapped, it became incorrect and quite dangerous whenever this assumption did not hold (such as when running from the second slot in an OTA scenario). The flash API now uses actual addresses, not translated/mapped addresses, and the users of this API have been adjusted accordingly. This makes the flash API work correctly regardless of what flash mapping is in use. The old macro is still available under the new name INTERNAL_FLASH_MAPPED_ADDRESS, and this is used to detect flash writes where the source is mapped flash (and thus has to be bounced), and to adjust the _flash_used_end linker symbol when used with flassh_find_sector() by the filesystem code. The latter usage is not OTA-proof, but in an OTA scenario the filesystem needs a fixed location anyway and thus would not use this code path.
582 lines
15 KiB
C
Executable File
582 lines
15 KiB
C
Executable File
// Platform-dependent functions
|
|
|
|
#include "platform.h"
|
|
#include "c_stdio.h"
|
|
#include "c_string.h"
|
|
#include "c_stdlib.h"
|
|
#include "gpio.h"
|
|
#include "user_interface.h"
|
|
#include "driver/uart.h"
|
|
// Platform specific includes
|
|
|
|
static void pwms_init();
|
|
|
|
int platform_init()
|
|
{
|
|
// Setup PWMs
|
|
pwms_init();
|
|
|
|
cmn_platform_init();
|
|
// All done
|
|
return PLATFORM_OK;
|
|
}
|
|
|
|
// ****************************************************************************
|
|
// KEY_LED functions
|
|
uint8_t platform_key_led( uint8_t level){
|
|
uint8_t temp;
|
|
gpio16_output_set(1); // set to high first, for reading key low level
|
|
gpio16_input_conf();
|
|
temp = gpio16_input_get();
|
|
gpio16_output_conf();
|
|
gpio16_output_set(level);
|
|
return temp;
|
|
}
|
|
|
|
// ****************************************************************************
|
|
// GPIO functions
|
|
#ifdef GPIO_INTERRUPT_ENABLE
|
|
extern void lua_gpio_unref(unsigned pin);
|
|
#endif
|
|
int platform_gpio_mode( unsigned pin, unsigned mode, unsigned pull )
|
|
{
|
|
// NODE_DBG("Function platform_gpio_mode() is called. pin_mux:%d, func:%d\n",pin_mux[pin],pin_func[pin]);
|
|
if (pin >= NUM_GPIO)
|
|
return -1;
|
|
if(pin == 0){
|
|
if(mode==PLATFORM_GPIO_INPUT)
|
|
gpio16_input_conf();
|
|
else
|
|
gpio16_output_conf();
|
|
return 1;
|
|
}
|
|
|
|
platform_pwm_close(pin); // closed from pwm module, if it is used in pwm
|
|
|
|
switch(pull){
|
|
case PLATFORM_GPIO_PULLUP:
|
|
PIN_PULLUP_EN(pin_mux[pin]);
|
|
break;
|
|
case PLATFORM_GPIO_FLOAT:
|
|
PIN_PULLUP_DIS(pin_mux[pin]);
|
|
break;
|
|
default:
|
|
PIN_PULLUP_DIS(pin_mux[pin]);
|
|
break;
|
|
}
|
|
|
|
switch(mode){
|
|
case PLATFORM_GPIO_INPUT:
|
|
#ifdef GPIO_INTERRUPT_ENABLE
|
|
lua_gpio_unref(pin); // unref the lua ref call back.
|
|
#endif
|
|
GPIO_DIS_OUTPUT(pin_num[pin]);
|
|
case PLATFORM_GPIO_OUTPUT:
|
|
ETS_GPIO_INTR_DISABLE();
|
|
#ifdef GPIO_INTERRUPT_ENABLE
|
|
pin_int_type[pin] = GPIO_PIN_INTR_DISABLE;
|
|
#endif
|
|
PIN_FUNC_SELECT(pin_mux[pin], pin_func[pin]);
|
|
//disable interrupt
|
|
gpio_pin_intr_state_set(GPIO_ID_PIN(pin_num[pin]), GPIO_PIN_INTR_DISABLE);
|
|
//clear interrupt status
|
|
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(pin_num[pin]));
|
|
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[pin])), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[pin]))) & (~ GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE))); //disable open drain;
|
|
ETS_GPIO_INTR_ENABLE();
|
|
break;
|
|
#ifdef GPIO_INTERRUPT_ENABLE
|
|
case PLATFORM_GPIO_INT:
|
|
ETS_GPIO_INTR_DISABLE();
|
|
PIN_FUNC_SELECT(pin_mux[pin], pin_func[pin]);
|
|
GPIO_DIS_OUTPUT(pin_num[pin]);
|
|
gpio_register_set(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[pin])), GPIO_PIN_INT_TYPE_SET(GPIO_PIN_INTR_DISABLE)
|
|
| GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_DISABLE)
|
|
| GPIO_PIN_SOURCE_SET(GPIO_AS_PIN_SOURCE));
|
|
ETS_GPIO_INTR_ENABLE();
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int platform_gpio_write( unsigned pin, unsigned level )
|
|
{
|
|
// NODE_DBG("Function platform_gpio_write() is called. pin:%d, level:%d\n",GPIO_ID_PIN(pin_num[pin]),level);
|
|
if (pin >= NUM_GPIO)
|
|
return -1;
|
|
if(pin == 0){
|
|
gpio16_output_conf();
|
|
gpio16_output_set(level);
|
|
return 1;
|
|
}
|
|
|
|
GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), level);
|
|
}
|
|
|
|
int platform_gpio_read( unsigned pin )
|
|
{
|
|
// NODE_DBG("Function platform_gpio_read() is called. pin:%d\n",GPIO_ID_PIN(pin_num[pin]));
|
|
if (pin >= NUM_GPIO)
|
|
return -1;
|
|
|
|
if(pin == 0){
|
|
// gpio16_input_conf();
|
|
return 0x1 & gpio16_input_get();
|
|
}
|
|
|
|
// GPIO_DIS_OUTPUT(pin_num[pin]);
|
|
return 0x1 & GPIO_INPUT_GET(GPIO_ID_PIN(pin_num[pin]));
|
|
}
|
|
|
|
#ifdef GPIO_INTERRUPT_ENABLE
|
|
static void platform_gpio_intr_dispatcher( platform_gpio_intr_handler_fn_t cb){
|
|
uint8 i, level;
|
|
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
|
|
for (i = 0; i < GPIO_PIN_NUM; i++) {
|
|
if (pin_int_type[i] && (gpio_status & BIT(pin_num[i])) ) {
|
|
//disable interrupt
|
|
gpio_pin_intr_state_set(GPIO_ID_PIN(pin_num[i]), GPIO_PIN_INTR_DISABLE);
|
|
//clear interrupt status
|
|
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(pin_num[i]));
|
|
level = 0x1 & GPIO_INPUT_GET(GPIO_ID_PIN(pin_num[i]));
|
|
if(cb){
|
|
cb(i, level);
|
|
}
|
|
gpio_pin_intr_state_set(GPIO_ID_PIN(pin_num[i]), pin_int_type[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void platform_gpio_init( platform_gpio_intr_handler_fn_t cb )
|
|
{
|
|
ETS_GPIO_INTR_ATTACH(platform_gpio_intr_dispatcher, cb);
|
|
}
|
|
|
|
int platform_gpio_intr_init( unsigned pin, GPIO_INT_TYPE type )
|
|
{
|
|
if (pin >= NUM_GPIO)
|
|
return -1;
|
|
ETS_GPIO_INTR_DISABLE();
|
|
//clear interrupt status
|
|
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(pin_num[pin]));
|
|
pin_int_type[pin] = type;
|
|
//enable interrupt
|
|
gpio_pin_intr_state_set(GPIO_ID_PIN(pin_num[pin]), type);
|
|
ETS_GPIO_INTR_ENABLE();
|
|
}
|
|
#endif
|
|
|
|
// ****************************************************************************
|
|
// UART
|
|
// TODO: Support timeouts.
|
|
|
|
// UartDev is defined and initialized in rom code.
|
|
extern UartDevice UartDev;
|
|
uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int parity, int stopbits )
|
|
{
|
|
switch( baud )
|
|
{
|
|
case BIT_RATE_300:
|
|
case BIT_RATE_600:
|
|
case BIT_RATE_1200:
|
|
case BIT_RATE_2400:
|
|
case BIT_RATE_4800:
|
|
case BIT_RATE_9600:
|
|
case BIT_RATE_19200:
|
|
case BIT_RATE_38400:
|
|
case BIT_RATE_57600:
|
|
case BIT_RATE_74880:
|
|
case BIT_RATE_115200:
|
|
case BIT_RATE_230400:
|
|
case BIT_RATE_460800:
|
|
case BIT_RATE_921600:
|
|
case BIT_RATE_1843200:
|
|
case BIT_RATE_3686400:
|
|
UartDev.baut_rate = baud;
|
|
break;
|
|
default:
|
|
UartDev.baut_rate = BIT_RATE_9600;
|
|
break;
|
|
}
|
|
|
|
switch( databits )
|
|
{
|
|
case 5:
|
|
UartDev.data_bits = FIVE_BITS;
|
|
break;
|
|
case 6:
|
|
UartDev.data_bits = SIX_BITS;
|
|
break;
|
|
case 7:
|
|
UartDev.data_bits = SEVEN_BITS;
|
|
break;
|
|
case 8:
|
|
UartDev.data_bits = EIGHT_BITS;
|
|
break;
|
|
default:
|
|
UartDev.data_bits = EIGHT_BITS;
|
|
break;
|
|
}
|
|
|
|
switch (stopbits)
|
|
{
|
|
case PLATFORM_UART_STOPBITS_1:
|
|
UartDev.stop_bits = ONE_STOP_BIT;
|
|
break;
|
|
case PLATFORM_UART_STOPBITS_2:
|
|
UartDev.stop_bits = TWO_STOP_BIT;
|
|
break;
|
|
default:
|
|
UartDev.stop_bits = ONE_STOP_BIT;
|
|
break;
|
|
}
|
|
|
|
switch (parity)
|
|
{
|
|
case PLATFORM_UART_PARITY_EVEN:
|
|
UartDev.parity = EVEN_BITS;
|
|
break;
|
|
case PLATFORM_UART_PARITY_ODD:
|
|
UartDev.parity = ODD_BITS;
|
|
break;
|
|
default:
|
|
UartDev.parity = NONE_BITS;
|
|
break;
|
|
}
|
|
|
|
uart_setup(id);
|
|
|
|
return baud;
|
|
}
|
|
|
|
// if set=1, then alternate serial output pins are used. (15=rx, 13=tx)
|
|
void platform_uart_alt( int set )
|
|
{
|
|
uart0_alt( set );
|
|
return;
|
|
}
|
|
|
|
|
|
// Send: version with and without mux
|
|
void platform_uart_send( unsigned id, u8 data )
|
|
{
|
|
uart_tx_one_char(id, data);
|
|
}
|
|
|
|
// ****************************************************************************
|
|
// PWMs
|
|
|
|
static uint16_t pwms_duty[NUM_PWM] = {0};
|
|
|
|
static void pwms_init()
|
|
{
|
|
int i;
|
|
for(i=0;i<NUM_PWM;i++){
|
|
pwms_duty[i] = DUTY(0);
|
|
}
|
|
pwm_init(500, NULL);
|
|
// NODE_DBG("Function pwms_init() is called.\n");
|
|
}
|
|
|
|
// Return the PWM clock
|
|
// NOTE: Can't find a function to query for the period set for the timer,
|
|
// therefore using the struct.
|
|
// This may require adjustment if driver libraries are updated.
|
|
uint32_t platform_pwm_get_clock( unsigned pin )
|
|
{
|
|
// NODE_DBG("Function platform_pwm_get_clock() is called.\n");
|
|
if( pin >= NUM_PWM)
|
|
return 0;
|
|
if(!pwm_exist(pin))
|
|
return 0;
|
|
|
|
return (uint32_t)pwm_get_freq(pin);
|
|
}
|
|
|
|
// Set the PWM clock
|
|
uint32_t platform_pwm_set_clock( unsigned pin, uint32_t clock )
|
|
{
|
|
// NODE_DBG("Function platform_pwm_set_clock() is called.\n");
|
|
if( pin >= NUM_PWM)
|
|
return 0;
|
|
if(!pwm_exist(pin))
|
|
return 0;
|
|
|
|
pwm_set_freq((uint16_t)clock, pin);
|
|
pwm_start();
|
|
return (uint32_t)pwm_get_freq( pin );
|
|
}
|
|
|
|
uint32_t platform_pwm_get_duty( unsigned pin )
|
|
{
|
|
// NODE_DBG("Function platform_pwm_get_duty() is called.\n");
|
|
if( pin < NUM_PWM){
|
|
if(!pwm_exist(pin))
|
|
return 0;
|
|
// return NORMAL_DUTY(pwm_get_duty(pin));
|
|
return pwms_duty[pin];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Set the PWM duty
|
|
uint32_t platform_pwm_set_duty( unsigned pin, uint32_t duty )
|
|
{
|
|
// NODE_DBG("Function platform_pwm_set_duty() is called.\n");
|
|
if ( pin < NUM_PWM)
|
|
{
|
|
if(!pwm_exist(pin))
|
|
return 0;
|
|
pwm_set_duty(DUTY(duty), pin);
|
|
} else {
|
|
return 0;
|
|
}
|
|
pwm_start();
|
|
pwms_duty[pin] = NORMAL_DUTY(pwm_get_duty(pin));
|
|
return pwms_duty[pin];
|
|
}
|
|
|
|
uint32_t platform_pwm_setup( unsigned pin, uint32_t frequency, unsigned duty )
|
|
{
|
|
uint32_t clock;
|
|
if ( pin < NUM_PWM)
|
|
{
|
|
platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT); // disable gpio interrupt first
|
|
if(!pwm_add(pin))
|
|
return 0;
|
|
// pwm_set_duty(DUTY(duty), pin);
|
|
pwm_set_duty(0, pin);
|
|
pwms_duty[pin] = duty;
|
|
pwm_set_freq((uint16_t)frequency, pin);
|
|
} else {
|
|
return 0;
|
|
}
|
|
clock = platform_pwm_get_clock( pin );
|
|
pwm_start();
|
|
return clock;
|
|
}
|
|
|
|
void platform_pwm_close( unsigned pin )
|
|
{
|
|
// NODE_DBG("Function platform_pwm_stop() is called.\n");
|
|
if ( pin < NUM_PWM)
|
|
{
|
|
pwm_delete(pin);
|
|
pwm_start();
|
|
}
|
|
}
|
|
|
|
void platform_pwm_start( unsigned pin )
|
|
{
|
|
// NODE_DBG("Function platform_pwm_start() is called.\n");
|
|
if ( pin < NUM_PWM)
|
|
{
|
|
if(!pwm_exist(pin))
|
|
return;
|
|
pwm_set_duty(DUTY(pwms_duty[pin]), pin);
|
|
pwm_start();
|
|
}
|
|
}
|
|
|
|
void platform_pwm_stop( unsigned pin )
|
|
{
|
|
// NODE_DBG("Function platform_pwm_stop() is called.\n");
|
|
if ( pin < NUM_PWM)
|
|
{
|
|
if(!pwm_exist(pin))
|
|
return;
|
|
pwm_set_duty(0, pin);
|
|
pwm_start();
|
|
}
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// I2C platform interface
|
|
|
|
uint32_t platform_i2c_setup( unsigned id, uint8_t sda, uint8_t scl, uint32_t speed ){
|
|
if (sda >= NUM_GPIO || scl >= NUM_GPIO)
|
|
return 0;
|
|
|
|
// platform_pwm_close(sda);
|
|
// platform_pwm_close(scl);
|
|
|
|
// disable gpio interrupt first
|
|
platform_gpio_mode(sda, PLATFORM_GPIO_INPUT, PLATFORM_GPIO_PULLUP); // inside this func call platform_pwm_close
|
|
platform_gpio_mode(scl, PLATFORM_GPIO_INPUT, PLATFORM_GPIO_PULLUP); // disable gpio interrupt first
|
|
|
|
i2c_master_gpio_init(sda, scl);
|
|
return PLATFORM_I2C_SPEED_SLOW;
|
|
}
|
|
|
|
void platform_i2c_send_start( unsigned id ){
|
|
i2c_master_start();
|
|
}
|
|
|
|
void platform_i2c_send_stop( unsigned id ){
|
|
i2c_master_stop();
|
|
}
|
|
|
|
int platform_i2c_send_address( unsigned id, uint16_t address, int direction ){
|
|
// Convert enum codes to R/w bit value.
|
|
// If TX == 0 and RX == 1, this test will be removed by the compiler
|
|
if ( ! ( PLATFORM_I2C_DIRECTION_TRANSMITTER == 0 &&
|
|
PLATFORM_I2C_DIRECTION_RECEIVER == 1 ) ) {
|
|
direction = ( direction == PLATFORM_I2C_DIRECTION_TRANSMITTER ) ? 0 : 1;
|
|
}
|
|
|
|
i2c_master_writeByte( (uint8_t) ((address << 1) | direction ));
|
|
// Low-level returns nack (0=acked); we return ack (1=acked).
|
|
return ! i2c_master_getAck();
|
|
}
|
|
|
|
int platform_i2c_send_byte( unsigned id, uint8_t data ){
|
|
i2c_master_writeByte(data);
|
|
// Low-level returns nack (0=acked); we return ack (1=acked).
|
|
return ! i2c_master_getAck();
|
|
}
|
|
|
|
int platform_i2c_recv_byte( unsigned id, int ack ){
|
|
uint8_t r = i2c_master_readByte();
|
|
i2c_master_setAck( !ack );
|
|
return r;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// SPI platform interface
|
|
uint32_t platform_spi_setup( uint8_t id, int mode, unsigned cpol, unsigned cpha, uint32_t clock_div)
|
|
{
|
|
spi_master_init( id, cpol, cpha, clock_div );
|
|
return 1;
|
|
}
|
|
|
|
int platform_spi_send( uint8_t id, uint8_t bitlen, spi_data_type data )
|
|
{
|
|
if (bitlen > 32)
|
|
return PLATFORM_ERR;
|
|
|
|
spi_mast_transaction( id, 0, 0, bitlen, data, 0, 0, 0 );
|
|
return PLATFORM_OK;
|
|
}
|
|
|
|
spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type data )
|
|
{
|
|
if (bitlen > 32)
|
|
return 0;
|
|
|
|
spi_mast_set_mosi( id, 0, bitlen, data );
|
|
spi_mast_transaction( id, 0, 0, 0, 0, bitlen, 0, -1 );
|
|
return spi_mast_get_miso( id, 0, bitlen );
|
|
}
|
|
|
|
int platform_spi_set_mosi( uint8_t id, uint8_t offset, uint8_t bitlen, spi_data_type data )
|
|
{
|
|
if (offset + bitlen > 512)
|
|
return PLATFORM_ERR;
|
|
|
|
spi_mast_set_mosi( id, offset, bitlen, data );
|
|
|
|
return PLATFORM_OK;
|
|
}
|
|
|
|
spi_data_type platform_spi_get_miso( uint8_t id, uint8_t offset, uint8_t bitlen )
|
|
{
|
|
if (offset + bitlen > 512)
|
|
return 0;
|
|
|
|
return spi_mast_get_miso( id, offset, bitlen );
|
|
}
|
|
|
|
int platform_spi_transaction( uint8_t id, uint8_t cmd_bitlen, spi_data_type cmd_data,
|
|
uint8_t addr_bitlen, spi_data_type addr_data,
|
|
uint16_t mosi_bitlen, uint8_t dummy_bitlen, int16_t miso_bitlen )
|
|
{
|
|
if ((cmd_bitlen > 16) ||
|
|
(addr_bitlen > 32) ||
|
|
(mosi_bitlen > 512) ||
|
|
(dummy_bitlen > 256) ||
|
|
(miso_bitlen > 512))
|
|
return PLATFORM_ERR;
|
|
|
|
spi_mast_transaction( id, cmd_bitlen, cmd_data, addr_bitlen, addr_data, mosi_bitlen, dummy_bitlen, miso_bitlen );
|
|
|
|
return PLATFORM_OK;
|
|
}
|
|
|
|
// ****************************************************************************
|
|
// Flash access functions
|
|
|
|
/*
|
|
* Assumptions:
|
|
* > toaddr is INTERNAL_FLASH_WRITE_UNIT_SIZE aligned
|
|
* > size is a multiple of INTERNAL_FLASH_WRITE_UNIT_SIZE
|
|
*/
|
|
uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t size )
|
|
{
|
|
SpiFlashOpResult r;
|
|
const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
|
|
uint32_t *apbuf = NULL;
|
|
uint32_t fromaddr = (uint32_t)from;
|
|
if( (fromaddr & blkmask ) || (fromaddr >= INTERNAL_FLASH_MAPPED_ADDRESS)) {
|
|
apbuf = (uint32_t *)c_malloc(size);
|
|
if(!apbuf)
|
|
return 0;
|
|
c_memcpy(apbuf, from, size);
|
|
}
|
|
system_soft_wdt_feed ();
|
|
r = flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size);
|
|
if(apbuf)
|
|
c_free(apbuf);
|
|
if(SPI_FLASH_RESULT_OK == r)
|
|
return size;
|
|
else{
|
|
NODE_ERR( "ERROR in flash_write: r=%d at %08X\n", ( int )r, ( unsigned )toaddr);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Assumptions:
|
|
* > fromaddr is INTERNAL_FLASH_READ_UNIT_SIZE aligned
|
|
* > size is a multiple of INTERNAL_FLASH_READ_UNIT_SIZE
|
|
*/
|
|
uint32_t platform_s_flash_read( void *to, uint32_t fromaddr, uint32_t size )
|
|
{
|
|
if (size==0)
|
|
return 0;
|
|
|
|
SpiFlashOpResult r;
|
|
system_soft_wdt_feed ();
|
|
|
|
const uint32_t blkmask = (INTERNAL_FLASH_READ_UNIT_SIZE - 1);
|
|
if( ((uint32_t)to) & blkmask )
|
|
{
|
|
uint32_t size2=size-INTERNAL_FLASH_READ_UNIT_SIZE;
|
|
uint32* to2=(uint32*)((((uint32_t)to)&(~blkmask))+INTERNAL_FLASH_READ_UNIT_SIZE);
|
|
r = flash_read(fromaddr, to2, size2);
|
|
if(SPI_FLASH_RESULT_OK == r)
|
|
{
|
|
os_memmove(to,to2,size2);
|
|
char back[ INTERNAL_FLASH_READ_UNIT_SIZE ] __attribute__ ((aligned(INTERNAL_FLASH_READ_UNIT_SIZE)));
|
|
r=flash_read(fromaddr+size2,(uint32*)back,INTERNAL_FLASH_READ_UNIT_SIZE);
|
|
os_memcpy((uint8_t*)to+size2,back,INTERNAL_FLASH_READ_UNIT_SIZE);
|
|
}
|
|
}
|
|
else
|
|
r = flash_read(fromaddr, (uint32 *)to, size);
|
|
|
|
if(SPI_FLASH_RESULT_OK == r)
|
|
return size;
|
|
else{
|
|
NODE_ERR( "ERROR in flash_read: r=%d at %08X\n", ( int )r, ( unsigned )fromaddr);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int platform_flash_erase_sector( uint32_t sector_id )
|
|
{
|
|
system_soft_wdt_feed ();
|
|
return flash_erase( sector_id ) == SPI_FLASH_RESULT_OK ? PLATFORM_OK : PLATFORM_ERR;
|
|
}
|