Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: странности в работе f5437a
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
shide_3
Здравствуйте!прошу помочь советом или направить в нужное русло, потому как у самого идеи уже кончились. был проект на 149-м MSP, переделали его под msp430f5437a, соответственно ничего существенного в коде программы не меняли, только ноги и некоторые названия регистров, и само собой, настройка PMM. проблема такова- есть прерывания по uart rx и tx, при срабатывании RX (прием кадра modbus ascii) кадр принимается нормально (несколько символов), затем по программе должен формироваться кадр ответа, но программа не доходит до нужной подпрограммы, она просто зависает каждый раз в разных местах, но чаще всего на обработке TX (даже когда прерывание TX я специально отключаю!). повторюсь-в коде ничего существенно не меняли. работал с отладчиком TI USB-FET. скорость uart 115200, пробовал и 9600. (но похоже он тут ни при чем)
короче, в итоге устройство абсолютно нерабочее! прошу, подскажите пож. может кто-то испытывал подобные трудности.
кристалл работал вначале от внешнего резонатора 25 Мгц, после проявления вышеописанных проблем я перевел его на DCO (2 мгц), стало лучше, но выполнение программы заканчивается все равно раньше конца подпрограммы (я смотрел пошагово отладчиком).
может у кого были похожие симптомы? незнаю уже на кого грешить.
спасибо всем
rezident
Цитата(shide_3 @ Dec 3 2013, 16:38) *
был проект на 149-м MSP, переделали его под msp430f5437a, соответственно ничего существенного в коде программы не меняли, только ноги и некоторые названия регистров, и само собой, настройка PMM.

В MSP430F149 UART реализуется в модуле USART, а в MSP430F5438A UART в модуле USCI. У этих модулей, кроме названий регистров, немало и других отличий. Поэтому код, разработанный для USART, даже после переименования регистров, не будет рабоать с модулем USCI. Цитата из документа, описывающего переход от USART к USCI Migrating From MSP430F13x/14x to MSP430F23x/24x
Цитата
3.2.1 UART Mode
The operation of the MSP430F23x/24x USCI in UART mode and that of the MSP430F13x/14x USART are
almost identical. The major differences are:
• The MSP430F23x/24x USCI uses a different baud rate generator. It utilizes a new modulation scheme,
provides a two-stage modulator, and can be used to implement an oversampling baud rate generation
scheme. During application migration, the baud rate register settings need to be recalculated.
However, it is safe to say that the USCI module can be used to generate the same target baud rate
using the same clock source that the MSP430F13x/14x USART would be able to provide.
• The start edge detection and clock activation schemes are different on the two devices. The
MSP430F23x/24x features a simplified scheme whereby the USCI module automatically activates the
USCI module clock source upon start edge detection and then provides an interrupt to wake up the
CPU after the entire character has been received. On the MSP430F13x/14x UART, an interrupt is
generated directly upon start edge detection, the application needs to handle the clock source
activation itself, and then, as a second step, the character reception.
• On the MSP430F23x/24x USCI, interrupt flags are no longer cleared automatically upon entering the
interrupt service routine
.

Если хотите конкретной помощи. то приводите ваш код для инициализации USCI (конечно, если это не ASM rolleyes.gif ).
shide_3
void UART_Init(unsigned long BaudRate,unsigned char MbMode)
{

UCA0CTL1 |= UCSWRST; // **Put state machine in reset**
UCA0CTL0 |= UCSPB + UC7BIT;//UCPEN + UCPAR ;//+
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 109;//0xD9;//109;//;//27 // 25MHz 115200 (see User's Guide)
UCA0BR1 = 0;//0; // 25MHz 115200
UCA0MCTL |= UCBRS_2;//|= UCBRS_2;
// UCA0MCTL |= UCBRS_4 + UCBRF_1 + UCOS16; // Modulation UCBRSx=1, UCBRFx=0
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCA0IE |= UCRXIE ;//+ UCTXIE; // Enable USCI_A0 RX interrupt

// __bis_SR_register(LPM0_bits + GIE); // Enter LPM0, interrupts enabled
// __no_operation(); // For debugger

}//сейчас скорость 9600 от DCO 1048576 hz.

А,кстати, интеррапт флаги usci автоматически сбрасываются. это видно в отладке




вот инициализация остального:

