Tôi đang cố gắng tạo ra một RTOS bán sẵn (hợp tác) cho vi điều khiển PIC x16. Trong câu hỏi trước đây của tôi , tôi đã học được rằng việc truy cập con trỏ ngăn xếp phần cứng là không thể trong các lõi này. Tôi đã xem xét này trang trong PIClist, và đây là những gì tôi đang cố gắng thực hiện bằng C.
Trình biên dịch của tôi là Microchip XC8 và hiện tại tôi đang làm việc trên PIC16F616 với bộ dao động RC bên trong 4 MHz được chọn trong các bit cấu hình.
Tôi đã học được rằng tôi có thể truy cập các thanh ghi PCLATH và PCL bằng C, xem tệp tiêu đề của trình biên dịch của tôi. Vì vậy, tôi đã cố gắng thực hiện một trình chuyển đổi tác vụ đơn giản.
Nó hoạt động như mong muốn trong trình gỡ lỗi nếu tôi tạm dừng trình gỡ lỗi sau khi khởi động lại, đặt lại và đặt PC ở con trỏ khi con trỏ không nằm trên dòng đầu tiên ( TRISA=0;
) mà trên một dòng khác (ví dụ ANSEL=0;
). Trong lần khởi động đầu tiên của trình gỡ lỗi, tôi nhận được các thông báo này trong Debugger Console
:
Launching
Programming target
User program running
No source code lines were found at current PC 0x204
Chỉnh sửa: Tôi không biết những gì làm cho nó hoạt động, nhưng trình gỡ lỗi bây giờ hoạt động hoàn hảo. Vì vậy, bỏ qua đầu ra và đoạn văn trên.
Chỉnh sửa: Thay đổi định nghĩa chính như thế này làm cho mã bên dưới hoạt động. Điều này bắt đầu chức năng chính tại địa chỉ chương trình 0x0099
. Tôi không biết điều gì gây ra điều này. Đây không phải là một giải pháp thực sự. Bây giờ tôi đoán rằng có một lỗi cụ thể của trình biên dịch.
void main(void) @ 0x0099
{
Đây là mã C của tôi:
/*
* File: main.c
* Author: abdullah
*
* Created on 10 Haziran 2012 Pazar, 14:43
*/
#include <xc.h> // Include the header file needed by the compiler
__CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & CP_OFF & IOSCFS_4MHZ & BOREN_ON);
/*
* INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
* WDT disabled and can be enabled by SWDTEN bit of the WDTCON register
* PWRT enabled
* MCLR pin function is digital input, MCLR internally tied to VDD
* Program memory code protection is disabled
* Internal Oscillator Frequency Select bit : 4MHz
* Brown-out Reset Selection bits : BOR enabled
*/
/*
* OS_initializeTask(); definition will copy the PCLATH register to the task's PCLATH holder, which is held in taskx.pch
* This will help us hold the PCLATH at the point we yield.
* After that, it will copy the (PCL register + 8) to current task's PCL holder which is held in taskx.pcl.
* 8 is added to PCL because this line plus the "return" takes 8 instructions.
* We will set the PCL after these instructions, because
* we want to be in the point after OS_initializeTask when we come back to this task.
* After all, the function returns without doing anything more. This will initialize the task's PCLATH and PCL.
*/
#define OS_initializeTask(); currentTask->pch = PCLATH;\
currentTask->pcl = PCL + 8;\
asm("return");
/*
* OS_yield(); definition will do the same stuff that OS_initializeTask(); definition do, however
* it will return to "taskswitcher" label, which is the start of OS_runTasks(); definition.
*/
#define OS_yield(); currentTask->pch = PCLATH;\
currentTask->pcl = PCL + 8;\
asm("goto _taskswitcher");
/*
* OS_runTasks(); definition will set the "taskswitcher" label. After that it will change the
* current task to the next task, by pointing the next item in the linked list of "TCB"s.
* After that, it will change the PCLATH and PCL registers with the current task's. That will
* make the program continue the next task from the place it left last time.
*/
#define OS_runTasks(); asm("_taskswitcher");\
currentTask = currentTask -> next;\
PCLATH = currentTask->pch;\
PCL = currentTask->pcl;
typedef struct _TCB // Create task control block and type define it as "TCB"
{
unsigned char pch; // pch register will hold the PCLATH value of the task after the last yield.
unsigned char pcl; // pcl register will hold the PCL value of the task after the last yield.
struct _TCB* next; // This pointer points to the next task. We are creating a linked list.
} TCB;
TCB* currentTask; // This TCB pointer will point to the current task's TCB.
TCB task1; // Define the TCB for task1.
TCB task2; // Define the TCB for task2.
void fTask1(void); // Prototype the function for task1.
void fTask2(void); // Prototype the function for task2.
void main(void)
{
TRISA = 0; // Set all of the PORTA pins as outputs.
ANSEL = 0; // Set all of the analog input pins as digital i/o.
PORTA = 0; // Clear PORTA bits.
currentTask = &task1; // We will point the currentTask pointer to point the first task.
task1.next = &task2; // We will create a ringed linked list as follows:
task2.next = &task1; // task1 -> task2 -> task1 -> task2 ....
/*
* Before running the tasks, we should initialize the PCL and PCLATH registers for the tasks.
* In order to do this, we could have looked up the absolute address with a function pointer.
* However, it seems like this is not possible with this compiler (or all the x16 PICs?)
* What this compiler creates is a table of the addresses of the functions and a bunch of GOTOs.
* This will not let us get the absolute address of the function by doing something like:
* "currentTask->pcl=low(functionpointer);"
*/
fTask1(); // Run task1 so that we get the address of it and initialize pch and pcl registers.
currentTask = currentTask -> next; // Point the currentTask pointer to the next pointer which
fTask2(); // is task2. And run task2 so that we get the correct pch and pcl.
OS_runTasks(); // Task switcher. See the comments in the definitions above.
}
void fTask1(void)
{
OS_initializeTask(); // Initialize the task
while (1)
{
RA0 = ~RA0; // Toggle PORTA.0
OS_yield(); // Yield
RA0 = ~RA0; // Toggle PORTA.0
}
}
void fTask2(void)
{
OS_initializeTask(); // Initialize the task
while (1)
{
RA1 = ~RA1; // Toggle PORTA.1
OS_yield(); // Yield
RA1 = ~RA1; // Toggle PORTA.1
}
}
Và đây là tập tin liệt kê tháo gỡ mà trình biên dịch của tôi tạo ra. Bắt đầu lúc line 74
.
Tôi đã lập trình chip thực tế, và không có thay đổi nào trên PORTA cả; nó không hoạt động.
Lý do chương trình của tôi không hoạt động là gì?