Например TDA7294

Форум РадиоКот • Просмотр темы - Проблема записи в EEPROM.
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Ср апр 24, 2024 18:36:03

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 10 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: Проблема записи в EEPROM.
СообщениеДобавлено: Чт янв 14, 2021 14:37:43 
Открыл глаза
Аватар пользователя

Зарегистрирован: Вт авг 13, 2013 12:13:07
Сообщений: 47
Рейтинг сообщения: 0
Приветствую. Пытаюсь перенести кусок кода не своего с ATmega128 на ATmega2560, и возникает проблема с записью из SRAM в EEPROM, а конкретно записывает одну переменную из семи, и дальше зависает. AVR Studio 4.18, оптимизация O3/Os
Код:
#define F_CPU 8000000UL // Я использую кристалл 8 МГц

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>

struct config_t {
  uint8_t cwl;            
  uint8_t cwh;            
  uint8_t tpsacold;       
  uint8_t divider;         
  uint8_t alternate;       
  uint8_t injpwm;         
  uint8_t injpwmt;
};

struct config_t config;
struct config_t config_ee EEMEM;


volatile uint8_t eeprom_store_idx;     /* счетчик обрабатываемых байт данных*/
volatile uint8_t eeprom_store_busy;    /* флаг, eeprom занято*/

/*
  Эта функция запускает процесс сохранение структуры конфигурации из sram в
  eeprom и немедленно возвращает управление,позволяя обработчику прерывания
  EEPROM продолжить работу по сохранению данных.
*/
uint8_t storeConfig(void) {

  if (eeprom_store_busy) {
    return -1;             /* eeprom занято, подождите! */
  }

  eeprom_store_idx = 0;      /* обнулить счетчик обрабатываемых байт данных*/
  eeprom_store_busy = 1;   /* установить флаг, eeprom занято*/
 
  EECR |= _BV(EERIE);      /* разрешить прерывание от eeprom */
  return 0;
}


/*
  время выполнения этого прерывания может быть достаточно высоким в случае
  самой плохой ситуации, это должно быть обязательно исследовано!
*/
SIGNAL(SIG_EEPROM_READY) {
  uint8_t *pe, *ps;
  uint8_t ebyte;

  pe = (uint8_t *)&config_ee + eeprom_store_idx; /* адрес данных в eeprom */
  ps = (uint8_t *)&config + eeprom_store_idx;    /* адрес данных в sram */
  ebyte = eeprom_read_byte(pe);

  /* перезаписывать данные в eeprom будем только если это необходимо */
  /*
    сравним содержимое структур в sram и eeprom, выход из цикла
   осуществляем по первому найденному различию в данных
  */   
  while( (ebyte == *ps) && (eeprom_store_idx != (sizeof(struct config_t) - 1)) ) {
    eeprom_store_idx++;
    pe++;
    ps++;
    ebyte = eeprom_read_byte(pe);
  }

  /* записываем новое значение в eeprom */
  if (ebyte != *ps)
    eeprom_write_byte(pe, *ps);

  /*
    если последняя запись в структуре не достигнута переходим к поиску
   следующего различия данных в sram и eeprom
  */
  if (eeprom_store_idx == sizeof(struct config_t)-1) {    /* запись закончена */
      EECR &= ~_BV(EERIE);                          /* запретить прерывание от eeprom */
      eeprom_store_busy = 0;                     /* сбросить флаг, eeprom занято*/
      PORTB &= ~_BV(PB7);                      /* погасить светодиод */
  } else {                                     /* переходим к следующему различию */
      eeprom_store_idx++;
      PORTB |= _BV(PB7);                      /* зажечь светодиод */
  /*
    необходимо отметить, если светодиод горит более 5 сек следует снять питание
   с контроллера иначе возможно повреждение eeprom
  */
  }
}


int main(void){

   DDRB |= _BV (PB7);      //установить как выход LED
   PORTB &=~ _BV (PB7);   //установить 0 LED

   config.cwl=50;         //0x32
   config.cwh=65;         //0x41
   config.tpsacold=155;   //0x9B
   config.divider=48;      //0x30
   config.alternate=4;      //0x04
   config.injpwm=94;      //0x5E
   config.injpwmt=223;      //0xDF

   uint8_t i=0;

   if (i==0)
   {
      eeprom_write_byte(0x11, config.injpwm);
      i++;
   }

   sei();

   while(1){
   
   storeConfig();

   }
}


В EEPROM записывает только переменную cwl, и переменную injpwm по указанному адресу, далее цикл в программе не продолжается.

:10000000 32000000000000FFFFFFFFFFFFFFFFFF C7
:10001000 FF5EFFFFFFFFFFFFFFFFFFFFFFFFFFFF 91

Для записи остальных переменных нужно шесть раз сбросить работу МК, нажатием на кнопку RESET.
Предполагаю что обработчик прерывания SIG_EEPROM_READY не генерируется постоянно. Либо сбрасывается EERIE где-то. Что я делаю не так? Где может быть ошибка?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Проблема записи в EEPROM.
СообщениеДобавлено: Чт янв 14, 2021 14:52:32 
Мудрый кот

Карма: 11
Рейтинг сообщений: 114
Зарегистрирован: Пт июн 01, 2018 07:28:45
Сообщений: 1759
Рейтинг сообщения: 0
Я бы прогнал код в симуляторе студии и посмотрел, что к чему.

Обязательно учесть тот факт, что при выходе из прерывания, МК ОБЯЗАТЕЛЬНО исполняет одну следующую инструкцию программы (в данном случае функция main) и только потом снова входит в обработчик прерывания.

Ну и студию обновить до последней версии. Возможно, что что-то поменялось аппаратно у МК.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Проблема записи в EEPROM.
СообщениеДобавлено: Чт янв 14, 2021 16:05:15 
Открыл глаза
Аватар пользователя

Зарегистрирован: Вт авг 13, 2013 12:13:07
Сообщений: 47
Рейтинг сообщения: 0
Да, программа зависала в функции storeConfig() потому что перезапускалась через main. Но в симуляции ни разу не сработало прерывание SIG_EEPROM_READY, хотя в реале один раз запускается. Вынес функцию storeConfig() из main в прерывание таймера
Код:
ISR(TIMER0_OVF_vect)      //функция прерывания по переполнению Т0
{
storeConfig();
TIMSK0 &=~ _BV(TOIE0);
}

В симуляции выполняет как нужно функцию и уходит обратно в main в бесконечный цикл минуя прерывание епром.

Добавлено after 12 minutes 10 seconds:
В общем висит разрешение EERIE, но прерывание не происходит.


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay + Услуги 3D печати
Не в сети
 Заголовок сообщения: Re: Проблема записи в EEPROM.
СообщениеДобавлено: Чт янв 14, 2021 18:05:02 
Мудрый кот

Карма: 11
Рейтинг сообщений: 114
Зарегистрирован: Пт июн 01, 2018 07:28:45
Сообщений: 1759
Рейтинг сообщения: 0
В общем висит разрешение EERIE, но прерывание не происходит.

Чтобы оно произошло, необходимо поднять бит EEPE. Как только этот бит обнулится, сработает прерывание EERIE.


Вернуться наверх
 
Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Проблема записи в EEPROM.
СообщениеДобавлено: Чт янв 14, 2021 19:31:14 
Открыл глаза
Аватар пользователя

Зарегистрирован: Вт авг 13, 2013 12:13:07
Сообщений: 47
Рейтинг сообщения: 0
EEPE сбрасывается после записи, а если записи до этого не было?


Вернуться наверх
 
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Проблема записи в EEPROM.
СообщениеДобавлено: Чт янв 14, 2021 21:22:50 
Мудрый кот

Карма: 11
Рейтинг сообщений: 114
Зарегистрирован: Пт июн 01, 2018 07:28:45
Сообщений: 1759
Рейтинг сообщения: 0
EEPE сбрасывается после записи, а если записи до этого не было?


Значит всё: сушим вёсла. Прерывания по готовности контроллера EEPROM не будет.
В SPI та же проблема - флаг не встаёт, пока не запишешь в data регистр. Приходится писать, а только потом прерывание.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Проблема записи в EEPROM.
СообщениеДобавлено: Чт янв 14, 2021 22:12:19 
Открыл глаза
Аватар пользователя

Зарегистрирован: Вт авг 13, 2013 12:13:07
Сообщений: 47
Рейтинг сообщения: 0
Временно сделал прерывание через свободный таймер
Код:
#define F_CPU 8000000UL // Я использую кристалл 8 МГц

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>

struct config_t {
  uint8_t cwl;           
  uint8_t cwh;           
  uint8_t tpsacold;       
  uint8_t divider;         
  uint8_t alternate;       
  uint8_t injpwm;         
  uint8_t injpwmt;
};

struct config_t config;
struct config_t config_ee EEMEM;

volatile uint8_t c=0;

volatile uint8_t eeprom_store_idx;     /* счетчик обрабатываемых байт данных*/
volatile uint8_t eeprom_store_busy;    /* флаг, eeprom занято*/

/* Эта функция запускает процесс сохранение структуры конфигурации из sram в
  eeprom и немедленно возвращает управление,позволяя обработчику прерывания
  TIMER0 продолжить работу по сохранению данных. */