void Peripheral_Setup(void)
{
unsigned int i;

WDTCTL = WDTPW + WDTHOLD; // Stop WDT
//==============================================================================
// Perepherial setup //
//==============================================================================
P1SEL = 0x00; // no alt. functions
P1OUT = 0x00;
P1DIR = 0xFF;

P2SEL = 0x00; // no alt. functions
P2DIR = 0x00; // input direction

P3SEL = 0x00; // no alt. functions
P3DIR = 0x00;
P3SEL = bmTxD | bmRxD; // USART0 TXD/RXD alt. functions
P3DIR = bmTxD; //TxD - out; RxD - in

///////////////////////////////////////////////////////////////

//SetVcore (0x03);
// UCSCTL6 &= ~XT2OFF; // Enable XT2
UCSCTL3 |= SELREF_2; // FLLref = REFO
// Since LFXT1 is not used,
// sourcing FLL with LFXT1 can cause
// XT1OFFG flag to set
UCSCTL4 |= SELA_2 + SELS_3 + SELM_3; // ACLK=REFO,SMCLK=DCO,MCLK=DCO
UCSCTL6 &= ~XT2DRIVE_3; // Clear XT2drive field
// Loop until XT1,XT2 & DCO stabilizes - in this case loop until XT2 settles
/* do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG_L + DCOFFG);
// Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
} while (SFRIFG1 & OFIFG); */ // Test oscillator fault flag

// UCSCTL6 &= ~XT2DRIVE0; // Decrease XT2 Drive according to
// expected frequency
// UCSCTL6 |= XTS; //
// UCSCTL6 |= XT2DRIVE_3; // Set requested value
// UCSCTL4 = SELS_5 + SELM_5;

}

void SetVcore (unsigned int level)
{
//#ifdef MSP
// Open PMM registers for write
PMMCTL0_H = PMMPW_H;
// Set SVS/SVM high side new level SVMHE = 1, SVSMHRRL
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
// Set SVM low side to new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Wait till SVM is settled
while ((PMMIFG & SVSMLDLYIFG) == 0);
// Clear already set flags
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
// Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
// Wait till new level reached
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0);
// Set SVS/SVM low side to new level
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
// Lock PMM registers for write access
PMMCTL0_H = 0x00;
//#endif
}

cейчас половина закомментирована, т.к. тактируемся от DCO
shide_3
может, 25 мгц виноваты- всетаки это предельная частота? но при тактировании от dco все равно глюки остаются, хотя меньше. насколько этот dco стабилен и может ли вообще от него процессор нормально работать? может помедленнее поставить генерюк стоит?
rezident
Кварц 25МГц ни при чем. Генераторы и на бОльшей частоте могут работать. Сейчас нет времени досконально разбираться с инициализацией. Отмечу пока только то, за что глаз "зацепился".
1. При начальной инициализации нужно все регистры прописывать явными значениями, а не накладывать маски на якобы дефолтные состояния. Я уже давно и настоятельно это всем рекомендую sm.gif
2. Зачем вы инициализируете UART в 7-ми битном режиме? Протокол Modbus 8-ми битные символы использует.
3. Работа модулятора в USCI отличается от работы модулятора в USART. Я бы на вашем месте вообще пока модуляцию не использовал. Тем более, что ошибка битовой частоты получается всего 0,2%=(1048576/109-9600)/9600*100%
4. Эмулятор при чтении регистров для отображения их в окне View может изменять их состояние, сбрасывая прерывания. Следует учитывать такой эффект. Это к вашему замечанию "интеррапт флаги usci автоматически сбрасываются". Кстати, неплохо бы еще и обработчик перывания посмотреть.
5. Был/есть какой-то глюк/нюанс при использовании DCO для тактирования USCI при синхронизации FLL от REFO или часового кварца. То ли в errata описанный, то ли еще где. Найду - напишу. Суть в том, что синхронизация и модуляция DCO приводит в результате к девиации битовой частоты, которая значительно влияет на работу UART. При использовании DCO для тактирования UART рекомендуется подключать источник синхронизации (REFO или LFXT) только на время (авто)подстройки частоты DCO. Затем источник синхронизации следует отключать, чтобы DCO работал на тех значениях, что получились в результате подстройки.
Подробнее разберу вечером, когду будет время.
shide_3
Цитата(rezident @ Dec 4 2013, 12:34) *
2. Зачем вы инициализируете UART в 7-ми битном режиме? Протокол Modbus 8-ми битные символы использует.

