Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: IAR STM8 ошибка линковщика [Li005]
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
den1s
Здравствуй!!! На работе руководством было принято стратегическое решение о переходе на процы STM8 взамен Атмела. Я в свою очередь решил юзать стандартную STMовскую библиотеку. Но в первом же проекте наткнулся на ошибку, которая по-ходу выше моих программерских познаний (см. ниже). Поиск по форуму и гуглу не помогли.
Смысл в следующем: при попытке прикрутить поверх стандартной либы свою библиотеку UART с использованием очереди (или циклического буфера) наткнулся на ошибку линковщика [Li005]. А именно в момент прописывания обработчика прервыния по завершению передачи UART в файле "stm8s_it.c".
Вот выдержки из всех файлов, которые на мой взгляд нужны для помощи мне))):
Файл main.c
Код
#include "main.h"
#include "stm8s.h"
#include "stdio.h"
#include "uart.h"

void main(void)
{
  UART_init();
  UART_SendStr("test");
  while(1);
}

Файл uart.h
Код
#include "stm8s.h"

#define UART_SPEED             115200
#define UART_GPIO_PINS      (GPIO_PIN_6 | GPIO_PIN_5)
#define SIZE_BUF                  256

void UART_init(void);
__monitor void UART_PutChar(uint8_t sym);
void UART_SendStr(uint8_t * data);

Файл uart.c
Код
#include "uart.h"

static volatile uint8_t uartTxBuf[SIZE_BUF];
static uint16_t txBufHead = 0;
static volatile uint16_t txCount = 0;

void UART_init(void)
{
  UART2_DeInit();
  UART2_Init((uint32_t)UART_SPEED, UART2_WORDLENGTH_8D, UART2_STOPBITS_1, UART2_PARITY_NO,
              UART2_SYNCMODE_CLOCK_DISABLE, UART2_MODE_TXRX_ENABLE);
  UART2_ITConfig(UART2_IT_TC, ENABLE);
  UART2_ITConfig(UART2_IT_RXNE_OR, ENABLE);
  enableInterrupts();
}

__monitor void UART_PutChar(uint8_t sym)
{
  if((UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET) && (txCount == 0))
    UART2_SendData8(sym);
  else
  {
    if (txCount < SIZE_BUF)
    {
      uartTxBuf[txBufTail] = sym;
      txCount++;
      txBufTail++;
      txBufTail = txBufTail % SIZE_BUF;
    }
  }
}

void UART_SendStr(uint8_t * data)
{
  uint8_t sym;
  while(*data)
  {
    sym = *data++;
    UART_PutChar(sym);
  }
}

Файл stm8s_it.c
Код
#include "stm8s_it.h"
#include "uart.h"

extern uint8_t uartTxBuf[SIZE_BUF];
extern uint16_t txBufHead;
extern uint16_t txCount;

INTERRUPT_HANDLER(UART2_TX_IRQHandler, 20)
{
   if (txCount > 0)
   {
     UART2_SendData8(uartTxBuf[txBufHead]);
     txCount--;
     txBufHead++;
     if (txBufHead == SIZE_BUF)
       txBufHead = 0;
   }
}

При компиляции IAR выдает следующее:
Код
Error[Li005]: no definition for "txCount" [referenced from F:\SOURSE\SST135\STM8S_StdPeriph_Lib_V2.1.0\Project\STM8S_StdPeriph_Template\EWSTM8\STM8S105\Obj\stm8s_it.o]
Error[Li005]: no definition for "txBufHead" [referenced from F:\SOURSE\SST135\STM8S_StdPeriph_Lib_V2.1.0\Project\STM8S_StdPeriph_Template\EWSTM8\STM8S105\Obj\stm8s_it.o]
Error[Li005]: no definition for "uartTxBuf" [referenced from F:\SOURSE\SST135\STM8S_StdPeriph_Lib_V2.1.0\Project\STM8S_StdPeriph_Template\EWSTM8\STM8S105\Obj\stm8s_it.o]
Errors: 3
Warnings: none

Link time:   0.08 (CPU)   0.10 (elapsed)
Error while running Linker

Total number of errors: 3
Total number of warnings: 0

В общем не нравятся ему переменные в файле stm8s_it.c которые объявлены в файле uart.c хотя я и объявил их как extern.
Что бы не было вопросов "включен ли файл в проект":

IAR 6.1.6.1880 (6.1.6.1880), проц STM8S105
Заранее благодарен.
_Артём_
Цитата(den1s @ Oct 19 2012, 12:59) *
При компиляции IAR выдает следующее:
Error[Li005]: no definition for "txCount" [referenced from F:\SOURSE\SST135\STM8S_StdPeriph_Lib_V2.1.0\Project\STM8S_StdPeriph_Template\EWSTM8\STM8S105\Obj\stm8s_it.o]
Error[Li005]: no definition for "txBufHead" [referenced from F:\SOURSE\SST135\STM8S_StdPeriph_Lib_V2.1.0\Project\STM8S_StdPeriph_Template\EWSTM8\STM8S105\Obj\stm8s_it.o]
Error[Li005]: no definition for "uartTxBuf" [referenced from F:\SOURSE\SST135\STM8S_StdPeriph_Lib_V2.1.0\Project\STM8S_StdPeriph_Template\EWSTM8\STM8S105\Obj\stm8s_it.o]
Errors: 3
Warnings: none