uint8_t storeConfig(void) {

  if (eeprom_store_busy) {
    return -1;             /* eeprom занято, подождите! */
  }

  eeprom_store_idx = 0;      /* обнулить счетчик обрабатываемых байт данных*/
  eeprom_store_busy = 1;   /* установить флаг, eeprom занято*/
 
  TCCR0B |=  _BV(CS00);      /* запустить таймер без предделителя */
  TCNT0=240;            /* за 16 тактов до переполнения */
  return 0;
}

/* время выполнения этого прерывания может быть достаточно высоким в случае
  самой плохой ситуации, это должно быть обязательно исследовано! */
ISR(TIMER0_OVF_vect) {
  uint8_t save_sreg=SREG;    /* сохранить регистр состояния */
  cli();               /* запретить прерывания */

  uint8_t *pe, *ps;
  uint8_t ebyte;

  pe = (uint8_t *)&config_ee + eeprom_store_idx; /* адрес данных в eeprom */
  ps = (uint8_t *)&config + eeprom_store_idx;    /* адрес данных в sram */
  ebyte = eeprom_read_byte(pe);

  /* перезаписывать данные в eeprom будем только если это необходимо */
  /* сравним содержимое структур в sram и eeprom, выход из цикла
   осуществляем по первому найденному различию в данных */   
  while( (ebyte == *ps) && (eeprom_store_idx != (sizeof(struct config_t) - 1)) ) {
    eeprom_store_idx++;
    pe++;
    ps++;
    ebyte = eeprom_read_byte(pe);
  }

  /* записываем новое значение в eeprom */
  if (ebyte != *ps)
    eeprom_write_byte(pe, *ps);

  /* если последняя запись в структуре не достигнута переходим к поиску
   следующего различия данных в sram и eeprom */
  if (eeprom_store_idx == sizeof(struct config_t)-1) {    /* запись закончена */
      TCCR0B &= ~_BV(CS00);                          /* выключить таймер */
      eeprom_store_busy = 0;                     /* сбросить флаг, eeprom занято*/
      PORTB &= ~_BV(PB7);                      /* погасить светодиод */
  } else {                                     /* переходим к следующему различию */
      eeprom_store_idx++;
      PORTB |= _BV(PB7);                      /* зажечь светодиод */
     TCNT0=240;                     /* обновить регистр счёта */
  /* необходимо отметить, если светодиод горит более 5 сек следует снять питание
   с контроллера иначе возможно повреждение eeprom */
  }
  SREG=save_sreg;      /* восстановить регистр состояния */
}

int main(void){

   DDRB |= _BV (PB7);      //установить как выход LED
   PORTB &=~ _BV (PB7);   //установить 0 LED

   config.cwl=50;         //0x32
   config.cwh=65;         //0x41
   config.tpsacold=155;   //0x9B
   config.divider=48;      //0x30
   config.alternate=4;      //0x04
   config.injpwm=94;      //0x5E
   config.injpwmt=223;      //0xDF

   TIMSK0 |= _BV(TOIE0);   //разрешить прерывание по переполнению таймера Т0

   sei();

   while(1){

      if (c==0)
      {
      c=1;
      storeConfig();
      }
   }
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Проблема записи в EEPROM.
СообщениеДобавлено: Чт янв 14, 2021 22:41:58 
Мудрый кот

Карма: 11
Рейтинг сообщений: 114
Зарегистрирован: Пт июн 01, 2018 07:28:45
Сообщений: 1759
Рейтинг сообщения: 0
Я бы в принципе пересмотрел концепцию (алгоритм) программы. Мы ж ведь так или иначе опрашиваем флаг занятости контроллера EEPROM (eeprom_store_busy). Так что мешает тогда всю работу делать в отдельной функции?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Проблема записи в EEPROM.
СообщениеДобавлено: Пт янв 15, 2021 04:00:49 
Открыл глаза
Аватар пользователя

Зарегистрирован: Вт авг 13, 2013 12:13:07
Сообщений: 47
Рейтинг сообщения: 0
Весь алгоритм записи в память я завёл целиком в storeConfig(), проверку байт и саму запись объединил в цикл while. Вроде прокатило. Нужно будет проверить не словит ли глюка в процессе работы остальных прерываний. Вопрос в том как это работало в оригинальном устройстве? И почему оно вообще работало? Может компилятор не того, в оригинале вроде как через WinAVR компилили, но во всем коде из 25 файлов я только подправил названия регистров, и всё зафурычило как надо, кроме записи в епром.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Проблема записи в EEPROM.
СообщениеДобавлено: Пт янв 15, 2021 09:54:55 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 141
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1384
Рейтинг сообщения: 0
Вечером, если не забуду, выложу свой пример. Если забуду, не стесняйтесь постучать в личку. Сдача объекта, занят.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 10 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 52


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y