как раз в нашем случае ascii modbus - 7 битный, это RTU-8 битный. и софт с соответствующими настройками (на 7 бит). кадр то нормально принимается, и скорее всего uart тут не виноват(может сам процессор?), программа просто затыкается на полпути при формировании фрейма ответа...

кстати, при 25 мгц программа затыкается немного раньше, и чаще всего попадает в обработчик прерывания TX.(там зацикливается). при DCO такого нет.

Цитата(rezident @ Dec 4 2013, 12:34) *
4. Эмулятор при чтении регистров для отображения их в окне View может изменять их состояние, сбрасывая прерывания. Следует учитывать такой эффект. Это к вашему замечанию "интеррапт флаги usci автоматически сбрасываются".

в мануале написано:
UCRXIFG and UCRXIE are reset by a
system reset PUC signal or when UCSWRST = 1. UCRXIFG is automatically reset when UCAxRXBUF is
read.


а вот обработчик

#pragma vector=USCI_A0_VECTOR


__interrupt void USCI_A0_ISR(void)
{
switch(__even_in_range(UCA0IV,4))

{
case 0:break; // Vector 0 - no interrupt
case 2:


b = UCA0RXBUF;




if ( UCA0STAT & UCRXERR ) return;
//__no_operation();


if ( BlockReceive ) return;

if(ModBusMode == MODE_ASCII)
{
if ( ! FrameReady )
{ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if(PDUlen >= 254){ PDUlen = 0; mbCRC16 = 0xFFFF; MB_Diag.BusCommErrorCount++; } //Message too long
if (! mbFrameStarted) // waiting for new frame
{
if (b == ':') // SOF
{
mbFrameStarted = 1;
mbAsciiChar = 0;
mbLRC = 0;
PDUlen = 0;
}
}
else
{
if((PDUlen != 0) && (b == ':')) { PDUlen = 0; MB_Diag.BusCommErrorCount++; } // SOF occured before previous EOF
if(b == 10)
{// EOF
if (mbLRC == 0)
{
FrameReady = 1;PDUlen--; mbFrameStarted = 0; Lock(); eventAdd();// UCA0IE |= UCTXIE ;
BlockReceive = 1;
return;
}
else
{
mbFrameStarted = 0; PDUlen = 0; MB_Diag.BusCommErrorCount++;
}
}

if (mbAsciiChar)
{
mbLRC += (serialPDU [PDUlen] = Get_ASCII_Byte(mbAsciiChar, cool.gif);
PDUlen ++;
mbAsciiChar = 0;
}
else
mbAsciiChar = b;
}
} // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}

break;

case 4:


// if ( FrameReady )
if ( BlockReceive )
{
if ( PDUlen >= ResponseLength )//ResponseLength
{
PDUlen = 0;
ResponseLength = 0;
FrameReady = 0;
mbFrameStarted = 0;

// while ((UCA0IFG & UCTXIFG) != UCTXIFG);

P7OUT &= ~BIT0; // RS485 direction = RECIEVE
UnLock();
BlockReceive = 0;
UCA0IE &= ~UCTXIE ;
}
else

__no_operation();
//UCA0TXBUF = serialPDU[1];}
UCA0TXBUF = (ModBusMode == MODE_ASCII)? transmitBuf[PDUlen++] : serialPDU[PDUlen++];}
//UCA0IE &= ~UCTXIE ;
}


break;

default: break;}

}
shide_3
эх. было бы наверное интересно и полезно опробовать заведомо рабочий прожект для подобного кристалла на своем. разумеется, не столь лажовый, как Flashing LED.
rezident
Цитата(shide_3 @ Dec 4 2013, 16:32) *
как раз в нашем случае ascii modbus - 7 битный, это RTU-8 битный. и софт с соответствующими настройками (на 7 бит).
В режиме ASCII используется бит четности и всего один стоповый бит. У вас четность не используется и два стоповых бита.
Цитата(shide_3 @ Dec 4 2013, 16:32) *
кстати, при 25 мгц программа затыкается немного раньше, и чаще всего попадает в обработчик прерывания TX.(там зацикливается). при DCO такого нет.

Я вам уже указал, что USCI отличается от USART в части обработки прерываний.
Цитата(shide_3 @ Dec 4 2013, 16:32) *
в мануале написано:
UCRXIFG and UCRXIE are reset by a
system reset PUC signal or when UCSWRST = 1. UCRXIFG is automatically reset when UCAxRXBUF is
read.

Правильно. В USART прерывание от приемника работает аналогично. Но, как я понял, проблема-то у вас с прерыванием от передатчика USCI! Вот сравните
Для USART
Цитата
UTXIFGx is automatically reset if the interrupt
request is serviced or if a character is written to UxTXBUF.

Для USCI
Цитата
UCTXIFG is
automatically reset if a character is written to UCAxTXBUF.

Отличие состоит в том, что в USART прерывание от передатчика сбрасывается в т.ч. просто при переходе по вектору прерывания передатчика. Это возможно, т.к. вектора прерываний для передатчика и для приемника UART разные. В USCI вектор прерывания расшарен и адрес у него один, поэтому сброс запроса прерывания только по факту перехода на обработку передатчика не работает. Если вы попали в прерывание от передатчика, но передавать уже нечего, то флаг UCTXIFG нужно сбросить "вручную". Либо запретить прерывание от передатчика, чтобы после выхода из прерывания не попасть в него вновь.

Цитата(shide_3 @ Dec 4 2013, 19:54) *
эх. было бы наверное интересно и полезно опробовать заведомо рабочий прожект для подобного кристалла на своем. разумеется, не столь лажовый, как Flashing LED.

У производителя на сайте есть примеры http://www.ti.com/lsds/ti/microcontroller/...tware.page#code
shide_3
Цитата(rezident @ Dec 5 2013, 22:58) *
Либо запретить прерывание от передатчика, чтобы после выхода из прерывания не попасть в него вновь.


у меня на данный момент так и сделано
shide_3
интересно, неужели у всех кто юзал эти мспшники, было все гладко с самого начала? тут же явно проблема характерная, программа затыкается на полпути.. со 149-ми не было подобных проблем
rezident
Цитата(shide_3 @ Dec 10 2013, 19:26) *
интересно, неужели у всех кто юзал эти мспшники, было все гладко с самого начала? тут же явно проблема характерная, программа затыкается на полпути.. со 149-ми не было подобных проблем

В крайнем проекте на MSP430F5438A задействовано три UART и два SPI. Питание батарейное. Работа UART и одного из SPI по перываниям. Писал в виде драйвера для работы с буфером UART (функции: управление буфером - запись/чтение/очистка, (ре)инициализация UART с заданными параметрами, переключение режимов прием/передача/режим энергосбережения, плюс отдельно обработчик прерывания с записью/чтением буфера UART в прерывании). Разбор содержимого буфера был реализован на более высоком уровне. Никаких особых проблем не было.
Проект коммерческий, поэтому код здесь привести не могу.
shide_3
Цитата(rezident @ Dec 10 2013, 18:06) *
В крайнем проекте на MSP430F5438A задействовано три UART и два SPI. Питание батарейное. Работа UART и одного из SPI по перываниям. Писал в виде драйвера для работы с буфером UART (функции: управление буфером - запись/чтение/очистка, (ре)инициализация UART с заданными параметрами, переключение режимов прием/передача/режим энергосбережения, плюс отдельно обработчик прерывания с записью/чтением буфера UART в прерывании). Разбор содержимого буфера был реализован на более высоком уровне. Никаких особых проблем не было.
Проект коммерческий, поэтому код здесь привести не могу.

может код инициализации (PMM, тактирование) вам показать реально?буду благодарен
rezident
Цитата(shide_3 @ Dec 10 2013, 20:48) *
может код инициализации (PMM, тактирование) вам показать реально?буду благодарен

Вместо того, чтобы кромсать исходник (там для вашего примера лишнее) мне было бы проще написать пример инициализации с нуля. Но сейчас под рукой нет отладочной платы в которой этот пример можно проверить. Если только на следующей неделе уже.
Неужели за такое продолжительное время при наличии примеров от производителя у вас до сих пор нет никакого положительного результата? cranky.gif
shide_3
Цитата(rezident @ Dec 14 2013, 19:35) *
Вместо того, чтобы кромсать исходник (там для вашего примера лишнее) мне было бы проще написать пример инициализации с нуля. Но сейчас под рукой нет отладочной платы в которой этот пример можно проверить. Если только на следующей неделе уже.
Неужели за такое продолжительное время при наличии примеров от производителя у вас до сих пор нет никакого положительного результата? cranky.gif

вы знаете, буквально два дня назад все заработало. причина оказалась неожиданной. в общем, у меня есть сектора во флеш-памяти (в code memory) которые используются для хранения уставок. так вот , судорожно пробуя все возможные варианты , я поменял адреса этих секторов в файле линкера, и глюки исчезли. а до этого было что-то непонятное, программа вылетала или зависала в определенном месте, причем незначительное изменение кода сказывалось совсем неоднозначно, иногда полной неработоспособностью... при попытке записи в регистр по модбасу микроконтроллер переставал реагировать вообще на любые запросы...
ну да ладно. вот только как это популярно объяснить? нет ли у Вас точки зрения по этому поводу? пока напрашивается одна мысль - компилятор синтезировал код так, что происходили коллизии между адресами кода программ и памяти данных во флеш.
но как такое вообще возможно? не знаю что еще подумать...
я уже начинал бояться, что это какой-то железячный глюк...
rezident
Цитата(shide_3 @ Dec 15 2013, 01:24) *
у меня есть сектора во флеш-памяти (в code memory) которые используются для хранения уставок. так вот , судорожно пробуя все возможные варианты , я поменял адреса этих секторов в файле линкера, и глюки исчезли.

Покажите как вы объявляете эти сегменты (в xcl-файле или в опциях проекта) и как их используете (декларация в исходнике программы)?
Уставки никак не могут должны располагаться в памяти программы. Для них должен быть выделен отдельный сегмент размером кратный сегменту памяти Flash (512 байт). Это в том случае, если они (уставки) не помещаются в области INFO, которая линкером не используется для размещения исполняемого кода. В противном случае линкер может поместить часть исполняемого кода в тот же сегмент, который стирается при изменении значения уставок. Соответственно при изменении уставок (связанное со стиранием сегмента Flash) программа становится неработоспособной.
shide_3
Цитата(rezident @ Dec 15 2013, 00:02) *
Покажите как вы объявляете эти сегменты (в xcl-файле или в опциях проекта) и как их используете (декларация в исходнике программы)?
Уставки никак не могут должны располагаться в памяти программы. Для них должен быть выделен отдельный сегмент размером кратный сегменту памяти Flash (512 байт). Это в том случае, если они (уставки) не помещаются в области INFO, которая линкером не используется для размещения исполняемого кода. В противном случае линкер может поместить часть исполняемого кода в тот же сегмент, который стирается при изменении значения уставок. Соответственно при изменении уставок (связанное со стиранием сегмента Flash) программа становится неработоспособной.

Да, видимо все из за этого, уставки располагались только в code memory, т.к. код линер-файла я просто перенес из соответствующего файла для 149-го msp. а в том проекте похоже все разместили в памяти программ потому что в 149-м information memory маловата - 2 сектора по 128 байт, в f5437a их хотя-бы четыре, но что делать, если и этого недостаточно? а объявляется в линкере так: -Z(DATA)ADCDATA=7200-73FF, в исходнике-
__no_init Adc_Data Adc @ "ADCDATA"; - таких сегментов в программе шесть. то есть в любом случае не хватит info memory.
и как же тогда в 149-м все работало?
rezident
Цитата(shide_3 @ Dec 16 2013, 23:38) *
а объявляется в линкере так: -Z(DATA)ADCDATA=7200-73FF, в исходнике-
__no_init Adc_Data Adc @ "ADCDATA";

А почему сегмент DATA? Вы же константы размещаете. Нужно в CONST писать

-Z(CONST)ADCDATA=7200-73FF

Кроме того, этот же сегмент нужно исключить из области, предназначенной для размещения кода и прочих констант. Т.е. если у вас для кода были два непрерывных сегмента

-P(CODE)CODE=5C00-FF7F,10000-45BFF //в исходном lnk430f5437a.xcl

то должно стать три

-P(CODE)CODE=5C00-71FF, 7400-FF7F,10000-45BFF //исключаем сегмент 7200-73FF

В самом исходнике я вот так объявлял
Код
//"теневой" сектор, используемый как буфер при модификации внутренней Flash
#pragma dataseg = SHADOW_SECT
__no_init unsigned char h_SHADOW_data[MSP430_FLASH_MAIN_SECT_SZ];
#pragma dataseg = default
#pragma required = h_SHADOW_data

При записи в выделенные мной сегменты Flash я использую указатели.
shide_3
теперь ясно,спасибо! не догадался что можно фрагментировать память кода.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.