preface

Developed a debug different chip class link tool. Specific implementations of different chips have different personnel development implementations. Then there is the possibility that different people will modify a copy of code, which will most likely lead to problems. A new way to do this is to put the specified operations in the same segment. In this way, the implementation of link and the implementation of business logic will be completely separated out.

The realization of the old

First, you need to implement the corresponding handler functions in the business logic, such as the following code.

void xx1_ops(void) {... }Copy the code
void xx2_ops(void) {... }Copy the code

Then in the specific call function by chip->name to distinguish between different chips, and then execute the corresponding function

void run(void) {
	switch (chip->name) {
	case xx1:
		xx1_ops();
		break;
	case xx2:
		xx2_ops();
		break;
	default: braek; }}Copy the code

This way is very suitable and convenient when there are few developers. But with more people, with more kinds of chips. Without adding a chip, you modify the contents of the run function, which can cause indeterminate errors. So a more appropriate approach is needed.

The new implementation

Principle: The most important thing is to find the functional entry to the business logic. So put all function entries in a single memory segment. The run function iterates from start to finish, figuring out which entry to execute. In this way, the chips in run are not identified, and the business logic does not need to modify the run function. This is a good isolation. The following is the code implemented in KEil, which is basically similar in GCC, except for the definition of the segment and the header of the segment. The end of the segment address needs to be specified in the LD file.

struct chip {
    char name[8];
    int ops;
};

#define SECTION		__attribute__((used)) __attribute__((section("Chip")))
#define ADD_OPS(name,ops) 		\
	SECTION const struct chip __chip_ops_##name = {	\
		#name,ops,			\
	}					\
	
extern unsigned int Chip$$Base;
extern unsigned int Chip$$Limit;

struct chip * v;
for(v = (struct chip *)&(Chip$$Base); v < (struct chip *)&(Chip$$Limit) ; v++) { LOG("%s\n",v->name);
}


Copy the code

The SECTION above tells the compiler that I will use this variable, tells the compiler not to optimize it, and places it in the Chip SECTION. And ChipBase is the first address of the memory, ChipBase is the first address of the memory, ChipBase is the first address of the memory, ChipLimit is the last address. You can find the entry of the specified function by traversing the segment address. In terms of business logic, there is no need to care about the underlying implementation of link. After focusing on the implementation of logic, use the following macro transfer function entry.

SC_ADD_CHIP(xxx,12);
Copy the code

It’s all personal. There are mistakes to discuss together