Air-duino / Arduino-AirMCU

Arduino core for the Air MCU.
https://arduino.luatos.com/
MIT License
69 stars 21 forks source link

当内存空间占用达到65%左右时程序无法运行 #70

Closed lineleb closed 1 year ago

lineleb commented 1 year ago

描述一下这个bug / Describe the bug

写程序的时候之前调试一直时好的,增加了一些代码之后整个程序不工作,即使在setup部分的代码也不运行。起初怀疑是新增部分代码的问题,后来发现把编译器打开体积优化之后代码就可以运行了。 然后又重新尝试了一下别的程序 也是到65%左右就完全不运行。 芯片丝印后缀是3F1HH1A,不知道是不是这个批次的芯片flash空间不到32k?

复现步骤 / To Reproduce

#include <Wire.h>

#define EEPROM_ADDRESS 0x50
#define EEPROM_SIZE 16384
#define FIFO_SIZE 32

class EEPROMFIFO {
public:
  EEPROMFIFO() {
    Wire.begin();

    // 从EEPROM中读取索引值,如果没有存储则初始化为0
    readIndex = readIndexFromEEPROM();
    if (readIndex == -1) {
      readIndex = 0;
      writeIndexToEEPROM(readIndex);
    }

    writeIndex = readIndex;
  }

  // 向FIFO中写入数据
  void writeData(byte data) {
    if (isFull()) {
      // 如果FIFO已满,则删除最早写入的数据
      readIndex = (readIndex + 1) % FIFO_SIZE;
    }

    // 将数据写入EEPROM
    int address = EEPROM_ADDRESS + writeIndex;
    Wire.beginTransmission(EEPROM_ADDRESS);
    Wire.write((byte)(address >> 8)); // 高字节地址
    Wire.write((byte)(address & 0xFF)); // 低字节地址
    Wire.write(data); // 写入数据
    int result = Wire.endTransmission();

    if (result != 0) {
      Serial.print("Write error: ");
      Serial.println(result);
    }

    // 更新写入索引
    writeIndex = (writeIndex + 1) % FIFO_SIZE;

    // 将写入索引写入EEPROM
    writeIndexToEEPROM(writeIndex);
  }

  // 从FIFO中读取数据
  byte readData() {
    if (isEmpty()) {
      // 如果FIFO为空,则返回0或其他适当的值
      return 0;
    }

    // 从EEPROM中读取数据
    int address = EEPROM_ADDRESS + readIndex;
    Wire.beginTransmission(EEPROM_ADDRESS);
    Wire.write((byte)(address >> 8)); // 高字节地址
    Wire.write((byte)(address & 0xFF)); // 低字节地址
    int result = Wire.endTransmission();

    if (result != 0) {
      Serial.print("Read address error: ");
      Serial.println(result);
    }

    delay(5); // 添加延迟以确保EEPROM可以响应
    Wire.requestFrom(EEPROM_ADDRESS, 1);
    byte data = Wire.read();

    // 更新读取索引
    readIndex = (readIndex + 1) % FIFO_SIZE;

    // 将读取索引写入EEPROM
    writeIndexToEEPROM(readIndex);

    return data;
  }

  // 检查FIFO是否为空
  bool isEmpty() {
    return readIndex == writeIndex;
  }

  // 检查FIFO是否已满
  bool isFull() {
    return ((writeIndex + 1) % FIFO_SIZE) == readIndex;
  }

private:
  int readIndex;
  int writeIndex;

  // 从EEPROM中读取索引值
  int readIndexFromEEPROM() {
    int value;
    int address = EEPROM_ADDRESS + EEPROM_SIZE - 4 + readIndex;
    Wire.beginTransmission(EEPROM_ADDRESS);
    Wire.write((byte)(address >> 8)); // 高字节地址
    Wire.write((byte)(address & 0xFF)); // 低字节地址
    int result = Wire.endTransmission();

    if (result != 0) {
      Serial.print("Read index address error: ");
      Serial.println(result);
    }

    delay(5); // 添加延迟以确保EEPROM可以响应
    Wire.requestFrom(EEPROM_ADDRESS, 2);
    value = Wire.read() | (Wire.read() << 8);
    Serial.print("Read Index: ");
    Serial.println(value);
    return value;
  }

  // 将索引写入EEPROM
  void writeIndexToEEPROM(int index) {
    int address = EEPROM_ADDRESS + EEPROM_SIZE - 4 + index;
    Wire.beginTransmission(EEPROM_ADDRESS);
    Wire.write((byte)(address >> 8)); // 高字节地址
    Wire.write((byte)(address & 0xFF)); // 低字节地址
    Wire.write((byte)(index & 0xFF)); // 索引低字节
    Wire.write((byte)((index >> 8) & 0xFF)); // 索引高字节
    int result = Wire.endTransmission();

    if (result != 0) {
      Serial.print("Write index address error: ");
      Serial.println(result);
    }

    Serial.print("Write Index: ");
    Serial.println(index);
  }
};

EEPROMFIFO eepromFIFO;

void setup() {
  Serial.begin(9600);
}

void loop() {
  // 向FIFO中写入数据
  eepromFIFO.writeData('A');

  // 从FIFO中读取数据并打印
  if (!eepromFIFO.isEmpty()) {
    byte data = eepromFIFO.readData();
    Serial.print("Read data from FIFO: ");
    Serial.println(data);
  }

  delay(1000);
}

这段代码正好是编译优化前无法运行 优化后内存占用小一些可以运行

如果正常,应该是什么样 / Expected behavior

正常应该可以运行。

截图 / Screenshots

因为无法运行所以无法截图

日志 / Logs

因为无法运行所以没日志

系统 / System

Win10

PACK包版本 / Version

0.4.5

验证

chenxuuu commented 1 year ago

e2prom用的是flash空间,你的代码把代码区域擦了,写bug了

lineleb commented 1 year ago

我用的是外置的AT24C128,读写都是通过IIC实现的

HalfSweet commented 1 year ago

可尝试运行这个例子

https://gitee.com/openLuat/luatos-soc-air001/tree/master/ModuleDemo/Flash/Example_HAL/FLASH_SectorEraseAndWrite

chenxuuu commented 1 year ago

给芯片拍张照吧,没见过3F1HH1A丝印的版本

chenxuuu commented 1 year ago

已使用同一批次同一丝印芯片测试,正常运行,无法复现你描述的问题

 项目使用 32196 字节(98%)的程序存储空间。最大值为 32768 字节。
 个全局变量使用 1112 个字节(27%)的动态内存,剩下 2984 个字节用于局部变量。最大值为 4096 字节。
AirISP v1.2.7.0
串口 COM27
连接中...
Chip PID is: 0x04 0x40 
擦除flash中(请耐心等待)...
擦除成功,耗时 71.9146 ms.
start write data ...
Write 32512 bytes at 0x08000000 in 23719.9374 ms

Leaving...
通过RTS硬件复位...

代码:

const static unsigned char t[1024*21] = {0};

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  for(int i=0;i<sizeof(t);i++)
    delay(t[i]);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
}
lineleb commented 1 year ago

那可能不是flash的问题,我再检查一下是什么原因。 用我提供的代码应该可以复现开启优化可以运行,默认优化无法运行的问题。