Объявите переменные так:
Код
volatile uint8_t uartTxBuf[SIZE_BUF];
uint16_t txBufHead = 0;
volatile uint16_t txCount = 0;
SSerge
Вы эти переменные в файле uart.c объявили со словом static.
А зря, в результате они за пределами этого файла не видны.
den1s
Цитата(_Артём_ @ Oct 19 2012, 14:16) *
Объявите переменные так:
Код
volatile uint8_t uartTxBuf[SIZE_BUF];
uint16_t txBufHead = 0;
volatile uint16_t txCount = 0;

но это будет неверно как я понимаю, переменные-то должны быть те же самые что и в файле uart.c поэтому я extern и пишу. Или я ошибаюсь?
Цитата(SSerge @ Oct 19 2012, 14:18) *
Вы эти переменные в файле uart.c объявили со словом static.
А зря, в результате они за пределами этого файла не видны.

Согласен, а можно ли какую-нить хитрость применить что бы они static остались? Я эту либу из своей старой AVRовской копипастил, но там-то прерывания описываются в том же файле а не в отдельном.
_Артём_
Цитата(den1s @ Oct 19 2012, 14:31) *
но это будет неверно как я понимаю, переменные-то должны быть те же самые что и в файле
Код
uart.c
поэтому я
Код
extern
и пишу

Чего же неверного?

Это объявление переменных в файле uart.c:
Код
volatile uint8_t uartTxBuf[SIZE_BUF];


Такое объявление (его можно поместить в файл uart.h) позволяет обращатся к uartTxBuf из других файлов:
Код
extern volatile uint8_t uartTxBuf[SIZE_BUF];


А static - запрет обращения (видимости переменной) из других файлов.
Поэтому объявлять uartTxBuf как static в одном файле и обращаться к uartTxBuf из другого файла - несколько странно.
den1s
Цитата(_Артём_ @ Oct 19 2012, 15:41) *
Чего же неверного?

Это объявление переменных в файле uart.c:
Код
volatile uint8_t uartTxBuf[SIZE_BUF];


Такое объявление (его можно поместить в файл uart.h) позволяет обращатся к uartTxBuf из других файлов:
Код
extern volatile uint8_t uartTxBuf[SIZE_BUF];


А static - запрет обращения (видимости переменной) из других файлов.
Поэтому объявлять uartTxBuf как static в одном файле и обращаться к uartTxBuf из другого файла - несколько странно.

про static ясно - мой косяк. А вот на счет extern я всегда считал иначе: запись с extern нужно включать в файл, в котором необходимо использовать переменную из другого файла. Т.е. грубо это означает не то что "переменная доступна в других файлах" а то что она "определена в другом файле". Пример в файле one.c есть переменная int i = 0. Что бы i была доступна в файле two.c нужно имеенно в файле two.c написать extern int i (а не в файле one.c как следует из Вашего поста).
_Артём_
Цитата(den1s @ Oct 19 2012, 15:20) *
А вот на счет extern я всегда считал иначе: запись с extern нужно включать в файл, в котором необходимо использовать переменную из другого файла.

Верно.
Цитата(den1s @ Oct 19 2012, 15:20) *
Т.е. грубо это означает не то что "переменная доступна в других файлах" а то что она "определена в другом файле". Пример в файле one.c есть переменная int i = 0. Что бы i была доступна в файле two.c нужно имеенно в файле two.c написать extern int i (а не в файле one.c как следует из Вашего поста).

А в файле one.c должна быть строка:
Код
int i;// приравнивать к нулю не нужно
MrYuran
Цитата(den1s @ Oct 19 2012, 16:20) *
А вот на счет extern я всегда считал иначе: запись с extern нужно включать в файл, в котором необходимо использовать переменную из другого файла.

Только обычно включают не напрямую, а через хедеры.
То есть, переменные, которые должны быть видны снаружи модуля, выносят в h-файл с квалификатором extern, а в другом модуле просто подключают этот h-файл через #include.
Это хорошо, когда у вас три переменных. А когда их будет по 30 в каждом из 10 модулей, то в этой вермишели запутаетесь напрочь.
den1s
Цитата(MrYuran @ Oct 19 2012, 16:34) *
Только обычно включают не напрямую, а через хедеры.
То есть, переменные, которые должны быть видны снаружи модуля, выносят в h-файл с квалификатором extern, а в другом модуле просто подключают этот h-файл через #include.
Это хорошо, когда у вас три переменных. А когда их будет по 30 в каждом из 10 модулей, то в этой вермишели запутаетесь напрочь.

Согласен, так грамотнее будет.

Раз уж начал)) Подскажите правильно ли я прверяю готовность передатчика UART if(UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET) ? Почему-то у меня это условие не выполняется нифига.

Ладно, спасибо всем ответившим за помощь и за то что чутом подтянули мои знания))). Другие вопросы буду задавать в отдельном топике.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.