bbill 0 4 апреля, 2010 Опубликовано 4 апреля, 2010 · Жалоба Помогите разобраться с ошибкой. При чтении данных с EEPROMa в переменную, данные оказываются в RAM по другому адресу. Описание проблемы: В main.c, по флагу вызывается функция, которая читает данные из EEPROMa в глобальную переменную. if(DevFlag.ReadDataEE) { ReReadDataEE(); } Флаг вызова ф-ии устанавливается в прерывании. Структура(флаги) объявлена main.c: typedef struct { volatile u_char Regim12 :1, // ... ReadDataEE :1, //считать с EEPROMa ... }dev_fl; dev_fl DevFlag; u_int ContrValueData, ContrValueTest; В функции очищается флаг вызова функции и читаются данные. Если флаг очищается сразу после входа в функцию, то данные пишутся по другому адресу. Если если перед выходом из ф-ии, то по адресу переменной(правильно). В чем ошибка? Функция чтения данных: void ReReadDataEE(void) { //если сброс флага здесь, то ошибка в адресе записи в RAM __disable_interrupt(); DevFlag.ReadDataEE = 0; __enable_interrupt(); if(!DevFlag.Regim12) { ContrValueData = ReadIntDataEE(ADR_DATA1_EE); ContrValueTest = ReadIntDataEE(ADR_DATA2_EE); } else { ContrValueData = ReadIntDataEE(ADR_DATA12_EE); } //если сброс флага здесь, то ошибки нет /* __disable_interrupt(); DevFlag.ReadDataEE = 0; __enable_interrupt(); */ } Расположение переменных из map файла: ContrValueTest DATA 0000007E ContrValueData DATA 0000007C TimerData DATA 0000007A //------------------------------------------------------------------------------ Листинг 1, с ошибкой: 312 void ReReadDataEE(void) \ ReReadDataEE: 313 { \ 00000000 93AA ST -Y, R26 314 //если сброс флага здесь, то ошибка в адресе записи в RAM 315 __disable_interrupt(); \ 00000002 94F8 CLI 316 DevFlag.ReadDataEE = 0; \ 00000004 .... LDI R26, (TimerData + 8) & 0xFF \ 00000006 910C LD R16, X \ 00000008 .... LDI R26, (TimerData) & 0xFF \ 0000000A 7F07 ANDI R16, 0xF7 \ 0000000C 930C ST X, R16 317 __enable_interrupt(); \ 0000000E 9478 SEI 318 319 if(!DevFlag.Regim12) { \ 00000010 910C LD R16, X \ 00000012 FD00 SBRC R16, 0 \ 00000014 C009 RJMP ??ReReadDataEE_0 320 ContrValueData = ReadIntDataEE(ADR_DATA1_EE); \ 00000016 E007 LDI R16, 7 \ 00000018 .... RCALL ReadIntDataEE \ 0000001A .... LDI R26, (TimerData - 6) & 0xFF //вот здесь задается ошибочный адрес \ 0000001C 930D ST X+, R16 \ 0000001E 931C ST X, R17 321 ContrValueTest = ReadIntDataEE(ADR_DATA2_EE); \ 00000020 E003 LDI R16, 3 \ 00000022 .... RCALL ReadIntDataEE \ 00000024 .... LDI R26, (TimerData - 4) & 0xFF \ 00000026 C003 RJMP ??ReReadDataEE_1 322 } 323 else { 324 ContrValueData = ReadIntDataEE(ADR_DATA12_EE); // \ ??ReReadDataEE_0: \ 00000028 E00B LDI R16, 11 \ 0000002A .... RCALL ReadIntDataEE \ 0000002C .... LDI R26, (TimerData - 6) & 0xFF \ ??ReReadDataEE_1: \ 0000002E 930D ST X+, R16 \ 00000030 931C ST X, R17 325 } 326 } \ 00000032 91A9 LD R26, Y+ \ 00000034 9508 RET Листинг 2, без ошибки: 312 void ReReadDataEE(void) \ ReReadDataEE: 313 { \ 00000000 93AA ST -Y, R26 314 if(!DevFlag.Regim12) { \ 00000002 .... LDI R26, (TimerData + 8) & 0xFF \ 00000004 910C LD R16, X \ 00000006 FD00 SBRC R16, 0 \ 00000008 C009 RJMP ??ReReadDataEE_0 315 ContrValueData = ReadIntDataEE(ADR_DATA1_EE); \ 0000000A E007 LDI R16, 7 \ 0000000C .... RCALL ReadIntDataEE \ 0000000E .... LDI R26, (TimerData + 2) & 0xFF \ 00000010 930D ST X+, R16 \ 00000012 931C ST X, R17 316 ContrValueTest = ReadIntDataEE(ADR_DATA2_EE); \ 00000014 E003 LDI R16, 3 \ 00000016 .... RCALL ReadIntDataEE \ 00000018 .... LDI R26, (TimerData + 4) & 0xFF \ 0000001A C003 RJMP ??ReReadDataEE_1 317 } 318 else { 319 ContrValueData = ReadIntDataEE(ADR_DATA12_EE); // \ ??ReReadDataEE_0: \ 0000001C E00B LDI R16, 11 \ 0000001E .... RCALL ReadIntDataEE \ 00000020 .... LDI R26, (TimerData + 2) & 0xFF \ ??ReReadDataEE_1: \ 00000022 930D ST X+, R16 \ 00000024 931C ST X, R17 320 } 321 //если сброс флага здесь, то ошибки адреса нет 322 __disable_interrupt(); \ 00000026 94F8 CLI 323 DevFlag.ReadDataEE = 0; \ 00000028 .... LDI R26, (TimerData + 8) & 0xFF \ 0000002A 910C LD R16, X \ 0000002C .... LDI R26, (TimerData) & 0xFF \ 0000002E 7F07 ANDI R16, 0xF7 \ 00000030 930C ST X, R16 324 __enable_interrupt(); \ 00000032 9478 SEI 325 } \ 00000034 91A9 LD R26, Y+ \ 00000036 9508 RET Компилятор IAR 5.30, контроллер tiny26. Оптимизация максимальная, по скорости. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 5 апреля, 2010 Опубликовано 5 апреля, 2010 · Жалоба листинги нечитаемые. ну а по проблеме - дело скорее всего в том, что надо обеспечить атомарность для всего байта структуры в который попал флаг ReadDataEE (модифицируемый в прерывании). либо ReadDataEE сделать байтом, а не битом в структуре, потому как пока он бит, то все операции записи этого флага делаются как Read-Modify-Write для БАЙТА и затрагивают еще 7 бит вашей структуры. PS: Никакой ошибки компиляции тут нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться